Gerrit: horizontaler Außenabstand von inline-block Elementen

Hallo,

ich habe gerade ein doofes Problem und kommen beim besten Willen nicht auf die Lösung.

Folgende HTML-Seite

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0;" />
		<title>zusammenfallende Margins</title>
		<style>
			#inline1, #inline2 {
				display: inline-block;
				height: 100px;
				width: 100px;
				background: #ccc;
				margin: 0;
				padding: 0;
				border: 0;
			}
			#inline1 {
				margin-right: 20px;
			}
			#inline2 {
				margin-left: -20px;
			}
		</style>
	</head>
	<body>
			<div id="inline1">Inline 1</div>
			<div id="inline2">Inline 2</div>
	</body>
</html>

erzeugt zwischen den DIV-Boxen einen verbleibenden 4px breiten "Restabstand". Warum? (Wenn ich bspw. das 2. Element floate, fällt der Abstand komplett weg, und beide grenzen wie erwartet aneinander).

Kann mir bitte jemand helfen? Das wäre großartig! Gruß, Gerrit

  1. Hey,

       <div id="inline1">Inline 1</div>
       <div id="inline2">Inline 2</div>
    

    erzeugt zwischen den DIV-Boxen einen verbleibenden 4px breiten "Restabstand". Warum? (Wenn ich bspw. das 2. Element floate, fällt der Abstand komplett weg, und beide grenzen wie erwartet aneinander).

    Bei einem Online-Beispiel hätte ich mehr Lust zu experimentieren, daher werfe ich mal einen Blick in meine Glaskugel:
    Ich tippe auf die Tatsache, dass du zwischen den beiden div's Whitespace hast. Da mehrere Leerzeichen genauso gut sind wie ein einziges erzeugst du damit unwillentlich einen Abstand.

    Reinhard

    1. Hallo Reihnard,

      vielen Dank für Deine schnelle und absolut richtige Antwort! Das whitespace war in diesem Fall der Linebreak zwischen den Inline-Elementen und ist mir wegen der Verwendung der DIVs einfach nicht aufgefallen.

         <div id="inline1">Inline 1</div>
         <div id="inline2">Inline 2</div>
      

      Manchmal sieht man halt den Wald vor lauter Bäumen nicht... Schönen Abend noch, Gruß

      Gerrit

  2. hi,

    Warum?

    Weil du display: inline-block setzt. Und weil da line-breaks und Leerstellen zwischen deinen inline1, inline2 sind. Es geht also bei den Lösungsansätzen darum diese Leerstellen und Linebreaks weg zu bekommen.

    Den genauen Grund, WARUM Browser das so rendern und den Abstand nicht einfach wegmachen kenne ich leider auch nicht.

    Lösungsansätze:

    • font-size des Elternelementes auf 0 des setzen und innerhalb der Kind-Elemente (inline1, inline2) wiederherstellen.

    In deinem Fall ist das Elternelemnet <body>, weshalb du gut daran tust um inline1, inline2 einen Wrapper zu setzen, da du sonst allen Elemente im body font-size 0 zuweist.

    • negative margins verwenden. margin-right: -4px. Davon ist eher abzuraten, aber es funktioniert.

    • word-spacing der Elemente inline1, inline2 auf 0, oder -1 setzen. Kann mich jetzt nicht mehr genau erinnern, ob das jetzt 0, oder -1 war ...

    • die Leerstellen und Zeilenumbrüche zwischen den Elementen inline1, inline2 entfernen.

    so:

    <div id="inline1">Inline 1</div><div id="inline2">Inline 2</div>
    

    oder so:

    <div id="inline1">Inline 1</div><!--
    --><div id="inline2">Inline 2</div>
    

    oder ...

    Sicher gibt es auch noch andere Möglichkeiten. Ich persönlich verwende die Lösung mit "font-size:0", oder ich entferne die Leerstellen mit Kommentaren. Solltest du vor haben irgendwo letter-spacing zu verwenden, so musst du auch das auf 0 setzen.

    lg mark

    1. Hallo mark,

      Den genauen Grund, WARUM Browser das so rendern und den Abstand nicht einfach wegmachen kenne ich leider auch nicht.

      Inline-block verhält sich nach außen wie inline. Deshalb. Oder würdest du erwarten, dass Zeilenumbrüche zwischen inline-Elementen oder innerhalb eines Elements entfernt werden?

      <p>Peter
      und der
      Wolf</p>
      

      wird „Peter und der Wolf“ und nicht „Peterund derWolf“.

      Bis demnächst
      Matthias

      --
      Das Geheimnis des Könnens liegt im Wollen. (Giuseppe Mazzini)
    2. @@mark

      Lösungsansätze:

      Ich hab die mal in einem Pen skizziert.

      Nachtrag: Die darin verwendeten Inline-style-Attribute sollen zur Verdeutlichung dienen. In Produktivcode sollten Darstellungsangaben natürlich nicht inline stehen, sondern im Stylesheet.

      Screenshot:

      Screenshot des Ergebnisses verschiedener Methoden

      • font-size des Elternelementes auf 0 des setzen und innerhalb der Kind-Elemente (inline1, inline2) wiederherstellen.

      Das Problem dabei ist, dass sich Schriftgröße der Kindelemente nicht einfach auf die ihres Großelternelements wiederherstellen lässt; weder em noch inherit kann man verwenden, da sich dies ja auf die 0 beziehen würde.

      Einzig rem bleibt (nein, px etc. ist keine Alternative); das bezieht sich aber nicht auf das Großelternelement. In meinem Beispiel wird das Problem deutlich; die Schriftgröße ist zu klein.

      Außerdem wird rem von alten Browsern nicht unterstützt. In dem Fall möchte man die Schriftgröße nicht auf 0 setzen. Also wenn diese Methode, dann font-size: 0rem.

      • negative margins verwenden. margin-right: -4px. Davon ist eher abzuraten, aber es funktioniert.

      Tut es nicht, siehe Beispiel. Du meinst: Davon ist eher abzuraten, weil es nicht funktioniert.

      Weder die beim Nutzer verwendete Schriftart noch deren Schriftgröße ist bekannt. Demzufolge kann man nicht wissen, wie breit genau ein Leerzeichen wirklich ist. 4px ist eine magic number; die gilt es immer zu vermeiden.

      Auch em hilft hier nicht weiter. Und eine Einheit, die sich auf die Breite des Leerzeichens der jeweiligen Schrift bezieht, gibt es nicht.

      • word-spacing der Elemente inline1, inline2 auf 0, oder -1 setzen. Kann mich jetzt nicht mehr genau erinnern, ob das jetzt 0, oder -1 war ...

      Weder noch. Sondern eine Längenangabe für die Breite des Leerzeichens (und zwar nicht für die Inline-Block-Elemente, sondern das Elternelement). Dasselbe Problem wie bei negativen margins, also auch nicht brauchbar.

      • die Leerstellen und Zeilenumbrüche zwischen den Elementen inline1, inline2 entfernen.

      Die Darstellung von der Formatierung des Codes abhängig zu machen, ist keine so gute Idee. Ein anderer Entwickler (oder das eigene Ich, das sich zu einem späteren Zeitpunkt nicht mehr daran erinnert, warum der Code so missgestaltet ist) mag den Code lesbar machen und Zeilenumbrüche einfügen bzw. Kommentare löschen. Ersteres könnte auch ein HTML-Linter tun, letzteres ein HTML-Minifier.

      oder ...

      Die sinnvolle Lösung verwenden: Flexbox!

      (Das in meinem Beispiel zusätzliche div-Element ist nur der Tabelle geschuldet. Normalerweise wird das Elternelement keine Tabellenzelle, sondern ein Blockelement (oder ein Inline(-Block)-Element) sein, dem man display: flex (bzw. inline-flex) verpassen kann.)

      LLAP 🖖

      --
      „Wir haben deinen numidischen Schreiber aufgegriffen, o Syndicus.“
      „Hat auf dem Forum herumgelungert …“
      (Wachen in Asterix 36: Der Papyrus des Cäsar)
      1. Die sinnvolle Lösung verwenden: Flexbox!

        Nur um Klugzuscheißen: Das ist nicht die Lösung des Problems des TO, der display: inline-block verwendet. Da kannst du ihm auch gleich raten, die elemente zu floaten.

        Außerdem wird rem von alten Browsern nicht unterstützt.

        Der Browsersupport von rem ist besser (relativ und absolut), als der von flexbox. So what?

        Tut es nicht, siehe Beispiel. Du meinst: Davon ist eher abzuraten, weil es nicht funktioniert.

        Es funktioniert sehr wohl. In deinem Beispiel sind's halt -6px anstatt -4px. Magic Numbers sollte man eben im Griff haben :)

        lg

        mark

        1. @@mark

          Die sinnvolle Lösung verwenden: Flexbox! Nur um Klugzuscheißen: Das ist nicht die Lösung des Problems des TO, der display: inline-block verwendet.

          Das Problem ist, Boxen nebeneinander ohne Zwischenraum darzustellen. Genau das lässt sich mit Flexbox lösen.

          Da kannst du ihm auch gleich raten, die elemente zu floaten.

          Nein, das Problem ist nicht, ein Element um ein anderes herumfließen zu lassen.

          Außerdem wird rem von alten Browsern nicht unterstützt. Der Browsersupport von rem ist besser (relativ und absolut), als der von flexbox. So what?

          Progressive enhancement. Wenn in alten Browsern doch ein Zwischenraum ist, so what?

          Mit Flexbox macht man in alten Bowsern nichts kaputt. Mit font-size: 0 schon; deshalb mein Hinweis auf 0rem.

          Es funktioniert sehr wohl. In deinem Beispiel sind's halt -6px anstatt -4px. Magic Numbers sollte man eben im Griff haben :)

          Das Entscheidende in diesem Absatz war der Smiley. Ich lachte. Ansonsten hätte ich laut „Bullshit“ gerufen.

          LLAP 🖖

          --
          „Wir haben deinen numidischen Schreiber aufgegriffen, o Syndicus.“
          „Hat auf dem Forum herumgelungert …“
          (Wachen in Asterix 36: Der Papyrus des Cäsar)
    3. Vielen Dank Euch allen für Eure ausführlichen Antworten!

      In meinem Beispiel reicht die Lösung des Nacheinandernotierens der DIVs bzw. die Nullsetzung der Schriftgröße (ich setze dann immer auch die Line-Height auf 0) völlig aus. (Auch, wenn dies sicher nicht die besten Lösungen sind...)

      Viele Grüße Gerrit