Verwenden Sie eine gemeinsame CSS-Datei für LTR- und RTL-Seiten, indem Sie die HTML-Richtung explizit festlegen, logische Eigenschaften für richtungsabhängige Abstände verwenden und zwischen Layoutelementen gap einsetzen. Diese Anleitung erstellt ein lokales Beispiel mit zwei Seiten, die Sie in einem Mac-Browser vergleichen können.

Die Aufgabe besteht darin, dafür zu sorgen, dass dieselbe kleine Komponente ihren vorgesehenen Abstand beibehält, wenn sich ihre Inline-Richtung ändert. Sie benötigen einen einfachen Texteditor und einen aktuellen Desktop-Browser. Das Beispiel verwendet künstliche Beschriftungen und einen dekorativen Kreis, ohne Framework, externe Ressourcen oder JavaScript.

Was soll das gemeinsame Stylesheet steuern?

Überlassen Sie dem HTML die Richtung und dem Stylesheet die Abstände. Beide Seiten laden dieselbe CSS-Ressource und verwenden dieselben Komponentenklassen; das Seitenstamm-Element gibt entweder dir="ltr" oder dir="rtl" vor. HTML definiert rel="stylesheet" als einen Link zu einer externen Ressource, der zur Dokumentgestaltung beiträgt. HTML-Standard: Stylesheet-Links.

Verwenden Sie HTML dir, wenn die Richtung bekannt ist. Nachgeordnete Elemente übernehmen die Richtung im Allgemeinen, und lang legt sie nicht fest. Ziehen Sie für diesen kontrollierten Vergleich eine explizite Richtung gegenüber dir="auto" vor: Die automatische Richtung hängt vom Inhalt ab und würde bei den lateinischen Beispielbeschriftungen LTR wählen. MDN: das Attribut dir.

Entscheidend ist der Unterschied zwischen einer physischen Kante und einer Position im Textfluss. In der Schreibrichtung horizontal-tb dieses Beispiels bedeutet Inline-Anfang bei LTR links und bei RTL rechts. Block-Anfang bleibt oben. Logische Eigenschaften drücken diese Beziehungen direkt aus. MDN: logische Ränder, Rahmen und Innenabstände.

Gewünschter Abstand Gemeinsame CSS-Auswahl Ergebnis bei Richtungsänderung
Abstand innerhalb der führenden Kante der Komponente padding-inline-start Wandert auf die andere physische Seite
Abstand innerhalb beider Inline-Kanten padding-inline Wendet Anfangs- und Endwerte in der neuen Richtung an
Abstand zwischen Flexbox-Elementen gap Behält den festgelegten Abstand zwischen Elementen bei
Abstand oberhalb und unterhalb in diesem horizontalen Layout padding-block Bleibt oberhalb und unterhalb
Ein Rand vor einem Element im Inline-Fluss margin-inline-start Wird der neuen Inline-Anfangsseite zugeordnet

Die Zuordnung von Rand und Innenabstand folgt Schreibrichtung und Richtung des Elements. gap erzeugt stattdessen Abstände in unterstützten Layout-Containern. Das sind getrennte Aufgaben: Verwenden Sie Innenabstand rund um den Inhalt und einen Abstand zwischen benachbarten Elementen. MDN: logische Abstände, MDN: gap.

Zwei lokale Seiten erstellen, die eine CSS-Datei verwenden

Erstellen Sie auf Ihrem Mac einen Ordner namens spacing-demo. Speichern Sie die folgenden Dateien als Klartext mit den exakten Dateiendungen. Vermeiden Sie einen Editor, der .txt an .html oder .css anhängt.

spacing-demo/
  ltr.html
  rtl.html
  components.css

Speichern Sie dieses vollständige HTML-Dokument als ltr.html. Speichern Sie dann eine zweite Kopie als rtl.html und ändern Sie nur das Stammattribut von dir="ltr" zu dir="rtl". Behalten Sie den Stylesheet-Verweis und das Komponenten-Markup unverändert bei. Die Beschriftungen bleiben auf Englisch, da es sich um einen künstlichen Layoutvergleich handelt.

<!doctype html>
<html lang="en" dir="ltr">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Component spacing sample</title>
  <link rel="stylesheet" href="components.css">
</head>
<body>
  <main class="demo">
    <h1>Spacing sample</h1>
    <article class="sample-card">
      <span class="sample-card__shape" aria-hidden="true"></span>
      <div class="sample-card__copy">
        <h2 class="sample-card__title">Module A</h2>
        <p class="sample-card__description">A compact sample tile</p>
      </div>
      <span class="sample-card__tag">Set B</span>
    </article>
  </main>
</body>
</html>

Speichern Sie nun das folgende vollständige Stylesheet als components.css. Der absichtlich ungleiche Inline-Innenabstand macht Richtungsänderungen leicht erkennbar: Der größere Einzug sollte dem Inline-Anfang folgen.

:root {
  --space-small: 8px;
  --space-medium: 16px;
  --space-large: 24px;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 24px;
  font-family: system-ui, sans-serif;
  line-height: 1.5;
  color: #243447;
  background: #f2f5f8;
}

.demo {
  writing-mode: horizontal-tb;
  max-width: 640px;
  margin-inline: auto;
}

.sample-card {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: var(--space-medium);
  padding-block: var(--space-medium);
  padding-inline: var(--space-large) var(--space-small);
  border: 1px solid #8594a5;
  border-radius: 12px;
  background: #ffffff;
}

.sample-card__shape {
  flex: 0 0 32px;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: #5477a3;
}

.sample-card__copy {
  flex: 1 1 0;
  min-width: 0;
  overflow-wrap: anywhere;
}

.sample-card__title,
.sample-card__description {
  margin: 0;
}

.sample-card__title {
  font-size: 18px;
}

.sample-card__description {
  margin-block-start: var(--space-small);
}

.sample-card__tag {
  flex: 0 0 auto;
  padding-block: 4px;
  padding-inline: var(--space-small);
  border: 1px solid #8594a5;
  border-radius: 6px;
}

Hier bedeutet padding-inline: 24px 8px den Innenabstand am Anfang, gefolgt vom Innenabstand am Ende. Es bedeutet nicht links, gefolgt von rechts. Ein einzelner Wert würde auf beide Inline-Kanten angewendet. MDN: padding-inline.

Behalten Sie flex-direction: row auf beiden Seiten bei. Eine Flexbox-Zeile folgt bereits der Richtung ihres Containers: Bei LTR verläuft sie von links nach rechts und bei RTL von rechts nach links. Wenn Sie row-reverse zur RTL-Version hinzufügen, kehren Sie diese Richtung erneut um. MDN: flex-direction.

Der neutrale Kreis hat keine Richtungsbedeutung, daher bleibt seine Darstellung unverändert, während seine Position der Zeile folgt. Auch die lateinischen Beschriftungen behalten ihre Buchstabenreihenfolge bei; dieses Beispiel prüft das Komponentenlayout und nicht übersetzten Text.

Wie prüfen Sie, ob die Abstände tatsächlich gemeinsam verwendet werden?

Öffnen Sie beide HTML-Dateien in Ihrem Mac-Browser und vergleichen Sie sie bei gleicher Fensterbreite. Die folgenden Werte ergeben sich aus den Deklarationen; es handelt sich nicht um gemeldete Browsermessungen. Der Rahmen der Karte ist getrennt von ihrem Innenabstand.

Prüfung LTR-Seite RTL-Seite
Position des Kreises Erstes Element links Erstes Element rechts
Innenabstand links an der Karte 24px 8px
Innenabstand rechts an der Karte 8px 24px
Abstand zwischen benachbarten Flex-Elementen 16px 16px
Innenabstand oben und unten an der Karte 16px 16px
Abstand vor der Beschreibung 8px darüber 8px darüber

Prüfen Sie die gemeinsame Ressource unabhängig von der Richtung. Ändern Sie --space-medium in components.css von 16px auf 20px, speichern Sie die Datei und laden Sie beide Seiten neu. Bei beiden sollte der Abstand zwischen den Elementen und der Block-Innenabstand größer werden, da die Deklarationen dieselbe Variable verwenden. Setzen Sie den Wert nach dem Vergleich auf 16px zurück.

Verkleinern Sie dann das Browserfenster und ersetzen Sie die Beschreibung durch eine längere künstliche Beschriftung, zum Beispiel Module A extended sample description. Prüfen Sie, ob der Text umbricht, ohne den Kreis oder das Tag zu überdecken. Das ist ein zweiter nützlicher Test: Eine Komponente kann sich bei einer Breite korrekt spiegeln und bei einer anderen zu eng werden.

Beurteilen Sie nicht jeden sichtbaren Abstand allein anhand von gap. Elementränder, interne Innenabstände und verteilte Ausrichtung können den sichtbaren Abstand vergrößern. Das Beispiel setzt die Textränder zurück und vermeidet verteilte Ausrichtung, damit der Vergleich gut lesbar bleibt. MDN: Beschreibung von gap.

Wie migrieren Sie eine bestehende Komponente ohne Abstandskonflikte?

Beginnen Sie mit der Bedeutung jeder vorhandenen Deklaration. Ein führender Texteinzug gehört normalerweise zum Inline-Anfang; für eine bewusst festgelegte physische Kante kann weiterhin eine physische Eigenschaft erforderlich sein. Richten Sie die Umstellung an der Designabsicht aus, statt jedes Vorkommen von left mechanisch zu ersetzen.

Gehen Sie bei einer Komponente wie dieser Beispielkomponente folgendermaßen vor:

  1. Bestimmen Sie das übergeordnete Element, das die Richtung vorgibt.
  2. Ersetzen Sie richtungsabhängige Innenabstände durch logische Innenabstände.
  3. Ersetzen Sie bei Bedarf richtungsabhängige Außenabstände durch logische Ränder.
  4. Verwenden Sie gap des übergeordneten Elements für gewöhnliche Abstände zwischen Flex-Elementen und entfernen Sie Ränder, die zuvor denselben Abstand erzeugt haben.
  5. Wiederholen Sie die Vergleiche mit ungleichen Innenabständen und schmalem Fenster in beiden Richtungen.

Achten Sie bei der Umstellung auf alte physische Deklarationen und spätere Kurzschreibweisen. Logische und physische Eigenschaften, die derselben Seite zugeordnet sind, nehmen gemeinsam an der Kaskade teil; eine logische Eigenschaft gewinnt nicht automatisch, weil sie logisch ist. Eine spätere Deklaration von padding kann zuvor über logische Eigenschaften festgelegte Innenabstände zurücksetzen, wenn alle anderen Kaskadenfaktoren gleich sind. CSS Logical Properties and Values Level 1: Box-Model-Eigenschaften.

Beachten Sie auch die Richtungsgrenze. Eine verschachtelte Komponente mit eigenem dir="ltr" sollte selbst innerhalb einer RTL-Seite LTR-Zuordnungen verwenden. Umgekehrt wird margin-inline selbst nicht vererbt. Geben Sie daher jeder Komponente die benötigten Abstandsdeklarationen, statt zu erwarten, dass der Rand eines übergeordneten Elements auf sie übergeht. MDN: Vererbung der Richtung, MDN: formale Definition von margin-inline.

Welche Browser-Einschränkungen beeinflussen diesen Ansatz?

MDN kennzeichnet padding-inline und margin-inline seit April 2021 als breit browserübergreifend verfügbar. Das spricht für ihre Verwendung in aktuellen Desktop-Browsern, ist aber keine Garantie für jeden älteren Browser oder jede neuere Syntax auf den Referenzseiten. Dieses Beispiel verwendet gewöhnliche Längen und auto, keine neueren Größenfunktionen. MDN: padding-inline, MDN: margin-inline.

Flexbox gap hat eine eigene Versionsgeschichte. Safari hat es mit Version 14.1 hinzugefügt; Grid gap wurde bereits seit Safari 12 unterstützt. WebKit weist ausdrücklich darauf hin, dass sich diese Kontexte nicht mit einer Property-Feature-Abfrage unterscheiden ließen. Daher reicht @supports (gap: 16px) allein nicht aus, um die Unterstützung von Flexbox gap in älteren Safari-Versionen zu erkennen. WebKit: Neue WebKit-Funktionen in Safari 14.1.

Wenn Ihr Zielbrowser logische Ränder unterstützt, aber Flexbox gap nicht, fügen Sie dieses Ersatzfragment nach den Hauptregeln des Stylesheets ein. Es stellt Abstände für diese spezielle Komponente mit einer einzelnen Zeile bereit. Verwenden Sie es wie gezeigt anstelle des aktiven gap-Abstands; für Zeilenumbrüche ist es keine allgemeine Lösung.

/* Optional single-row replacement for Flexbox gap. */
.sample-card {
  gap: 0;
}

.sample-card > * + * {
  margin-inline-start: var(--space-medium);
}

Für Browser, denen auch logische Eigenschaften fehlen, reicht dieser Fallback nicht aus. Verwenden Sie für die lokale Aufgabe einen aktuellen Browser oder erstellen und testen Sie für das ältere Ziel explizite physische Regeln für LTR und RTL. Treffen Sie diese browserspezifische Entscheidung unabhängig vom Hauptentwurf des gemeinsamen Stylesheets.

Der abgeschlossene Vergleich sollte einen einheitlichen Vertrag zeigen: Das HTML gibt die Richtung vor, das gemeinsame CSS legt die Abstände fest und der führende Einzug der Komponente folgt dem Inline-Anfang. Bewahren Sie die beiden lokalen Seiten als kompakte Regressionstestvorlage auf, wenn Sie Abstände oder Layout der Komponente ändern.

Quellen