30 Модуль 6 Современный CSS 16 мин урок 5 из 25

Логические свойства и многоязычность

margin-inline вместо margin-left: почему привычные стороны света ломаются на арабском и японском — и как перестать о них думать.

Что ты научишься делать

  • Заменишь left и right на свойства, которые едут вместе с текстом
  • Развернёшь макет в RTL одним атрибутом, без правки стилей
  • Поймёшь, где физические свойства всё-таки нужны

#Одна строка, которая ломает весь макет

Ты сверстал цитату: полоска слева, отступ слева, текст по левому краю. Красиво.

Потом сайт переводят на арабский. Текст идёт справа налево, и вся страница разворачивается зеркально — браузер делает это сам, если поставить dir="rtl". Всё, кроме твоей цитаты: полоска осталась слева, отступ тоже, а текст прижался к правому краю. Блок развалился.

Причина в том, что left — это про экран, а не про текст. Логические свойства говорят не «слева», а «в начале строки» — и начало у каждого языка своё.

Интерактивный разбор доступен при включённом JavaScript.

#Две оси вместо четырёх сторон

Вместо верх-низ-лево-право в логической модели две оси.

Inline — вдоль строки. В русском и английском это горизонталь, слева направо. В арабском — та же горизонталь, но справа налево. В японской вертикальной вёрстке — сверху вниз.

Block — поперёк строки, в направлении, куда идут блоки. Обычно это сверху вниз.

ФизическоеЛогическоеЧто означает
margin-leftmargin-inline-startОтступ в начале строки
margin-rightmargin-inline-endОтступ в конце строки
margin-topmargin-block-startОтступ до блока
margin-bottommargin-block-endОтступ после блока
widthinline-sizeРазмер вдоль строки
heightblock-sizeРазмер поперёк строки
text-align: lefttext-align: startВыравнивание к началу строки
border-leftborder-inline-startРамка в начале строки

Так не надо

.quote {
  border-left: 3px solid;
  padding-left: 16px;
  margin-top: 24px;
  margin-bottom: 24px;
  text-align: left;
}

Пять строк, привязанных к сторонам экрана. При dir="rtl" полоска и отступ останутся слева, а текст уедет вправо — блок развалится.

Так надо

.quote {
  border-inline-start: 3px solid;
  padding-inline-start: 16px;
  margin-block: 24px;
  text-align: start;
}

Четыре строки, и все едут вместе с текстом. Тот же CSS работает и в русском, и в арабском, и в вертикальном японском.

Переключи dir у контейнера
В песочницу

#Позиционирование и inset

У абсолютного позиционирования есть своя пара логических свойств, а заодно очень удобное сокращение.

inset: 0 заменяет четыре строки с нулями — это самый частый способ растянуть элемент на весь родитель. А inset-inline-start ведёт себя как left в русском и как right в арабском.

CSSbadge.css
.card {  position: relative;}/* Бейдж всегда в начале верхнего края — где бы это начало ни было */.card__badge {  position: absolute;  inset-block-start: 8px;  inset-inline-start: 8px;}/* Подложка на весь родитель — одна строка вместо четырёх */.card__overlay {  position: absolute;  inset: 0;}

#Скругления и логика углов

Скругления тоже умеют быть логическими, но имена у них непривычные: сначала ось block, потом inline.

border-start-start-radius — угол на пересечении начала блочной оси и начала строчной. В обычном русском тексте это левый верхний угол, в арабском — правый верхний.

#Как это выглядит в реальном проекте

Кусок стилей интерфейса, который живёт сразу в нескольких локалях. Ни одного left или right — и при этом ни одного отдельного файла под RTL.

CSSnotification.css
@layer components {  .toast {    position: fixed;    /* Всплывает в конце строки: справа в русском, слева в арабском */    inset-block-end: 24px;    inset-inline-end: 24px;    inline-size: min(360px, calc(100vw - 32px));    display: grid;    grid-template-columns: auto 1fr auto;    gap: 12px;    padding-block: 14px;    padding-inline: 16px;    border-inline-start: 3px solid var(--accent);    border-radius: 12px;  }  .toast__close {    /* Кнопка закрытия — в конце строки, а не «справа» */    margin-inline-start: auto;  }  /* Стрелка — единственное место, где нужен разворот вручную */  .toast__arrow {    transform: scaleX(1);  }  [dir="rtl"] .toast__arrow {    transform: scaleX(-1);  }}

Обрати внимание на последнее правило. Логические свойства разворачивают раскладку, но не разворачивают содержимое: иконка со стрелкой вправо так и останется смотреть вправо. Такие вещи переворачивают вручную — и их обычно единицы.

#Что ещё меняется вместе с языком

Локализация не заканчивается на отступах. Есть вещи, о которых вспоминают только когда сайт уже перевели.

  • Длина текста. Немецкий и финский дают слова вдвое длиннее английских, и кнопка «Save» превращается в «Speichern unter». Фиксированная ширина кнопки — верный способ получить обрезанный текст.
  • Цифры. В арабской локали могут использоваться свои начертания цифр, и ширина строки меняется.
  • Переносы. hyphens: auto работает только вместе с правильным lang — без него браузер не знает словарь переносов.
  • Сортировка и регистр. Это уже забота бэкенда, но верстальщику стоит знать: порядок букв в алфавитах разный.

#Когда физические свойства нужны

  • Тень от источника света. Свет в интерфейсе падает сверху и не зависит от языка. box-shadow: 0 4px 12px так и остаётся физическим.
  • Иконки с направлением. Стрелка «назад» должна смотреть в сторону начала строки — её переворачивают через transform: scaleX(-1) под [dir="rtl"].
  • Привязка к физическому устройству. Вырез камеры, безопасные зоны, аппаратные особенности экрана — это про экран, а не про текст.
  • Графика и координаты. Внутри SVG и на canvas работают собственные системы координат, логических свойств там нет.

#Поддержка браузерами

ВозможностьСостояние
margin-inline, padding-block и прочие отступыВо всех современных браузерах с 2021 года
inline-size, block-sizeТам же
inset и его логические вариантыВо всех современных браузерах, Safari подтянулся последним
border-start-start-radiusПоддерживается, но появилось позже остальных
writing-mode: vertical-rlДавно и везде — используется в японской типографике

Где спотыкаются почти все

Смешаны физические и логические свойства в одном правиле

Почему При RTL margin-left останется слева, а padding-inline-start уедет вправо. Блок разъедется, и причину искать тяжело.

Как надо В одном компоненте — одна система. Проще всего договориться: логические везде, физические только там, где это осознанное исключение.

dir поставлен на body вместо html

Почему Часть браузерных элементов — полосы прокрутки, встроенные виджеты форм — смотрят именно на корневой элемент.

Как надо Пиши <html lang="ar" dir="rtl">. Язык и направление задаются вместе.

Отдельный файл rtl.css с переопределениями

Почему Два файла, которые надо держать в синхроне. Каждая правка компонента требует правки во втором месте — и рано или поздно про неё забывают.

Как надо Логические свойства убирают необходимость во втором файле почти полностью.

Забыто, что содержимое не переворачивается

Почему Раскладка развернулась, а стрелка на кнопке «дальше» продолжает показывать вправо, то есть назад.

Как надо Пройдись по иконкам с направлением и переверни их через scaleX(-1) под [dir="rtl"].

Строчная ось inline axis
Направление, вдоль которого идёт текст. Зависит от языка и режима письма.
Блочная ось block axis
Направление, в котором идут блоки. Обычно сверху вниз.
Логическое свойство logical property
Свойство, привязанное к осям текста, а не к сторонам экрана.
Направление письма direction, dir
Атрибут dir="ltr" или dir="rtl", задающий начало и конец строки.
Режим письма writing-mode
Горизонтальное или вертикальное расположение строк.

Проверь себя

  1. Что означает <code>margin-inline-start</code> при <code>dir="rtl"</code>?

    Начало строки в арабском справа. Свойство едет вместе с текстом — в этом весь смысл.

  2. Чем удобен <code>inset: 0</code>?

    Это сокращение для всех четырёх смещений сразу. Самый частый способ растянуть элемент на весь родитель.

  3. Где всё-таки уместно физическое свойство?

    Свет в интерфейсе падает сверху независимо от языка. Отступы и выравнивание, наоборот, должны ехать с текстом.

  4. Развернёт ли <code>dir="rtl"</code> иконку со стрелкой?

    Переворачивается раскладка, а не картинки. Иконки с направлением переворачивают вручную через <code>scaleX(-1)</code>.

  5. Какая запись задаёт верхний и нижний отступ одной строкой?

    Блочная ось идёт поперёк строк — в обычном горизонтальном тексте это как раз верх и низ.

Задание

Переверстать блок под арабскую локаль

Карточка отзыва свёрстана на физических свойствах. Контейнер стоит в режиме dir="rtl", и блок разъехался: полоска и отступ слева, текст справа.

Переведи стили на логические свойства так, чтобы карточка корректно собралась в обе стороны. Разметку не трогай, dir не меняй.

Открыть в песочнице
    Подсказка 1

    border-left становится border-inline-start, padding-left — padding-inline-start.

    Подсказка 2

    Пара margin-top и margin-bottom с одинаковым значением сворачивается в margin-block: 20px.

    Подсказка 3

    width заменяется на inline-size, text-align: left — на text-align: start.

    Показать решение
    HTMLindex.html
    <div dir="rtl">  <article class="review">    <p class="review__text">قهوة ممتازة والمكان هادئ.</p>    <p class="review__author">مارينا</p>  </article></div>
    CSSstyle.css
    .review {  border-inline-start: 3px solid #6544e0;  padding-inline-start: 16px;  padding-inline-end: 8px;  margin-block: 20px;  text-align: start;  inline-size: 320px;  max-inline-size: 100%;}.review__text { margin: 0 0 6px; }.review__author { margin: 0; font-size: 13px; color: #666; }

    Проверь себя