Es gibt einige neue Funktionen in CSS, die uns beim einfachen Erstellen von Layouts für verschiedene Richtungen und Sprachen unterstützen können. Dieser Artikel handelt von CSS-Logikeigenschaften und -werten (z. B. margin-inline-start). Diese sind ein W3C-Arbeitsentwurf, der sich noch in starker Bearbeitung befindet, aber in vielen Browsern bereits unterstützt wird. Ich möchte darüber sprechen, weil ich diese Eigenschaften seit einiger Zeit verwende und nach der Umstellung auf sie eine deutliche Verbesserung meines Arbeitsablaufs festgestellt habe.
Ich werde auf die Spezifikationen eingehen und wie Sie sie heute in Ihrer Arbeit nutzen können. Ich lebe in Ägypten, wo wir Arabisch als Hauptsprache verwenden. Arabisch wird von rechts nach links geschrieben, was bedeutet, dass arabische Websites wie ein Spiegelbild einer englischen Version aussehen. Die meisten Websites, die wir erstellen, sind zweisprachig, was bedeutet, dass wir für jede Richtung ein eigenes Stylesheet bereitstellen. Das tun wir, indem wir Werte und Eigenschaften von fast allem umdrehen! Ich werde nicht im Detail darauf eingehen, aber Sie können sich einen schnellen Überblick über einen früheren Artikel verschaffen, den ich zu diesem Thema geschrieben habe.
Es beginnt mit der Deklaration des `dir`-Attributs im HTML-Tag.
<html dir="rtl">
Dieses Attribut akzeptiert einen von zwei Werten: `ltr` (was der Standardwert ist, wenn keiner angegeben ist) und `rtl`. Entsprechend seinem Wert beginnt der Browser, die Elemente nach einem bestimmten Algorithmus zu malen. Text wird unter Berücksichtigung der Richtung geschrieben und Satzzeichen werden an ihrer richtigen Stelle platziert. Einige Elemente, wie Tabellen, werden ihre Richtung ändern (zum Beispiel beginnt eine <td> in rtl von rechts). Glücklicherweise folgen einige neue Spezifikationen, wie CSS Grid und Flexbox, einem ähnlichen Ansatz wie die Tabelle. Das bedeutet, dass wir die Reihenfolge von nichts ändern müssen, da der Browser sich darum kümmert!
HTML5 führte einen neuen Wert `auto` für das `dir`-Attribut ein. Es prüft das erste Zeichen innerhalb des Elements und, wenn es zu einer Sprache gehört, die von links nach rechts geschrieben wird (wie lateinische Zeichen), hat das Element eine `ltr`-Richtung und umgekehrt. Das W3C rät den Autoren, sich nicht auf diesen Wert zu verlassen, um die Textrichtung zu bestimmen, und stattdessen eine serverseitige Lösung zu verwenden.
Ein interessanter Anwendungsfall für den `auto`-Wert ist, wenn Sie sich über die Richtung des Inhalts nicht sicher sind, wie z. B. benutzergenerierte Inhalte in einem Kommentar-Thread. Ich sehe viele Leute, die in arabischen Foren auf Englisch zu Diskussionen beitragen. Die Unterstützung für `auto` ist ziemlich gut, außer bei Internet Explorer und Edge.
Einführung der :dir()-Pseudoklasse
Die Pseudoklasse :dir() ist ein neuer Selektormodifikator, der ein Element basierend auf seinem Richtungswert auswählt. Sie funktioniert so
/* Select all paragraphs that have their direction value set to rtl */
p:dir(rtl) {
font-size: 16px; /* Sometimes Arabic glyphs need a size boost to feel right. */
}
/* Select all paragraphs that have their direction value set to ltr */
p:dir(ltr) {
font-size: 14px;
}
Dieser Selektor wählt das Element aus, wenn seine Richtung direkt gesetzt ist oder den automatisch gesetzten Wert mit auto auswertet. Er wird das Element trotzdem korrekt basierend auf seinem Inhalt auswählen!
<style>
p:dir(ltr) {
background: green;
}
p:dir(rtl) {
background: red;
}
</style>
<!-- The following paragraph will have a green background -->
<p dir="auto">This is a paragraph that starts with a latin character</p>
<!-- The following paragraph will have a red background -->
<p dir="auto">هذا النص يستخدم حروف عربية</p>
Leider ist die Unterstützung für :dir() nicht großartig und auf Firefox beschränkt.
Diese Browser-Supportdaten stammen von Caniuse, das mehr Details bietet. Eine Zahl zeigt an, dass der Browser die Funktion ab dieser Version unterstützt.
Desktop
| Chrome | Firefox | IE | Edge | Safari |
|---|---|---|---|---|
| 120 | 17* | Nein | 120 | 16.4 |
Mobil / Tablet
| Android Chrome | Android Firefox | Android | iOS Safari |
|---|---|---|---|
| 127 | 127 | 127 | 16.4 |
Selbst wenn die Browserunterstützung großartig wäre, erlaubt der Selektor nur, Elemente anzusprechen und ihnen manuell bestimmte Stile zuzuweisen. Das bedeutet, dass wir immer noch die Werte für alles (wie Ränder, Abstände, Floats, Positionen usw.) umdrehen müssen, was unseren Arbeitsablauf nicht wirklich verbessert oder den Aufwand für mehrdirektionale Layouts reduziert.
Einführung von CSS-Logikeigenschaften und -werten
Wie vom W3C definiert, bieten uns Logikeigenschaften und -werte die Möglichkeit, das Layout über logische statt über physische Richtungs- und Dimensionszuordnungen zu steuern. Überspringen wir den technischen Jargon und springen direkt zu den Details. Diese bieten uns neue Eigenschaften und Werte, die sich je nach bestimmten Bedingungen unterschiedlich auswerten.
Logische Werte
Nehmen wir an, wir haben einen Absatz, den wir in einer Richtung ausrichten möchten, die der natürlichen Richtung der Sprache entgegengesetzt ist. Nehmen wir an, dies ist auf Englisch, das der `ltr`-Richtung folgt. Wir würden etwas wie dieses tun
<article>
<p class="opposite">
Lorem ipsum dolor sit amis ..
</p>
</article>
Und die CSS-Datei würde so aussehen
.opposite {
text-align: right;
}
Um das Gegenteil für die `rtl`-Version bereitzustellen, würden wir den Selektor überschreiben, indem wir das `<html>`-Tag mit dem `dir`-Attribut ansprechen, oder einfach eine andere Datei für die `rtl`-Version bereitstellen, wie hier
html[dir="rtl"] .opposite {
text-align : left;
}
Logische Eigenschaften und Werte wurden geschaffen, um dieses Problem zu lösen. Warum verwenden wir keine Werte, die sich in den richtigen Kontext auswerten, anstatt links und rechts zu verwenden? In einem `ltr`-Element bedeutet der Wert `left` den Anfang oder den Start des Elements, während in einem `rtl`-Element der Wert `right` den Start bedeutet! Ganz einfach, oder?
Anstatt dessen, was wir vorher geschrieben haben, können wir also verwenden
.opposite {
text-align: end;
}
Und das war's! Wenn die berechnete Richtung des Elements `ltr` ist, wird der Text rechts ausgerichtet; und die berechnete Richtung ist für die `rtl`-Elemente entgegengesetzt. Anstatt also `left`- und `right`-Werte für `text-align` zu verwenden, können wir sie einfach durch `start` und `end` ersetzen. Das ist viel einfacher und bequemer als unsere bisherigen Optionen.
Logische Eigenschaften
Was wir gerade betrachtet haben, waren logische *Werte*, wenden wir uns nun den logischen *Eigenschaften* zu. Logische Eigenschaften sind neue Eigenschaften, die die gleiche Idee verfolgen; sie werten sich je nach Richtung des Elements unterschiedlich aus. Betrachten wir zum Beispiel den Rand. Zuvor wollten wir etwas Abstand zum Anfang des Absatzes hinzufügen. Das können wir im `ltr`-Dokument tun, indem wir
article img {
margin-left: 15px;
}
Nun müssen wir im Falle der `rtl`-Version den Rand in die entgegengesetzte Richtung hinzufügen, zusätzlich zum Zurücksetzen des linken Wertes
html[dir="rtl"] article img {
margin-left: 0;
margin-right: 15px;
}
Mit logischen Eigenschaften können wir es besser machen. Betrachten Sie Folgendes
article img {
margin-inline-start: 15px;
}
Der Teil `-inline-start` wertet den Anfang der horizontalen Achse des Bildes aus. Im Fall von `ltr` bedeutet das links, und im Fall von `rtl` bedeutet das rechts.
Die Begriffe `start` und `end` sind wahrscheinlich inzwischen klar, aber was ist mit dem Wort `inline` und warum brauchen wir es? Um das zu verstehen, müssen wir über etwas namens **CSS-Schreibmodi** sprechen. Jen Simmons hat einen ausgezeichneten Artikel zu diesem Thema geschrieben. Ich werde nicht alles wiederholen, was dort erklärt wird, aber die Quintessenz ist, dass wir Schreibmodi verwenden können, um die Schreibrichtung zu definieren. Manche Sprachen, wie Chinesisch, Koreanisch und Japanisch, können vertikal von oben nach unten geschrieben werden. CSS-Schreibmodi ermöglichen es uns, *diesen* Fluss zu steuern. Betrachten Sie den folgenden Absatz

Sie können die oberen, unteren, linken und rechten Kanten des Blocks klar identifizieren. Was passiert, wenn wir die Richtung des Absatzes mithilfe von CSS-Schreibmodi vertikal fließen lassen?

Wenn wir vom "Oben" dieses gedrehten Absatzes sprechen, meinen wir damit den Anfang des Inhalts oder was war die rechte Kante, als er nicht gedreht war? Die Identifizierung der vier Richtungen wird verwirrend. Betrachten wir sie aus einer anderen Perspektive. Unter "normalen" Schreibbedingungen hat die vertikale Achse das Suffix `-block` und die horizontale Achse hat das Suffix `-inline`, beide gefolgt von `start` oder `end`

Und wenn wir es drehen, sollte es so aussehen

Da wir uns mit normalem horizontalem Layout beschäftigen, werden wir `-inline-start` und `-inline-end` verwenden, aber es ist gut, auch von den anderen Eigenschaften zu wissen. Wir können auch logische Kurzwerte schreiben, indem wir das logische Schlüsselwort verwenden. Betrachten Sie Folgendes
article img {
margin: logical 10px 20px 30px 40px;
}
Der berechnete Wert des Rands des Bildes wird folgender sein
article img {
margin-block-start: 10px;
margin-inline-start: 20px;
margin-block-end: 30px;
margin-inline-end: 40px;
}
Das Schlüsselwort `logical` ist derzeit eine experimentelle Funktion, was bedeutet, dass es sich ändern oder durch die offizielle Spezifikation ersetzt werden könnte. Es gibt eine offene Diskussion zu diesem Thema, der Sie in der Zwischenzeit folgen können.
Logische Eigenschaften ermöglichen es uns auch, Werte auf eine bestimmte Achse anzuwenden, was bedeutet, dass wir `margin-inline` und `margin-block` für die horizontale bzw. vertikale Achse haben.
| Eigenschaft | Logische Eigenschaft |
|---|---|
margin-top | margin-block-start |
margin-left | margin-inline-start |
margin-right | margin-inline-end |
margin-bottom | margin-block-end |
Genau wie bei den logischen Rand-Eigenschaften haben wir auch logische Padding-Eigenschaften, die denselben Regeln wie die Ränder folgen.
| Eigenschaft | Logische Eigenschaft |
|---|---|
padding-top | padding-block-start |
padding-left | padding-inline-start |
padding-right | padding-inline-end |
padding-bottom | padding-block-end |
Logische Positionierungseigenschaften
In den vorherigen Beispielen konnten wir die Bedeutung der Eigenschaft durch Anhängen von Suffixen ändern, aber was ist mit den Positionen? Die Eigenschaftsnamen haben sich vollständig von dem geändert, was wir jetzt als top, right, bottom und left kennen.
.element {
position: absolute;
inset-block-start: 0; /* evaluates to top */
inset-block-end: 0; /* evaluates to bottom */
inset-inline-start: 0; /* evaluates to left in ltr and right in rtl */
inset-inline-end: 0; /* evaluates to right in ltr and left in rtl */
}
Das Erlernen neuer Eigenschaften und Werte kann schwierig sein, aber hey, wir bekommen eine Kurzschreib-Eigenschaft namens inset, um es etwas einfacher zu machen
/* Shorthand FTW! */
.element {
position: absolute;
inset: logical 10px 20px 30px 40px;
}
/* It evaluates to this */
.element {
position: absolute;
inset-block-start: 10px;
inset-inline-start: 20px;
inset-block-end: 30px;
inset-inline-end: 40px;
}
inset unterstützt sowohl inset-block als auch inset-inline, genau wie `margin` und `padding`.
| Eigenschaft | Logische Eigenschaft |
|---|---|
top | inset-block-start |
left | inset-inline-start |
right | inset-inline-end |
bottom | inset-block-end |
Logische Bordüre-Eigenschaften
Bordüre-Eigenschaften können auch logisch werden, indem ` -inline-start` und `-block-start` angehängt werden.
| Eigenschaft | Logische Eigenschaft |
|---|---|
border-top{-size|style|color} | border-block-start{-size|style|color} |
border-left{-size|style|color} | border-inline-start{-size|style|color} |
border-right{-size|style|color} | border-inline-end{-size|style|color} |
border-bottom{-size|style|color} | border-block-end{-size|style|color} |
In ihrem Deep Dive zu logischen Eigenschaften und Werten enthält Rachel Andrew eine ausgezeichnete Demo, die logische Bordüre-Eigenschaften und deren Reaktion auf verschiedene Schreibmodi zeigt.
Wie können wir damit heute beginnen?
Dank der Leistungsfähigkeit von PostCSS können wir die ganze Magie der logischen Eigenschaften und Werte ab heute nutzen! Jonathan Neal hat dieses schöne PostCSS-Plugin geschrieben, das es uns ermöglicht, logisch zu schreiben und den Code in etwas zu kompilieren, das die Browser von heute verstehen. Das Plugin funktioniert in drei Phasen
- Es übersetzt die neue Syntax in bestehende Standards, die von Browsern, die sie nicht unterstützen, erkannt werden, und verwendet die Pseudoklasse
:dir, um Ausgaben für `ltr` und `rtl` zu erstellen. - Es verwendet ein weiteres Plugin von Neal, um
:dirin einen Attributselektor zu übersetzen, wie hier
.element:dir(ltr) {
...
}
[dir="ltr"] .element {
...
}
- Es verwendet das Plugin postcss-nested, um verschachtelte Selektoren in einzeilige Selektoren zu transformieren, so wie es auch andere CSS-Präprozessoren tun.
PostCSS funktioniert mit jedem Workflow. Sie können es mit Grunt, Gulp und webpack ausprobieren.
Ich schließe mit der Aussage, dass ich seit der Umstellung auf logische Eigenschaften und Werte viele Vorteile gesehen habe. Sicher, der Aufbau von mehrdirektionalen Layouts erfordert Zeit. Es gibt die Lernkurve, die zusätzliche Anzahl von zu schreibenden Eigenschaften und natürlich das Testen. Unsere bisherigen Methoden zur Erstellung mehrdirektionaler Layouts beinhalteten entweder die gleichzeitige Berücksichtigung beider Richtungen in der Entwicklung oder die Arbeit an einer Richtung nach der anderen – beides ist für große Projekte nicht gerade ideal. Mit logischen Eigenschaften und Werten schreiben Sie Ihren Code einmal, und er funktioniert für beide Richtungen ohne Rücksicht.
Referenzen
- CSS-Schreibmodi von Jen Simmons
- Verständnis von logischen Eigenschaften und Werten von Rachel Andrew
- PostCSS Logische Eigenschaften und Werte von Jonathan Neal
- Mehrsprachige Layouts im Jahr 2017 auf Arabisch von mir (Folien)
Bezüglich der Pseudoklasse
:dir()haben Sie geschrieben: "…Ob die Richtung des Elements vom HTML dir-Attribut geerbt wurde oder mithilfe von CSS gesetzt wurde, wie z. B. html:lang("ar") { direction: rtl; }, wählt der Selektor das Element aus."Laut W3C stimmt das nicht.
Hier sagt W3C dazu: "Die :dir()-Pseudoklasse wählt nicht basierend auf stilistischen Zuständen aus – zum Beispiel beeinflusst die CSS-direction-Eigenschaft nicht, ob sie übereinstimmt."
Nach weiteren Untersuchungen habe ich festgestellt, dass Sie Recht haben
Der erste Absatz wird vom
rtl-Selektor nicht ausgewählt. Ich glaube, ich habe die Wirkung desauto-Wertes mit diesem Punkt verwechselt. Ich werde es korrigieren, dankeIch habe vor ein paar Monaten eine Übersicht über CSS-Logikeigenschaften geschrieben und festgestellt, dass eine Visualisierung für meine Kunden und einige meiner Kollegen gut zu funktionieren schien...
Was denken Sie über diesen Tweet zur Behandlung mehrsprachiger Websites, die mehrere Sprachen im selben Layout enthalten?
Das Hauptproblem, das ich sehe, ist, dass Sie die Zahlen niemals in der arabischen Schrift anzeigen können. Es wird immer die erste Schriftart verwendet.
Vielen DANK, Ahmad, das ist genau das, wovon ich "geträumt" habe, als ich danach gegoogelt habe!
Ich brauche das PostCSS-Plugin im Jahr 2022 (dieser Artikel wurde 2020 geschrieben) nicht einmal mehr, da laut caniuse.com die Browserunterstützung für logische Eigenschaften in allen großen Browsern hervorragend ist.
Auch hier sind die logischen Eigenschaften für border-radius für zukünftige Leser