Тег bdi (от английского bidirectional isolate, «двунаправленная изоляция») отделяет фрагмент текста от окружения при выборе направления написания. Он нужен, когда в строку попадает текст, направление которого автор не знает заранее: имя пользователя, заголовок комментария, название из базы данных. Тег парный, собственных атрибутов у него нет, а атрибут dir по умолчанию действует как auto: браузер сам определяет направление по содержимому.
Без bdi беда случается не с самим именем, а с тем, что рядом: если имя пользователя написано справа налево, соседние число, двоеточие или скобка могут оказаться не с той стороны. Автору такая строка при проверке обычно не встречается, потому что тестовые имена почти всегда латинские. Чем bdi отличается от span с dir="auto", а также от тега bdo, показано ниже.
<p>Игрок: <bdi>שלום</bdi> - 5</p>
В этой статье
Тег bdi в HTML: что это и для чего нужен
Слова идут слева направо (русский, английский) или справа налево (арабский, иврит). Когда в строку с одним направлением попадает текст с другим, браузер по алгоритму двунаправленного текста решает, как выстроить слова, числа и знаки препинания рядом. Иногда решение ломает порядок: число или знак рядом с чужим текстом переезжает на другую сторону.
Тег bdi изолирует свой текст: то, что внутри, не влияет на порядок снаружи, а окружение не влияет на порядок внутри. Направление внутри определяется по первому знаку с явным направлением. В Chrome bdi - строчный элемент (display: inline) со свойством unicode-bidi: isolate, а вычисленное направление для арабского имени равно rtl, хотя атрибута dir в разметке нет.
Спецификация указывает главный случай применения: пользовательский текст с неизвестным направлением. По данным справки MDN, тег доступен во всех современных браузерах с января 2020 года. Сам текст тег не меняет: выделение и textContent остаются в обычном порядке, меняется только показ.
Что ломается без тега bdi: имя, число и знаки рядом
Возьмём строку из таблицы результатов: «Игрок: имя - 5». Если имя записано на иврите или по-арабски, а вокруг русский текст, знак «-» и число «5» оказываются слева от имени, а не справа. В замере порядок кусков слева направо был такой: «Игрок:», «- 5», имя. С bdi порядок верный: «Игрок:», имя, «- 5».
<p>Игрок: <span>שלום</span> - 5</p>
<p>Игрок: <bdi>שלום</bdi> - 5</p>
Так же ломаются строки «имя - 5 очков», «1. имя: 5», «Игрок имя, 5» и «имя (5)». Строки «Игрок имя!» и «Игрок имя: Anna» в замере не ломались. Поэтому риск не оценить по одной удачной строке: имя записывает пользователь, а проверять нужно любой язык.
Проверьте сами в кадре: выберите имя и способ записи, кадр измерит порядок кусков. Можно ввести своё имя.
Пример: где оказывается счёт рядом с именем
Выберите имя и способ записи. Кадр измеряет положение кусков строки и показывает, где оказался счёт.
Тег bdi, span dir=auto и атрибут dir: что выбрать
Изоляцию можно получить тремя способами. Первый - тег bdi. Второй - <span dir="auto">: в замере он получил такие же unicode-bidi: isolate и направление по содержимому. Третий - CSS-свойство unicode-bidi: isolate у обычного span: изоляция есть, но направление остаётся ltr, потому что автоопределения нет. Для арабского имени порядок кусков в кадре выше у всех трёх способов верный.
Между bdi и span dir=auto разница в смысле: bdi прямо говорит, что здесь изолированный текст, и короче. По справке MDN, стили браузер или сторонняя среда могут проигнорировать, а тег остаётся, поэтому для этого случая лучше тег.
Атрибут dir у bdi можно задать явно: ltr и rtl фиксируют направление, а auto возвращает автоопределение. Явное значение нужно, когда направление известно заранее, например язык поля.
<bdi>שלום</bdi>
<bdi dir="ltr">שלום</bdi>
<bdi dir="rtl">Anna</bdi>
Явное значение опасно, если язык неизвестен. У имени на иврите со знаком в конце в замере: без dir и с dir=auto знак «!» стоит слева от букв, как принято в иврите, а с dir=ltr оказывается справа. С dir=rtl латинское имя «Anna!» получает «!» слева, а не справа.
Пример: атрибут dir у bdi
Выберите имя и значение dir. Кадр показывает вычисленное направление и сторону, на которой оказался знак.
Тег bdi и bdo: изоляция против принудительного направления
Тег bdi направление не меняет: он выбирает его по содержимому и изолирует. Тег bdo действует наоборот: атрибутом dir он принудительно задаёт направление, и буквы латинского слова в dir=rtl идут задом наперёд. Изоляция у bdo получается попутно (в замере unicode-bidi: isolate-override).
Копируемый текст в обоих случаях остаётся в обычном порядке: меняется только показ. Убедитесь в кадре: он сортирует буквы по положению на экране и сравнивает с текстом, который попадёт в копию.
Пример: bdi и bdo на одном слове
Выберите запись. Кадр показывает порядок букв на экране и текст, который попадёт в копию.
Частые ошибки с тегом bdi
Ошибки с этим тегом связаны с тем, что изоляцию не записывают или путают с принудительным направлением.
| Ошибка | Что происходит | Как исправить |
|---|---|---|
Имя пользователя без изоляции: Игрок: <span>שלום</span> - 5 | Счёт и знаки рядом с арабским именем или именем на иврите оказываются слева от него | Обернуть имя в bdi |
bdo вместо bdi для имён | bdo принудительно меняет направление: латинские буквы идут задом наперёд | Использовать bdi, он выбирает направление по содержимому |
| Проверка только на русских и английских именах | Порядок ломается лишь на тексте с другим направлением, и ошибку не видно | Проверить строку с арабским именем и именем на иврите |
Явный dir="ltr" для имени, язык которого неизвестен | Знак «!» в конце имени на иврите оказывается справа от букв, а не слева | Не задавать dir: по умолчанию действует auto |
Ожидание, что bdi изменит копируемый текст | Меняется только показ, копия остаётся в обычном порядке | Порядок в самом тексте не менять |