Używaj tego samego pliku CSS na stronach LTR i RTL, jawnie ustawiając kierunek w HTML, stosując właściwości logiczne do odstępów zależnych od kierunku oraz używając gap między elementami układu. W tym przewodniku utworzysz lokalny przykład z dwiema stronami, które możesz porównać w przeglądarce na Macu.
Celem jest zapewnienie temu samemu niewielkiemu komponentowi zamierzonych odstępów po zmianie kierunku przepływu w tekście. Potrzebujesz edytora zwykłego tekstu i aktualnej przeglądarki na komputer. W przykładzie użyto wymyślonych etykiet i ozdobnego koła, bez frameworka, zewnętrznych zasobów ani JavaScriptu.
Co powinien kontrolować współdzielony arkusz stylów?
Przypisz HTML-owi odpowiedzialność za kierunek, a arkuszowi stylów za odstępy. Obie strony wczytują ten sam zasób CSS i używają tych samych klas komponentu; element główny strony określa dir="ltr" albo dir="rtl". HTML definiuje rel="stylesheet" jako odnośnik do zewnętrznego zasobu, który wpływa na stylizację dokumentu. Standard HTML: odnośniki do arkuszy stylów.
Gdy kierunek jest znany, używaj HTML-owego atrybutu dir. Elementy potomne zazwyczaj dziedziczą kierunek, a lang go nie ustawia. W tym kontrolowanym porównaniu wybierz jawne określenie kierunku zamiast dir="auto": automatyczny kierunek zależy od treści, więc łacińskie etykiety przykładowe spowodowałyby wybór LTR. MDN: atrybut dir.
Warto rozróżnić fizyczną krawędź od położenia w przepływie treści. W trybie pisma horizontal-tb z tego przykładu początek wiersza oznacza lewą stronę w LTR i prawą w RTL. Początek bloku pozostaje u góry. Właściwości logiczne wyrażają te zależności bezpośrednio. MDN: logiczne marginesy, obramowania i dopełnienia.
| Zamierzony odstęp | Wybór we współdzielonym CSS | Wynik po zmianie kierunku |
|---|---|---|
| Odstęp wewnątrz krawędzi początkowej komponentu | padding-inline-start |
Przenosi się na drugą fizyczną stronę |
| Odstęp wewnątrz obu krawędzi wiersza | padding-inline |
Stosuje wartości początku i końca w nowym kierunku |
| Odstęp między elementami Flexboxa | gap |
Zachowuje określony odstęp między elementami |
| Odstęp u góry i u dołu w tym układzie poziomym | padding-block |
Pozostaje u góry i u dołu |
| Margines przed elementem w przepływie wiersza | margin-inline-start |
Przypada na nową stronę początku wiersza |
Odwzorowanie marginesów i dopełnień wynika z trybu pisma i kierunku elementu. Natomiast gap tworzy odstępy w obsługiwanych kontenerach układu. To odrębne zadania: używaj dopełnienia wokół zawartości, a odstępu między elementami potomnymi tego samego poziomu. MDN: logiczne odstępy, MDN: gap.
Utwórz dwie lokalne strony korzystające z jednego pliku CSS
Utwórz na Macu folder o nazwie spacing-demo. Zapisz poniższe pliki jako zwykły tekst, zachowując dokładnie podane rozszerzenia. Nie używaj edytora, który dopisuje .txt po .html lub .css.
spacing-demo/
ltr.html
rtl.html
components.css
Zapisz ten kompletny dokument HTML jako ltr.html. Następnie zapisz jego drugą kopię jako rtl.html, zmieniając tylko atrybut elementu głównego z dir="ltr" na dir="rtl". Pozostaw odwołanie do arkusza stylów i znaczniki komponentu bez zmian. Etykiety pozostają po angielsku, ponieważ to syntetyczne porównanie układu.
<!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>
Teraz zapisz poniższy kompletny arkusz stylów jako components.css. Celowo nierówne dopełnienie w wierszu ułatwia sprawdzenie zmiany kierunku: większe wcięcie powinno podążać za początkiem wiersza.
: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;
}
Tutaj padding-inline: 24px 8px oznacza dopełnienie od początku, a następnie od końca. Nie oznacza lewej, a potem prawej strony. Jedna wartość dotyczyłaby obu krawędzi wiersza. MDN: padding-inline.
Pozostaw flex-direction: row na obu stronach. Wiersz Flexboxa już podąża za kierunkiem kontenera: w LTR biegnie od lewej do prawej, a w RTL od prawej do lewej. Dodanie row-reverse do wersji RTL ponownie odwróciłoby ten kierunek. MDN: flex-direction.
Neutralne koło nie ma znaczenia kierunkowego, więc jego wygląd pozostaje bez zmian, a jego położenie podąża za wierszem. Etykiety zapisane alfabetem łacińskim również zachowują kolejność liter; ten przykład sprawdza układ komponentu, a nie przetłumaczony tekst.
Jak sprawdzić, czy odstępy są rzeczywiście współdzielone?
Otwórz oba pliki HTML w przeglądarce na Macu i porównaj je przy tej samej szerokości okna. Poniższe wartości wynikają z deklaracji — nie są pomiarami zgłoszonymi przez przeglądarkę. Obramowanie karty jest niezależne od jej dopełnienia.
| Sprawdzenie | Strona LTR | Strona RTL |
|---|---|---|
| Położenie koła | Pierwszy element po lewej | Pierwszy element po prawej |
| Lewe dopełnienie karty | 24px |
8px |
| Prawe dopełnienie karty | 8px |
24px |
| Odstęp między sąsiednimi elementami Flexboxa | 16px |
16px |
| Górne i dolne dopełnienie karty | 16px |
16px |
| Odstęp przed opisem | 8px u góry |
8px u góry |
Sprawdź współdzielenie zasobów niezależnie od kierunku. Zmień --space-medium w components.css z 16px na 20px, zapisz plik i wczytaj ponownie obie strony. Na obu powinien zwiększyć się odstęp między elementami oraz dopełnienie w kierunku bloku, ponieważ te deklaracje odwołują się do tej samej zmiennej. Po porównaniu przywróć wartość 16px.
Następnie zwęź okno przeglądarki i zastąp opis dłuższą, wymyśloną etykietą, na przykład Module A extended sample description. Sprawdź, czy tekst zawija się i nie zasłania koła ani znacznika. To dodatkowy przydatny test: komponent może poprawnie odbijać układ przy jednej szerokości, a przy innej być zbyt ciasny.
Nie oceniaj każdej widocznej odległości wyłącznie na podstawie gap. Marginesy elementów, wewnętrzne dopełnienie i wyrównanie rozdzielające mogą sprawić, że widoczny odstęp będzie większy niż zadeklarowana szczelina. W przykładzie wyzerowano marginesy tekstu i pominięto wyrównanie rozdzielające, by ułatwić porównanie. MDN: opis właściwości gap.
Jak przenieść istniejący komponent bez konfliktów odstępów?
Zacznij od ustalenia znaczenia każdej istniejącej deklaracji. Wcięcie tekstu od strony początkowej zwykle odpowiada początkowi wiersza; krawędź celowo przypisana do konkretnej fizycznej strony może nadal wymagać właściwości fizycznej. Konwertuj deklaracje zgodnie z zamierzeniem projektu, zamiast mechanicznie zastępować każde wystąpienie left.
W przypadku komponentu podobnego do tego przykładu wykonaj kolejno następujące kroki:
- Wskaż element nadrzędny określający kierunek.
- Zastąp zależne od kierunku odstępy wewnętrzne logicznym dopełnieniem.
- W razie potrzeby zastąp zależne od kierunku odstępy zewnętrzne logicznymi marginesami.
- Użyj właściwości
gapelementu nadrzędnego do zwykłych odstępów między elementami Flexboxa i usuń marginesy, które wcześniej zapewniały ten sam odstęp. - Powtórz porównania z nierównym dopełnieniem i zwężonym oknem dla obu kierunków.
W trakcie migracji sprawdź starsze deklaracje fizyczne i późniejsze skrócone zapisy. Właściwości logiczne i fizyczne odwzorowujące tę samą stronę uczestniczą razem w kaskadzie; właściwość logiczna nie wygrywa automatycznie tylko dlatego, że jest logiczna. Późniejsza deklaracja padding może zresetować dopełnienie przypisane wcześniej przez właściwości logiczne, jeśli pozostałe czynniki kaskady są równe. Właściwości i wartości logiczne CSS, poziom 1: właściwości modelu pudełkowego.
Pamiętaj też o granicy kierunku. Zagnieżdżony komponent z własnym dir="ltr" powinien korzystać z odwzorowania LTR nawet na stronie RTL. Z kolei samo margin-inline nie jest dziedziczone, więc przypisz każdemu komponentowi potrzebne deklaracje odstępów, zamiast oczekiwać, że margines elementu nadrzędnego przeniesie się na niego. MDN: dziedziczenie kierunku, MDN: formalna definicja margin-inline.
Jakie ograniczenia przeglądarek wpływają na to podejście?
Według MDN właściwości padding-inline i margin-inline są szeroko obsługiwane w przeglądarkach od kwietnia 2021 r. Pozwala to używać ich w aktualnych przeglądarkach na komputer, ale nie gwarantuje obsługi w każdej starszej przeglądarce ani każdej nowszej składni pokazanej na tych stronach referencyjnych. W tym przykładzie użyto zwykłych długości i auto, bez nowszych funkcji określania rozmiaru. MDN: padding-inline, MDN: margin-inline.
Odstęp Flexboxa ma odrębną historię. Safari dodało tę obsługę w wersji 14.1; obsługa odstępów w Grid była dostępna już od Safari 12. WebKit zwraca szczególną uwagę na to, że zapytanie o obsługę właściwości nie potrafiło rozróżnić tych kontekstów, więc samo @supports (gap: 16px) nie wystarcza do wykrycia obsługi odstępu Flexboxa w starszym Safari. WebKit: nowe funkcje WebKit w Safari 14.1.
Jeśli docelowa przeglądarka obsługuje logiczne marginesy, ale nie obsługuje odstępu Flexboxa, dodaj poniższy fragment zastępczy na końcu głównych reguł arkusza stylów. Zapewnia odstępy temu konkretnemu komponentowi w jednym wierszu. Użyj go zamiast aktywnego odstępu, jak pokazano; nie jest to ogólne rozwiązanie dla zawijanych wierszy.
/* Optional single-row replacement for Flexbox gap. */
.sample-card {
gap: 0;
}
.sample-card > * + * {
margin-inline-start: var(--space-medium);
}
Jeśli przeglądarka nie obsługuje również właściwości logicznych, ten fragment zastępczy nie wystarczy. Do lokalnego zadania użyj aktualnej przeglądarki albo utwórz i przetestuj jawne reguły fizyczne LTR i RTL dla starszej wersji docelowej. Decyzję dotyczącą konkretnej przeglądarki oddziel od głównego projektu współdzielonego arkusza stylów.
Końcowe porównanie powinno potwierdzić spójne założenie: HTML określa kierunek, współdzielony CSS określa odstępy, a wcięcie początkowe komponentu podąża za początkiem wiersza. Zachowaj obie lokalne strony jako niewielki zestaw regresyjny, który możesz wykorzystać przy każdej zmianie odstępów lub układu komponentu.
Źródła
- Standard HTML — typ odnośnika „stylesheet” — WHATWG.
- Globalny atrybut HTML dir — MDN Web Docs.
- Właściwości logiczne marginesów, obramowań i dopełnienia — MDN Web Docs.
- Właściwość CSS padding-inline — MDN Web Docs.
- Właściwość CSS margin-inline — MDN Web Docs.
- Właściwość CSS gap — MDN Web Docs.
- Właściwość CSS flex-direction — MDN Web Docs.
- Moduł właściwości i wartości logicznych CSS, poziom 1 — W3C.
- Nowe funkcje WebKit w Safari 14.1 — WebKit.