Firefox unter Linux – Cache reaktivieren nach Update auf Quantum

In bestimmten Testphasen von Weblösungen stelle ich mit Hilfe von Add-Ons oder auch über die in FF integrierten Developer-Tools öfter den Cache meines Lieblingsbrowsers Browsers ab. Im alten Firefox (etwa der unter Opensuse Leap 42.3 ausgelieferten FF-Version 52.8 ESR) gab es im Add-On "Web Developer" lange Zeit eine Möglichkeit zum dauerhaften Ab- und Anstellen des FF-Caches. Diese Möglichkeit bietet selbiges Add-On unter Quantum nicht mehr.

Bei einem Update auf Firefox Quantum unter Linux hatte sich die vorher gewählte Einstellung zur Deaktivierung des Caches im alten Firefox (Vers. 52.8, ESR) aber irgendwie verselbständigt:

Nach dem Update auf Quantum wurden keine Dateien mehr aus dem Cache gezogen - die Netzanalyse in den FF-eigenen Entwicklertools zeigte ein permanentes Nachladen aller Seitenelemente an. Das führt beim Wechseln zwischen den Seiten einer Web-Site, bei denen größere Hintergrundsbilder angezeigt werden, typischerweise zu spürbaren Verzögerungen und ggf. zu Flacker-Effekten. An diesen Effekten haben wir gemerkt, dass etwas nicht mehr stimmte.

Eigentlich wäre das auch OK - schließlich hatte ich die Einstellung ja selbst gewählt.
Irritierend ist aber, dass man in keinem Entwicklertool irgendwo eine Information zum dauerhaft deaktivierten Cache sehen würde. Mit den in FF integrierten Entwickler-Tools (unter dem Menü "Extras >> Web-Entwickler ..." findet man etwa im Bereich der "Netzwerkanalyse" eine Möglichkeit, den Cache temporär ab- und wieder anzuschalten. Eine Abschaltung für den gesamten Zeitraum, in dem man die Entwickler-Toolpalette nutzt, bietet auch der dortige Punkt "Werkzeugkasten-Einstellungen". Diese Einstellungen sind aber sitespezifisch wie temporär und verschwinden spätestens mit dem Schließen des FF-Developer-Werkzeugkastens.

Leider zeigten die genannten Werkzeuge nach dem Update auf Quantum nicht an, dass der Cache deaktiviert war. War er aber. Wegen der Einstellmöglichkeiten und der zuletzt getroffenen Wahl unter der alten FF-Version.

Die Behebung dieses Problems ist einfach, wenn man weiß, wo man zu suchen hat:

Man öffne die URL "about:config". Dort gibt man dann im Suchfeld den String "browser.cache.*.enable" ein. In meinem Fall ergab die Suche 5 verschiedene Einstell-Optionen:

browser.cache.disk.enable - browser.cache.disk.smart_size.enabled - browser.cache.memory.enable - browser.cache.offline.enable - browser.cache.offline.insecure.enable

Bei mir waren die Werte für "browser.cache.disk.enable" und "browser.cache.memory.enable" leider auf "false" gesetzt. Man stelle diese Werte auf "true" um - und schon funktioniert der FF-Cache wieder!

Für das temporäre Abschalten nutzt man die Optionen im FF-eigenen Entwickler-Werkzeugkasten. Mir reicht diese Möglichkeit zum temporären Abschalten in der Regel für das Testen von Webseiten.

Leider gibt es hier unter Quantum wohl noch Bugs: Die Kuchendiagramme des Punktes "Netzwerkanalyse starten" weisen bei vielen Seiten aus meiner Sicht fehlerhafterweise nicht aus, was unter Nutzung des Caches passieren würde. Angezeigt wird dort für bestimmte Sites "Antworten aus dem Cache:0". Obwohl die reguläre Darstellung der Downloadzeiten für die Seitenelemente mittels "Balkendiagrammen" die Nutzung des Caches mit korrekten Werten ausweist.

Dennoch viel Spaß weiterhin mit FF.

Apache Rewrite für zwei Domänen, die gemeinsame Datei-Ressourcen nutzen

Gestern wurden wir mit zwei Websites konfrontiert, die wir um einen Blog ergänzen sollten. Die Webserver-Installation, die wir vorfanden, war interessant und hat uns ein wenig beschäftigt:

Zwei Domain-Namen (alpha.de und beta.de) waren beim Hosting-Provider mit ein und demselben Webserver-Verzeichnis verbunden. Dieses wiederum wies zwei Unterverzeichnisse auf, in denen sich vor allem HTML-Seiten zu den verschiedenen Domänen befanden. Die Idee hinter diesem Setup war wohl, von den Webseiten beider Domänen aus gemeinsame Datei-Ressourcen im Hauptverzeichnis zu nutzen.

Setup zur Nutzung gemeinsamer Datei-Ressourcen durch zwei Web-Domänen auf demselben Webserver

Nennen wir das Hauptverzeichnis mal dir_domains und die Subverzeichnisse dir_alpha und dir_beta.

Die Webseiten von alpha.de und beta.de nutzen gleiche Datei-Ressourcen (CSS-Dateien, Javascripts, PHP-Programme, ...). Entsprechende Verzeichnisse fanden sich unter dir_domains:

dir_domains (Webserververzeichnis für Domains alpha/beta)
|__css
|__js
|__php
|__index.php
| ....
|
|__dir_alpha
|        |__index.html
|        |...(HTML-Dateien für die Domäne beta.de)
|        | ....
|__dir_beta
         |__index.html
         |... (HTML-Dateien für die Domäne beta.de)
         |...

Die Datei index.php übernahm die Zugangssteuerung für die Startseiten: Je nach Domain-Anforderung (alpha.de oder beta.de) des Users wurde dieser auf die jeweilige Index-Seite unter dir_alpha oder dir_beta umgelenkt. So weit, so gut - oder eher so schlecht ....

Nach Inaugenscheinnahme der beiden Domänen im Internet war mir klar, warum das so aufgesetzt worden war:

Die Webseiten unter alpha.de bzw. beta.de haben einen ganz ähnlichen Aufbau und nutzen gleiche PHP-Programme und Scripts. Da bei der Anforderung von Ressourcen wie CSS-/JS-/PHP-Dateien Domaingrenzen in der Verzeichnisstruktur des Web-Servers normalerweise nicht überschritten werden dürfen, waren die Web-Designer gezwungen gewesen, beiden Domänen dasselbe Hauptverzeichnis des gehosteten Webserver-Accounts zuzuweisen. Zur Kompensation musste eine Art Umlenkung auf die jeweiligen Verzeichnisstrukturen integriert werden. (Anmerkung am Rande: Die Domängrenzen, im Sinne von Verzeichnisgrenzen, gelten übrigens nicht für Include-Dateien, die in PHP-Programmen nachgeladen werden. Solche Include-Dateien kann man ruhig oberhalb des Domainverzeichnisses unterbringen!).

Was war am Setup schlecht?

Während die Nutzung gemeinsamer Ressourcen durchaus zu befürworten ist, war die "Umlenkung" durch das PHP-Skript schlecht gelöst. Sie funktionierte eigentlich nur für den Aufruf einer der beiden Domän-Namen selbst (Umlenkung auf die jeweilige index.html-Seiten). Die Navigation innerhalb der Webseiten einer Domäne war über relative Pfade gelöst; sobald ein User sich einmal innerhalb einer Domäne bewegte, funktionierte deshalb alles aus Nutzersicht alles bestens.

Aber: Der Aufruf einer spezifischen Seite einer Domäne über eine direkte Eingabe in die Adresszeile des Browsers - z.B. http://alpha.de/infos/impressum.html - funktionierte mit dem vorhandenen PHP-Script nicht. Das Script index.php kümmerte sich nur um die Index-Seiten der Domänen. Es wurde als Index-Datei ja nur dann aktiv, wenn eine der Domän-Adressen alpha.de oder beta.de ohne weitere Zusätze im Browser aufgerufen wurde.

Lösungsansatz über Apache Rewrite

Bei dem gehosteten Webserver handelte es sich um einen Apache-Server. Eine saubere Lösung für den gewünschten Setup-Ansatz mit geteilten Datei-Ressourcen besteht dann natürlich darin, das Apache Rewrite-Modul (mod_rewrite) zu nutzen. Die Servereinstellungen beim Provider waren so, dass die Rewrite Engine über lokale ".htaccess"-Dateien aktiviert und gesteuert werden konnte. Wir haben dann folgenden einfachen Vorschlag umgesetzt:

Inhalt der .htaccess-Datei für das Verzeichnis dir_domains:

Options +FollowSymLinks 
RewriteEngine On 
RewriteBase /

RewriteRule ^alpha/(.*)$ - [L]
RewriteRule ^beta/(.*)$ - [L]

RewriteRule ^css/(.*)$ - [L]
RewriteRule ^images/(.*)$ - [L]
RewriteRule ^php/(.*)$ - [L]
RewriteRule ^script/(.*)$ - [L]

RewriteCond %{SERVER_NAME} alpha.de [OR]
RewriteCond %{SERVER_NAME} www.alpha.de
RewriteRule ^$ alpha/index.html [L]

RewriteCond %{SERVER_NAME} alpha.de [OR]
RewriteCond %{SERVER_NAME} www.alpha.de
RewriteRule ^(.*)$ alpha/$1 [NC,L]

RewriteCond %{SERVER_NAME} beta.de [OR]
RewriteCond %{SERVER_NAME} www.beta.de
RewriteRule ^$ beta/index.html [L]

RewriteCond %{SERVER_NAME} beta.de [OR]
RewriteCond %{SERVER_NAME} www.beta.de
RewriteRule ^(.*)$ beta/$1 [NC,L]

 
Die ersten 2 Rewrite-Regeln sorgen dafür, dass keine Umlenkung mehr vorgenommen wird, wenn man sich bereits im Verzeichnisbereich der Seite befindet. Dieser Vorspann ist wichtiger, als man meinen möchte: die nachfolgenden Regeln würden für sich allein zu einer unbegrenzten Iteration von Rewrites führen!

Die nächsten 4 Regeln sorgen dann dafür, dass Verweise auf die gemeinsam genutzten Ressourcen-Verzeichnisse und zugehörige GET-Anforderungen an den Server unangetastet bleiben. Diese Verzeichnisse werden ja aus dem HTML-Code der Webseiten unter dem alpha- bzw. dem beta-Sub-Verzeichnis referenziert; z.B. über relative Pfade.

Danach kommen die eigentlichen Umlenkungsregeln. Wir haben hier die Grundregel befolgt, dass eine oder mehrere Rewrite Conditions sich nur und ausschließlich auf die nächste Rewrite Rule beziehen - also auf genau eine Rewrite Rule! Das wird in der hektik oft übersehen; es gibt keine native Klammerung mehrerer Rewrite Rules zu Rewrite Conditions. Allerdings kann man mit Negationen der Bedingungen und Skip-Zusätzen hinter den Rewrite-Regeln tricksen. Um das Verständnis nicht zu erschweren, haben wir hier auf solche Hacks verzichtet.

Wird keine Dateiname angegeben - ist also der Pfad hinter dem Domain-Anteil leer - wird auf die jeweilige Index-Seite umgelenkt. Sind konkrete Webseiten einer Domäne angefordert, wird auf die gewünschte Datei im jeweiligen Unterverzeichnis verwiesen.

Das war es schon; die Datei index.php kann und sollte danach gelöscht werden. Unser Kunde kann nun 2 Domänen im gleichen Webserververzeichnis nutzen und zwischen beiden Implementierungen gemeinsame Ressourcen teilen. Eigentlich eine nette kleine Geschichte, die ich vielleicht auch mal für eigene Sites nutzen werde - Apache sei Dank!

Vertical gaps resulting from nested inline block elements inside DIV containers – II – getting control

In the first article of this mini series

Vertical gaps resulting from nested inline block elements inside DIV containers – I

we have seen that under certain circumstances (nested) inline-blocks may lead to vertical gaps between themselves and/or between their lower border and the lower bottom of surrounding DIV containers. (Others may describe it as an unexected spacing or margin). We tried to explain this behavior:

If no other precisely defined height scale is given the (min-) height of the innermost inline element - in our case an inline block - will be interpreted as if a letter of a corresponding font-size were present. We have shown that the baseline for letters indeed is set to the bottom of the innermost inline block if no (relatively positioned) contents of the innermost inline block is given.

In this article we want to play around with our example to get an improved understanding and to find options to control and eliminate the vertical gaps. Our example code is:

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Test</title>
<style type="text/css">
	
	html {
		font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
		font-size: 10px;
	}
	
	div {
		position:relative;
		margin:0;
		padding:0;
	}
	
	div.header {
		float:left; 
		min-width: 30.0rem; 
		min-height: 3.2rem; 
		background-color: #DDDDDD;
	}
	
	div.hornav {
		width: auto; 
		min-height: 3.0rem;
		line-height: 3.0rem;
		border: #F00 0.1rem solid;
		background-color: black; 
		text-align: center; 
		
	}
	
	div.hornav_txt {
		display:inline-block; 
		min-width: 20.0rem;  
		min-height:2.8rem;
		line-height: 2.8rem;
		border: solid 0.1rem #FF0; 
		background-color: #FFF;
		text-align:center; 
		
	}
	
	div.mp_cont {
		display:inline-block; 
		min-width:10.0rem; 
		min-height:2.6rem;
		line-height:2.6rem; 
		border:solid 0.1rem #090;
		background-color:#F00; 
		
	}
	
	div.bg{
		position: absolute; 
		min-width:10.0rem; 
		min-height:2.6rem;
		top:0;
		bottom:0;
		left:0;
		right:0;
		border:0;
		background-color:#FF0;
		opacity: 0.5;
		z-index:1;  
	}
	
	div.fg {
		position: absolute; 
		min-width:10.0rem; 
		min-height:2.6rem;
		line-height:2.6rem; 
		border:0;
		z-index:2;
	}
	
</style>
</head>

<body>
        <div class="header">
            <div class="hornav">
                <div class="hornav_txt">
                	<div class="mp_cont">
                		<div class="bg"></div>
                		<div class="fg"></div>
                	</div>
             	</div>
            </div>
        </div> 
        <div class="header" style="margin-left:50px;">
            <div class="hornav">
                <div class="hornav_txt">
                	<div class="mp_cont">
                		<div class="bg"></div>
                		<div class="fg"></div>
                	</div><span style="font-size:2.8rem; ">XÜj</span>jjgg
             	</div><span style="color:yellow;">jg</span>
            </div>
        </div>
        <p style="clear:left;" ></p>
</body>
</html>

Test 1 - line-height reduction for the inline-blocks

If our explanation of the gap occurrence has some truth in it we should see an effect when we reduce the line-height for the inline-blocks in their containers.
So, let us first try the following:

        <div class="header">
            <div class="hornav">
                <div class="hornav_txt" style="line-height:0;">
                	<div class="mp_cont">
                		<div class="bg"></div>
                		<div class="fg"></div>
                	</div>
             	</div>
           </div>
        </div> 

 
Now, our innermost inline-block element div.mp_cont gets no line-height in its container, but it still has a min-height. The result is:

nested_inline_blocks_5

Not quite, what we wanted. At least div.mp_cont shrank to the expected height. But, still, there is no defined inline-block height available and the browser still does not know what to do about the inline element div.hornav. Hence the vertical gap between div.hornav_txt and div.hornav.

Now, we go a step further and repeat our approach one tag-level higher:

        <div class="header">
            <div class="hornav" style="line-height:0;>
                <div class="hornav_txt" style="line-height:0;">
                	<div class="mp_cont">
                		<div class="bg"></div>
                		<div class="fg"></div>
                	</div>
             	</div>
            </div>
        </div>
 

 
We get:

nested_inline_blocks_6

Yes! Now, we have at least found a remedy in case that we need to control the height for inline boxes with empty or absolutely positioned contents. Let us keep this option of line-height reduction in mind!

Test 2 - provide some relatively positioned contents in the innermost inline block

If our gap theory is valid we should provide an innermost inline content with a defined height to get a reasonable vertical adjustment in the end. To achieve this for our example we have to perform 2 steps:

  1. Set the CSS value of "position" for the innermost block element div.fg to "relative" instead of "absolute".
  2. Put some inline text into div.fg

With the first step we fulfill an objective that we already discussed in our first article:

The innermost contents shall control the height expansion of all containers in a dynamical, flexible way. This is especially important for responsive layouts and CMS systems.

So, lets do the following:

        <div class="header">
            <div class="hornav">
                <div class="hornav_txt">
                	<div class="mp_cont">
                		<div class="bg"></div>
                		<div class="fg" style="position:relative;"></div>
                	</div>
             	</div>
            </div>
        </div> 

 
Note that we eliminated the setting "line-heigt:0;" again. We get:

nested_inline_blocks_7
 
A bit frustrating, isn't it? We gained nothing compared with our original example. But our finding is still consistent with our theory - we still have no defined height of an innermost inline element.

So, now let us look at a small wonder of CSS: We just add a text element - a tiny harmless letter
"x" -

        <div class="header">
            <div class="hornav">
                <div class="hornav_txt">
                	<div class="mp_cont">
                		<div class="bg"></div>
                		<div class="fg" style="position:relative;">x</div>
                	</div>
             	</div>
            </div>
        </div>
 

 
and, hey, everything gets fixed in the sense of our original expectations.

nested_inline_blocks_8

Intermediate Summary

If we had started with the very reasonable setting of our last test we would never have noted any problem in our example. So, why all the fuss?

One reason is that there are a lot of articles on the Internet about uncontrollable vertical gaps related to inline block elements. Actually these gaps are understandable and controllable.

The other reason is that in templates (e.g. for CMS systems) the (future) contents of inline-blocks may not be known - and the inline block elements may intentionally be left empty. Then we would run into the described situation of our example. The use of nested inline blocks on the other side makes horizontal centering easy if the width of the innermost contents is not really known.

Two options to get control over the gaps
Now, we have seen 2 remedies that can be applied to avoid gaps between (nested) inline blocks and their containers:

  • Set the line-height in each of the container of an inline-block to zero or a sufficiently small value. (But be careful - this may have an impact on other elements on the same HTML/DOM hierarchy level.)
  • Provide an innermost inline (text) element with a defined height (e.g. given by a font-size). This innermost element may be a "&nbsp;". Ensure that the innermost inline element can have an impact on outer containers via relative (!) positioning.

Of course, you may/must in some situations also combine these options.

Note: The use of a "&nbsp;" may be helpful for (PHP) templates as a dummy contents. Just replace this dummy text during the creation of the real page by real contents - eg. the text of a real menu point.

What about <P>-tags with different font-sizes as the innermost tags?

Ok, up to now we used plain text inside the div.fg-container. What happens when we use

-tags and change the font sizes for these tags? Well, then it may get pretty weird:

A <p> may actually create vertical gaps again - despite the fact there is enough space for it inside its block container div.fg. One of the reasons is that browsers add their own bit of white space to a <p>. This can be controlled by margin- and padding-settings. However, in our case of a a <p> inside inline-blocks even a "margin-top:0; margin-bottom:0;" does not help.

See the following example:

       
	<div class="header" style="margin-left:50px;">
            <div class="hornav">
                <div class="hornav_txt" >
                    <div class="mp_cont" >
                        <div class="bg"></div>
                        <div class="fg">
                            <p style="font-size:1.4rem; margin-top:0rem; margin-bottom:0rem;">Ügj</p>
                        </div>
                    </div>
             	</div>
            </div>
        </div>

 
nested_inline_blocks_9

There is again (!) a small but clearly visible gap at the lower bottom. The inline text-element inside the <p>-tag affects the next inline-block element despite the fact that we have defined normal block element with sufficient vertical space in between. The gap gets bigger with the font-size. See the same example for "font-size:1.6rem;":

nested_inline_blocks_10

For real CSS2/3 experts this may not be too surprising; for me it was.

So, how can we correct this effect? And what do we have to do, when the font-size of the encapsulated

-tag really exceeds the height and line-height of the surrounding container?

The answers are given in the following final code for our example:

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Test</title>
<style type="text/css">
	
	html {
		font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
		font-size: 10px;
	}
	
	div {
		position:relative;
		margin:0;
		padding:0;
	}
	
	div.header {
		float:left; 
		min-width: 30.0rem; 
		min-height: 3.2rem; 
		background-color: #DDDDDD;
	}
	
	div.hornav {
		width: auto; 
		min-height: 3.0rem;
		line-height: 0rem;
		border: #F00 0.1rem solid;
		background-color: black; 
		text-align: center; 
		margin:0; 
		padding:0;
	}
	
	div.hornav_txt {
		display:inline-block; 
		position:relative; 
		min-width: 20.0rem;  
		min-height:2.8rem;
		line-height: 0rem;
		border: solid 0.1rem #FF0; 
		background-color: #FFF;
		text-align:center; 
		margin:0; 
		padding:0;
	}
	
	div.mp_cont {
		display:inline-block; 
		position: relative; 
		min-width:10.0rem; 
		min-height:2.6rem;
		line-height: 2.6rem; 
		border:solid 0.1rem #090;
		background-color:#F00;
		margin:0; 
		padding:0;
	}
	
	div.bg{
		position: absolute; 
		min-width:10.0rem; 
		/* line below not required */
		/*min-height:2.6rem;*/
		top:0;
		bottom:0;
		left:0;
		right:0;
		border:0;
		background-color:#FF0;
		opacity: 0.5;
		z-index:1;  
	}
	
	div.fg {
		position:relative; 
		min-width:10.0rem; 
		min-height:2.6rem;
		line-height:2.6rem; 
		border:transparent 0.0rem solid;
		padding:0;
		margin:0;
		z-index:2;
	}
	
</style>
</head>

<body>
        <div class="header">
            <div class="hornav">
                <div class="hornav_txt">
                	<div class="mp_cont">
                		<div class="bg"></div>
                		<div class="fg"> </div>
                	</div>
             	</div>
	    </div>
        </div> 
       <div class="header" style="margin-left:50px;">
            <div class="hornav">
                <div class="hornav_txt" >
                	<div class="mp_cont" >
                		<div class="bg"></div>
                		<div class="fg"><p style="font-size:1.8rem; margin-top:0rem; margin-bottom:0rem;">Ügj</p></div>
		  	</div>
                </div>
	    </div>
        </div>
        <p style="clear:left;"></p>
        <div class="header" style="margin-left:0px; margin-top:50px;">
            <div class="hornav">
                <div class="hornav_txt" >
                	<div class="mp_cont" >
                		<div class="bg"></div>
                		<div class="fg" style="line-height: normal;"><p style="font-size:5.0rem; margin-top:0.6rem; margin-bottom:0.6rem;">Ügj</p></div>
                	</div>
             	</div>
            </div>
        </div>
        <div class="header" style="margin-left:50px; margin-top:50px;">
            <div class="hornav">
                <div class="hornav_txt" >
                	<div class="mp_cont" >
                		<div class="bg"></div>
                		<div class="fg" style="line-height:normal;"><p style="font-size:5.0rem; margin-top:0.6rem; margin-bottom:0.6rem;">Ügj<br>Ügj</p></div>
                	</div>
             	</div>
            </div>
        </div>
        <p style="clear:left;"></p>
        <div class="header" style="margin-left:50px; margin-top:50px; min-width: 50.0rem; ">
            <div class="hornav">
                <div class="hornav_txt" >
                	<div class="mp_cont" >
                		<div class="bg"></div>
                		<div class="fg" style="line-height:normal; padding-left:1.0rem; padding-right:1.0rem;"><p style="font-size:5.0rem; margin-top:0.6rem; margin-bottom:0.6rem;">Hallo Hallo<br>Hallo Hallo Ügj</p></div>
                	</div>
             	</div>
            </div>
        </div>
</body>
</html>

 
What did we change ?

The first thing you may note is that in the CSS definitions we used our first trick:
We explicitly set the line-heights for div.hornav and div.hornav_txt to zero.

The second important point is that when the font gets too large we must adjust the line-height for the container div.fg. We use "line-height:normal;" to adjust the line-height to the height of the included contents.

So, in case you should build a CMS in which the user can choose font-sizes by himself this is something you have to take care about. You may provide a standard setting; but if in situations like in our example case the font size of a <P>-tag exceeds defined limits our page creation program has to modify style settings explicitly to guarantee a flexible height adjustment.

The result is shown in following picture:

nested_inline_blocks_12

This gives us exactly what we wanted:

  • Easy horizontal centering via the use of (nested) inline block elements (even if the content length gets bigger than some threshold).
  • Vertical flexibility - even if we work with font-sizes bigger than a threshold.
  • NO VERTICAL GAPS between (nested) containers of inline-block elements.

It is easy to see how we can use the discussed elements in templates to create horizontally centered menus with menu points for which the horizontal and vertical size is not known.

CSS is a bit weird sometimes - but fun, too!