Layout-Steuerung auf einer multidirektionalen Website

Avatar of Alaa Abd El-Rahim
Alaa Abd El-Rahim am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Viele geschäftliche Websites benötigen eine mehrsprachige Einrichtung. Wie bei allem entwicklungsbezogenen ist es wünschenswert, diese auf einfache, effiziente und wartungsfreundliche Weise zu implementieren. Die Gestaltung und Entwicklung für mehrere Sprachen, sei es sofort nach dem Start oder zu einem beliebigen Zeitpunkt in der Zukunft, ist intelligent.

Das Ändern der Sprache und des Inhalts ist der einfache Teil. Aber wenn Sie das tun, hat die Sprache, zu der Sie wechseln, manchmal eine andere *Richtung*. Zum Beispiel fließt Text (und damit das Layout) in Englisch von links nach rechts, während Text (und damit das Layout) in Arabisch von rechts nach links fließt.

In diesem Artikel möchte ich eine mehrsprachige Landingpage erstellen und einige CSS-Techniken vorstellen, die diesen Prozess erleichtern. Hoffentlich haben Sie beim nächsten Mal, wenn Sie dasselbe tun müssen, einige Implementierungstechniken, auf die Sie zurückgreifen können.

Wir werden sechs Hauptpunkte behandeln. Ich glaube, dass die ersten fünf unkompliziert sind. Der sechste Punkt enthält mehrere Optionen, über die Sie zuerst nachdenken müssen.

1. Beginnen Sie mit dem HTML-Markup

Die Attribute lang und dir definieren die Sprache und Richtung der Seite.

<!-- English, left-to-right -->
<html lang="en" dir="ltr">

<!-- Arabic, right-to-left -->
<html lang="ar" dir="rtl">

Dann können wir diese Attribute in Selektoren verwenden, um das Styling durchzuführen. Die Attribute lang und dir befinden sich auf dem HTML-Tag *oder* auf einem bestimmten Element, bei dem die Sprache von der übrigen Seite abweicht. Diese Attribute helfen, die SEO der Website zu verbessern, indem die Website in der richtigen Sprache für Benutzer angezeigt wird, die danach suchen, falls jede Sprache ein separates HTML-Dokument hat.

Außerdem müssen wir sicherstellen, dass das charset-Meta-Tag enthalten ist und sein Wert UTF-8 ist, da dies die einzige gültige Kodierung für HTML-Dokumente ist, die auch alle Sprachen unterstützt.

<meta charset="utf-8">

Ich habe zu Demonstrationszwecken eine Landingpage in drei verschiedenen Sprachen vorbereitet. Sie enthält das benötigte HTML, CSS und JavaScript.

2. CSS Custom Properties sind Ihr Freund

Das Ändern der Richtung kann zum Umkehren einiger Eigenschaften führen. Wenn Sie also die CSS-Eigenschaft left in einem Layout von links nach rechts verwendet haben, benötigen Sie wahrscheinlich right in einem Layout von rechts nach links und so weiter. Und das Ändern der Sprache kann zum Ändern von Schriftfamilien, Schriftgrößen usw. führen.

Diese mehrfachen Änderungen können zu unsauberem und schwer zu wartendem Code führen. Stattdessen können wir den Wert einer Custom Property zuweisen und dann den Wert bei Bedarf ändern. Dies ist auch großartig für Responsivität und andere Dinge, die eine Umschaltung erfordern könnten, wie z. B. den Dunkelmodus. Wir können font-size, margin, padding, Farben usw. im Handumdrehen ändern, wobei die Werte dann kaskadieren, wo immer sie benötigt werden.

Hier sind einige der CSS Custom Properties, die wir in diesem Beispiel verwenden

html {
  /* colors */
  --dark-color: #161616;
  --light-color: #eee;
  --primary-text-color: var(--dark-color);
  --primary-bg-color: #fff;
  --shadow-color: var(--light-color);
  --hero-bg-gradient: linear-gradient(90deg, #30333f, #161616, #161616);

  /* font sizes */
  --logo-font-size: 2rem;
  --lang-switcher-font-size: 1.02em;
  --offers-item-after-font-size: 1.5rem;

  /* margin and padding */
  --btn-padding: 7px;
  --sec-padding-block: 120px;

  /* height and width */
  --hero-height: 500px;
  --cta-img-width: 45.75%;
}

Beim Styling unserer Seite können wir einige dieser Custom Properties hinzufügen/ändern, und das ist ganz natürlich. Obwohl sich dieser Artikel mit multidirektionalen Websites beschäftigt, hier ist ein kurzes Beispiel, das zeigt, wie wir Custom Property-Werte neu zuweisen können, indem wir einen Satz von Werten auf dem <body> haben und dann einen anderen Satz, wenn der <body> eine .dark Klasse enthält

body {
  background-color: var(--primary-bg-color);
  color: var(--primary-text-color);
}
body.dark {
  --primary-bg-color: #0f0f0f;
  --primary-text-color: var(--light-color);

  /* other changes */
  --shadow-color: #13151a;
  --hero-bg-gradient: linear-gradient(90deg, #191b20, #131313, #131313);
}

Das ist die allgemeine Idee. Wir werden Custom Properties auf ähnliche Weise verwenden, aber zur Änderung von Sprachrichtungen.

3) CSS Pseudo-Klassen und Selektoren

CSS hat einige Funktionen, die beim Schreiben von Richtungen helfen. Die folgenden beiden Pseudo-Klassen und Attribute sind gute Beispiele, die wir in diesem Beispiel nutzen können.

Die :lang() Pseudo-Klasse

Wir können die :lang() Pseudo-Klasse verwenden, um bestimmte Sprachen anzusprechen und ihnen individuell oder gemeinsam CSS-Eigenschaftswerte zuzuweisen. Zum Beispiel können wir in diesem Beispiel die Schriftgröße ändern, wenn die :lang Pseudo-Klasse entweder auf Arabisch oder Japanisch wechselt

html:lang(ar),
html:lang(jp){
  --offers-item-after-font-size: 1.2rem; 
}

Sobald wir das tun, müssen wir auch die Eigenschaft writing-mode von ihrer standardmäßigen horizontalen Links-nach-rechts-Richtung auf eine vertikale Rechts-nach-links-Richtung umstellen

html:lang(jp) .about__text {
  writing-mode: vertical-rl;
}

Die :attr() Pseudo-Klasse

Die :attr() Pseudo-Klasse macht den "Inhalt" von Pseudo-Elementen wie ::before oder ::after in gewissem Sinne "dynamisch", da wir das dir HTML-Attribut mit der attr() Funktion in die CSS content Eigenschaft einfügen können. Auf diese Weise bestimmt der Wert von dir, was wir auswählen und stylen.

<div dir="ltr"></div>
<div dir="rtl"></div>
div::after {
  content: attr(dir);
}

Die Stärke liegt in der Fähigkeit, jedes benutzerdefinierte Datenattribut zu verwenden. Hier verwenden wir ein benutzerdefiniertes data-name Attribut, dessen Wert in CSS verwendet wird

<div data-name="English content" dir="ltr"></div>
<div data-name="محتوى عربي" dir="rtl"></div>
div::after {
  content: attr(data-name);
}

Dies macht es relativ einfach, den Inhalt nach dem Wechsel der Sprache zu ändern, ohne den Stil zu ändern. Aber zurück zu unserem Design. Das Drei-Karten-Raster hat neben einem Bild eine gelbe "Special" oder "Best"-Markierung.

Das ist das HTML für jede Karte

<div class="offers__item relative" data-attr="data-offer" data-i18n_attr="special_offer">
  <figure class="offers__item_img">
    <img src="./assets/images/offer1.png" data-attr="alt" data-i18n_attr="image_alt" alt="" class="w-100">
  </figure>
  <div class="offer-content_item-text">
    <p class="para" data-i18n="offer_item_text"></p>
    <span class="price bolder" data-i18n="offer_item_price"></span>
  </div>
</div>

Die Rolle von JavaScript ist es,

  1. Ein Attribut namens data-offer auf jeder Karte zu setzen.
  2. Einen Wert "special offer" oder "best offer" zuzuweisen.

Schließlich können wir das data-offer Attribut in unserem Stil verwenden

.offers__item::after {
  content: attr(data-offer);
  /* etc. */
}

Auswahl nach dem dir Attribut

Viele Sprachen sind von links nach rechts, aber einige nicht. Wir können festlegen, was sich in [dir='rtl'] unterscheiden soll. Dieses Attribut muss auf dem Element selbst vorhanden sein oder wir können Verschachtelung verwenden, um das gewünschte Element zu erreichen. Da wir das dir Attribut bereits zu unserem HTML Tag hinzugefügt haben, können wir es in der Verschachtelung verwenden. Wir werden es später auf unserer Beispielseite verwenden.

4. Vorbereiten der Web-Schriften

In einer mehrsprachigen Website möchten wir vielleicht auch die Schriftfamilie zwischen den Sprachen ändern, da eine bestimmte Schrift für eine bestimmte Sprache besser lesbar ist.

Fallback-Schriften

Wir können von der Fallback-Funktion profitieren, indem wir die Rechts-nach-links-Schrift nach der Standard-Schrift schreiben.

font-family: 'Roboto', 'Tajawal', sans-serif;

Dies hilft in Fällen, in denen die Standard-Schrift keine Rechts-nach-links-Unterstützung hat. Der obige Ausschnitt verwendet die Roboto-Schrift, die keine arabischen Buchstaben unterstützt. Wenn die Standard-Schrift Rechts-nach-links unterstützt (wie die Cairo-Schrift) und das Design sie ändern muss, ist dies keine perfekte Lösung.

font-family: 'Cairo', 'Tajawal', sans-serif; /* won't work as expected */

Schauen wir uns eine andere Methode an.

Verwendung von CSS-Variablen und der :lang() Pseudo-Klasse

Wir können die beiden vorherigen Techniken kombinieren, bei denen wir den font-family Eigenschaftswert mit Custom Properties ändern, die durch die :lang Pseudo-Klasse neu zugewiesen werden.

html {
  --font-family: 'Roboto', sans-serif;
}

html:lang(ar){
  --font-family: 'Tajawal', sans-serif;
}

html:lang(jp){
  --font-family: 'Noto Sans JP', sans-serif;
}

5. CSS Logical Properties

In früheren CSS-Zeiten haben wir left und right verwendet, um Offsets entlang der x-Achse zu definieren, und die Eigenschaften top und bottom, um Offsets entlang der y-Achse zu definieren. Das macht die Richtungsänderung zu einer Kopfschmerzursache. Glücklicherweise unterstützt CSS logische Eigenschaften, die richtungsrelative Entsprechungen der älteren physischen Eigenschaften definieren. Sie unterstützen Dinge wie Positionierung, Ausrichtung, Abstände, Polsterung, Rahmen usw.

Wenn der Schreibmodus horizontal ist (wie Englisch), dann ist die logische inline-Richtung entlang der x-Achse und die block-Richtung bezieht sich auf die y-Achse. Diese Richtungen sind in einem vertikalen Schreibmodus umgekehrt, wo inline die y-Achse entlangläuft und block entlang der x-Achse fließt.

Schreibmodusx-Achsey-Achse
horizontalinlineblock
vertikal blockinline

Mit anderen Worten, die block-Dimension ist die Richtung senkrecht zum Schreibmodus und die inline-Dimension ist die Richtung parallel zum Schreibmodus. Sowohl inline- als auch block-Ebenen haben start- und end-Werte, um eine spezifische Richtung zu definieren. Zum Beispiel können wir margin-inline-start anstelle von margin-left verwenden. Das bedeutet, dass sich die Randrichtung automatisch umkehrt, wenn die Seitenrichtung rtl ist. Es ist, als ob unser CSS richtungsbewusst ist und sich bei Kontextwechseln anpasst.

Es gibt einen weiteren Artikel auf CSS-Tricks, Building Multi-Directional Layouts von Ahmad El-Alfy, der auf die Nützlichkeit der Erstellung von Websites in mehreren Sprachen mit logischen Eigenschaften eingeht.

Genau so können wir Abstände, Polsterung und Ränder handhaben. Wir werden sie im Footer-Bereich verwenden, um zu ändern, welcher Rand die abgerundete Kante hat.

Die obere rechte Kante des Rahmens ist in einem standardmäßigen ltr-Schreibmodus abgerundet.

Solange wir das logische Äquivalent von border-top-right-radius verwenden, wird CSS diese Änderung für uns handhaben.

.footer {
  border-start-end-radius: 120px;
}

Nach dem Wechsel zur RTL-Richtung funktioniert es nun einwandfrei.

Der "Call to Action"-Bereich ist ein weiterer großartiger Ort dafür

.cta__text {
  border-start-start-radius: 50%;
  border-end-start-radius: 50px;
}
.cta__img {
  border: 1px dashed var(--secondary-color);
  border-inline-start-color: var(--light-color);
}

Jetzt erhalten wir auf Arabisch das richtige Layout

Sie fragen sich vielleicht genau, wie sich die block- und inline-Dimensionen umkehren, wenn sich der Schreibmodus ändert. Zurück zur japanischen Version, der Text ist vertikal und geht von oben nach unten. Ich habe diese Zeile zum Code hinzugefügt

/* The "About" section when langauge is Japanese */
html:lang(jp) .about__text {
  margin-block-end: auto;
  width: max-content;
}

Obwohl ich dem "Block"-Level einen Rand hinzugefügt habe, wurde er dem linken Rand zugewiesen. Das liegt daran, dass der Text um 90 Grad gedreht wurde, als die Sprache gewechselt hat und er in vertikaler Richtung fließt.

6. Andere Layout-Überlegungen

Selbst nach all dieser Vorbereitung ist es manchmal so, dass Elemente, die sich beim Wechsel der Richtung und Sprache verschieben, komplett daneben liegen. Es spielen mehrere Faktoren eine Rolle, also schauen wir sie uns an.

Position

Die Verwendung von position: absolute oder fixed zur Verschiebung von Elementen kann beeinflussen, wie sich Elemente beim Richtungswechsel verschieben. Einige Designs erfordern es. Aber ich würde Sie immer noch bitten, sich zu fragen: brauche ich das wirklich?

Zum Beispiel kann das Formular für die Newsletter-Anmeldung im Footer-Bereich unseres Beispiels mit position implementiert werden. Das Formular selbst nimmt die relative Position ein, während der Button die absolute Position einnimmt.

<form id="newsletter-form" class="relative">
  <input type="email" data-attr="placeholder" data-i18n_attr="footer_input_placeholder" class="w-100">
  <button class="btn btn--tertiary footer__newsletter_btn bolder absolute" data-i18n="footer_newsLetter_btn"></button>
</form>
html[dir="ltr"] .footer__newsletter_btn {
  right: 0;
}
html[dir="rtl"] .footer__newsletter_btn {
  left: 0;
}
Dies funktioniert in einem rtl-Schreibmodus einwandfrei.

Im "Hero"-Bereich habe ich den Hintergrund mit einer ::before Pseudo-Klasse und absoluter Positionierung erstellt

<header class="hero relative">
  <!-- etc. -->
</header>
.hero {
  background-image: linear-gradient(90deg, #30333f, #161616, #161616);
}
.hero::before  {
  content: '';
  display: block;
  height: 100%;
  width: 33.33%;
  background-color: var(--primary-color);
  clip-path: polygon(20% 0%, 100% 0, 100% 100%, 0% 100%);
  position: absolute;
  top: 0;
  right: 0;
}

Hier ist das HTML für unser Hero-Element

<header class="hero relative">
  <!-- etc. -->
  <div class="hero__social absolute">
    <div class="d-flex flex-col">
      <!-- etc. -->
    </div>
  </div>
</header>

Beachten Sie, dass dort eine .absolute Klasse vorhanden ist, die position: absolute auf das Social-Widget des Hero-Bereichs anwendet. In der Zwischenzeit ist der Hero selbst relativ positioniert.

Wie wir das Social-Widget auf halber Höhe der y-Achse verschieben

.hero__social {
  left: 0;
  top: 50%;
  transform: translateY(-50%);
}

Im Arabischen können wir die Position der ::before Pseudo-Klasse, die im Hintergrund verwendet wird, mit derselben Technik korrigieren, die wir im Footer-Formular verwenden. Das heißt, es gibt mehrere Probleme, die wir hier beheben müssen

  1. Die Richtung von clip-path
  2. Der Hintergrund linear-gradient
  3. Die Richtung des Kaffeebecher-Bildes
  4. Die Position der Social-Media-Box

Verwenden wir stattdessen einen einfachen Flip-Trick. Zuerst wickeln wir den Hero-Inhalt und den Social-Inhalt in zwei separate Wrapper-Elemente anstelle von einem

<header class="hero relative">
  <div class="hero__content">
      <!-- etc. -->
  </div>
  <div class="hero__social absolute">
    <div class="d-flex flex-col">
      <!-- etc. -->
    </div>
  </div>
</header>

Dann drehen wir beide Hero-Wrapper – den inneren Wrapper der Social-Box und das Bild – um 180 Grad

html[dir="rtl"] .hero,
html[dir="rtl"] .hero__content,
html[dir="rtl"] .hero__img img,
html[dir="rtl"] .hero__social > div {
  transform: rotateY(180deg);
}

Ja, das war's. Dieser einfache Trick ist auch hilfreich, wenn der Hintergrund des Heroes ein Bild ist.

transform: translate()

Diese CSS-Eigenschaft und ihr Funktionswert helfen, das Element auf einer oder mehreren Achsen zu bewegen. Der Unterschied zwischen ltr und rtl besteht darin, dass die x-Achse der inverse/negative Wert des aktuellen Werts ist. Wir können den Wert also in einer Variablen speichern und ihn entsprechend der Sprache ändern.

html {
  --about-img-background-move: -20%;
}

html[dir='rtl']{
  --about-img-background-move: 20%;
}

Dasselbe können wir für das Hintergrundbild in einem anderen Abschnitt tun

<figure class="about__img relative">
  <img src="image.jpg" data-attr="alt" data-i18n_attr="image_alt" class="w-100">
</figure>
.about__img::after {
  content: '';
  position: absolute;
  z-index: -1;
  transform: translateY(-75%) translateX(var(--about-img-background-move));
  /* etc. */
}

Ränder

Ränder werden verwendet, um Abstände zwischen Elementen zu vergrößern oder zu verringern. Sie akzeptieren auch negative Werte. Zum Beispiel drückt ein positiver margin-top Wert (20%) den Inhalt nach unten, während ein negativer Wert (z. B. -20%) den Inhalt nach oben zieht.

Wenn Ränder negativ sind, verschieben die oberen und linken Ränder das Element nach oben oder links. Die rechten und unteren Ränder tun dies jedoch nicht. Stattdessen ziehen sie den Inhalt, der sich rechts vom Element befindet, nach links, und den Inhalt unter dem Element nach oben. Wenn wir zum Beispiel einen negativen oberen und einen negativen unteren Rand auf dasselbe Element anwenden, wird das Element nach oben verschoben und der Inhalt darunter wird in das Element gezogen.

Hier ist ein Beispiel:

<section>
  <div id="d1"></div>
  <div id="d2"></div>
  <div id="d3"></div>
</section>
div {
  width: 100px;
  height: 100px;
  border: 2px solid;
}
#d1 {
  background-color: yellow;
  border-color: red;
}
#d2 {
  background-color: lightblue;
  border-color: blue;
}
#d3 {
  background-color: green;
  border-color: red;
}

Das Ergebnis des obigen Codes sollte etwa so aussehen

Fügen wir diese negativen Ränder zum #d2 Element hinzu

#d2 {
  margin-top: -40px;
  margin-bottom: -70px;
}

Beachten Sie, wie sich die zweite Box in der Grafik dank eines negativen margin-top Wertes nach oben verschiebt, und die grüne Box verschiebt sich ebenfalls nach oben und überlappt die zweite Box, dank eines negativen margin-bottom Wertes.

Als Nächstes fragen Sie sich vielleicht: Aber was ist der Unterschied zwischen transform: translate und Rändern?

Wenn ein Element mit einem negativen Rand bewegt wird, ist der anfängliche Platz, den das Element einnimmt, nicht mehr vorhanden. Im Falle des Translating des Elements mit einer Transformation ist das Gegenteil der Fall. Mit anderen Worten, ein negativer Rand zieht das Element nach oben, aber die Transformation ändert lediglich seine Position, ohne den für sie reservierten Platz zu verlieren.

Bleiben wir bei der Verwendung von Rändern in einer Richtung

#d2 {
  margin-top: -40px;
  /* margin-bottom: -70px; */
}

Jetzt ersetzen wir den Rand durch die Transformation

#d2 {
  /* margin-top: -40px;*/
  transform: translateY(-40px);
}

Man sieht, dass das Element zwar nach oben gezogen wird, sein anfänglicher Platz aber noch vorhanden ist, entsprechend dem natürlichen Dokumentenfluss.

Flexbox

display: flex bietet eine schnelle Möglichkeit, die Ausrichtung von Elementen in ihrem Container zu steuern. Wir können align-items und justify-content verwenden, um Kindelemente auf der Elternebene auszurichten.

In unserem Beispiel können wir Flexbox in fast jedem Abschnitt verwenden, um das Spaltenlayout zu erstellen. Außerdem können wir es im "Angebote"-Bereich verwenden, um die Menge dieser gelben "Special"- und "Best"-Markierungen zu zentrieren.

.offers__item::after {
  content: attr(data-offer);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}

Dasselbe kann auf den Hero-Bereich angewendet werden, um Text vertikal zu zentrieren.

<div class="d-lg-flex align-items-center">
  <div class="hero__text d-xl-flex align-items-center">
    <div>
      <!-- text -->
    </div>
  </div>
  <figure class="hero__img relative">
    <img src="/image.jpg" data-attr="alt" data-i18n_attr="image_alt" class="w-100">
  </figure>
</div>

Wenn der Wert flex-direction row ist, können wir die Breite für jedes Element kontrollieren. Im "Hero"-Bereich müssen wir das Bild auf den abgeschrägten Hang des Hintergrunds setzen, wo der Übergang von Dunkelgrau zu Gelb erfolgt.

.hero__text {
  width: 56.5%;
}
.hero__img {
  width: 33.33%;
}

Beide Elemente nehmen zusammen 89,83 % der Breite des Elter containers ein. Da wir justify-content auf dem Elternteil nicht angegeben haben, ist es standardmäßig auf start gesetzt, wobei die verbleibende Breite am Ende verbleibt.

Wir können Flexbox mit jeder der zuvor gesehenen Techniken kombinieren, wie z. B. Transformationen und Ränder. Dies kann uns helfen, die Anzahl der position-Instanzen in unserem Code zu reduzieren. Lassen Sie uns es mit einem negativen Rand im "Call to Action"-Bereich verwenden, um das Bild zu platzieren.

<section class="cta d-xl-flex align-items-center">
  <div class="cta__text w-100">
    <!-- etc. -->
  </div>
  <figure class="cta__img">
    <img src="image.jpg" data-attr="alt" data-i18n_attr="image_alt" class="w-100">
  </figure>
</section>

Da wir die Eigenschaften flex-wrap und flex-basis nicht angegeben haben, passen das Bild und der Text beide in den Elternteil. Da wir jedoch einen negativen Rand verwendet haben, wird das Bild nach links gezogen, zusammen mit seiner Breite. Dies spart zusätzlichen Platz für den Text. Wir wollen auch eine logische Eigenschaft, inline-start, anstelle von left verwenden, um den Wechsel zur rtl-Richtung zu handhaben.

Grid

Schließlich können wir einen grid Container verwenden, um die Elemente zu positionieren. CSS Grid ist leistungsstark (und anders als Flexbox) insofern, als es Elemente entlang der x-Achse und der y-Achse anordnet, anstatt nur einer davon.

Angenommen, im "Angebote"-Bereich ist die Rolle des "Alle anzeigen"-Buttons, um zusätzliche Daten zu erhalten, die auf der Seite angezeigt werden sollen. Hier ist JavaScript-Code, um den aktuellen Inhalt zu wiederholen

// offers section ==> "see all" btn functionality
(function(){
  document.querySelector('.offers .btn').addEventListener('click', function(){
    const offersContent = document.querySelector('.offers__content');
    offersContent.innerHTML += offersContent.innerHTML;
    offersContent.classList.remove('offers__content--has-margin');
    this.remove();
  })
})();

Dann verwenden wir display: grid im CSS für diesen Abschnitt. Zuerst ist hier unser HTML mit unserem hervorgehobenen Grid-Container.

<div class="offers__content offers__content--has-margin d-grid">
  <div class="offers__item relative" data-attr="data-offer" data-i18n_attr="special_offer">
    <!-- etc. -->
  </div>
  <div class="offers__item relative" data-attr="data-offer" data-i18n_attr="best_offer">
    <!-- etc. -->
  </div>
  <div class="offers__item relative" data-attr="data-offer" data-i18n_attr="best_offer">
    <!-- etc. -->
  </div>
</div>

Wir implementieren CSS Grid auf dem Element .offers__content

html {
  /* custom properties */
  --offers-content-column: repeat(3, 1fr);
  --offers-content-gap: 5vw;
}

.offers__content {
  display: grid;
  grid-template-columns: var(--offers-content-column);
  gap: var(--offers-content-gap);
}
.offers__content--has-margin {
  margin-block-end: 60px;
}

Das ist das Ergebnis nach dem Klicken auf den Button

Unsere Seite ist weit davon entfernt, das beste Beispiel für die Funktionsweise von CSS Grid zu sein. Während ich online Designs durchsuchte, fand ich ein Design, das die folgende Struktur verwendet

Beachten Sie, wie CSS Grid das responsive Layout ohne Media Queries erstellt. Und wie Sie vielleicht erwarten, funktioniert es gut für den Wechsel von Schreibmodi, wo wir die Position von Elementen im Grid basierend auf dem aktuellen Schreibmodus anpassen.

Zusammenfassung

Hier ist die endgültige Version der Seite. Ich habe darauf geachtet, die Responsivität mit einem Mobile-First-Ansatz zu implementieren, um Ihnen die Leistungsfähigkeit der CSS-Variablen zu zeigen. Öffnen Sie die Demo unbedingt auch im Vollbildmodus.

Ich hoffe, diese Techniken helfen Ihnen dabei, mehrsprachige Designs einfacher zu erstellen. Wir haben uns eine Reihe von CSS-Eigenschaften angesehen, die wir verwenden können, um Stile auf bestimmte Sprachen anzuwenden. Und wir haben uns verschiedene Ansätze dazu angesehen, wie z. B. die Auswahl der :lang Pseudo-Klasse und von Datenattributen mit der attr() Funktion. Im Rahmen dessen haben wir behandelt, was logische Eigenschaften in CSS sind und wie sie sich an den Schreibmodus eines Dokuments anpassen – was so viel schöner ist, als zusätzliche CSS-Regelsätze schreiben zu müssen, um physische Eigenschaftseinheiten auszutauschen, die ansonsten vom Schreibmodus nicht betroffen sind.

Wir haben uns auch eine Reihe von verschiedenen Positionierungs- und Layouttechniken angesehen und speziell darauf geachtet, wie verschiedene Techniken besser responsiv und wartungsfreundlicher sind als andere. Zum Beispiel sind CSS Grid und Flexbox mit Funktionen ausgestattet, die Elemente innerhalb eines Containers basierend auf sich ändernden Bedingungen neu ausrichten können.

Es gibt eindeutig viele bewegliche Teile, wenn man mit einer mehrsprachigen Website arbeitet. Es gibt wahrscheinlich andere Anforderungen, die Sie bei der Optimierung einer Website für bestimmte Sprachen berücksichtigen müssen, aber die hier gemeinsam behandelten Dinge sollten Ihnen alle Layout-biegenden Superkräfte verleihen, die Sie benötigen, um robuste Layouts zu erstellen, die jede beliebige Anzahl von Sprachen und Schreibmodi aufnehmen können.