Зачем нужны логические свойства CSS
Свойства -top
, -bottom
, -left
и -right
Многие свойства CSS — такие как margin
, padding
, border
и другие — имеют направленные варианты.
Возьмём, к примеру, свойство margin
. Допустим, необходимо установить отступы 1em
сверху и снизу, 2em
слева и справа.
Длинная форма записи будет выглядеть так…
.component {
margin-top: 1em;
margin-bottom: 1em;
margin-left: 2em;
margin-right: 2em;
}
CSS предоставляет удобный сокращённый синтаксис, позволяющий создавать такие элементы с помощью одного свойства margin
, следуя порядку top
, right
, bottom
, left
по часовой стрелке.
.component {
margin: 1em 2em 1em 2em;
}
При использовании сокращённой записи, если значение опущено, то копируется значение, расположенное напротив него. В результате можно ещё больше сократить запись.
.component {
margin: 1em 2em;
}
Это отлично работает, когда ваш код всегда используется в языке, который следует одному и тому же потоку текста.
Но не все языки такие!
Как обрабатывать RTL и вертикальные языки
Русский, мой родной язык, пишется слева направо и сверху вниз.
Но такой язык, как арабский, пишется справа налево. Такие языки, как китайский и японский, традиционно пишутся вертикальными столбцами.
Если я применю направленный margin
только к одной стороне, как здесь…
.component:first-child {
margin-left: 0;
}
…где удаляется margin
? Это зависит от языка!
В русском языке поле удаляется с начала первого элемента. В арабском языке оно удаляется после первого элемента, что может привести к неожиданным визуальным эффектам.
В традиционном китайском языке оно было бы удалено из пространства между двумя столбцами (немного похоже на удаление нижнего поля в параграфе).
Исторически сложилось так, что для поддержки различных языков необходимо было проверять атрибут [dir]
, чтобы обрабатывать подобные вещи...
[dir="ltr"] .component:first-child {
margin-left: 0;
}
[dir="rtl"] .component:first-child {
margin-right: 0;
}
Очень раздражает, правда? Но теперь есть логические свойства CSS!
Логические свойства CSS
Логические свойства CSS определяют значения свойств не явными указаниями, такими как top
или left
, а их логическим направлением: inline
или block
, start
или end
.
*-inline
свойства следуют направлению текста (слева и справа для русского языка)*-block
свойства пересекают его (сверху и снизу для русского языка)*-start
свойства применяются перед элементом (сверху или слева для русского языка)*-end
свойства применяются после элемента (справа или снизу для русского языка)
Возьмём предыдущий пример…
.component {
margin-top: 1em;
margin-bottom: 1em;
margin-left: 2em;
margin-right: 2em;
}
Его можно переписать с использованием логических свойств следующим образом…
.component {
margin-block-start: 1em; /* top */
margin-block-end: 1em; /* bottom */
margin-inline-start: 2em; /* left */
margin-inline-end: 2em; /* right */
}
Свойства *-block
и *-inline
также имеют сокращённые версии, в формате {start} {end}
…
.component {
margin-block: 1em 1em;
margin-inline: 2em 2em;
}
И, как и в случае со старыми свойствами, можно ещё больше упростить, если оба значения одинаковы…
Практический пример
Помните предыдущий пример, где мы удалили поле из элемента :first-child
?
[dir="ltr"] .component:first-child {
margin-left: 0;
}
[dir="rtl"] .component:first-child {
margin-right: 0;
}
С помощью логических свойств CSS его можно записать следующим так...
.component:first-child {
margin-inline-start: 0;
}
Теперь, независимо от направления текста, margin
применяется (или в данном случае удаляется) в нужном месте!