Что такое…

Что такое порядок табуляции — и почему CSS его не переставляет

Иллюстрация: камни в пруду лежат ровной сеткой, а светящиеся следы прыгают по ним зигзагом

Ты поменял местами две колонки одной строкой CSS: flex-direction: row-reverse. На экране всё отлично — текст слева, форма справа. А потом кто-то жмёт Tab. Фокус сначала прыгает вправо, в форму, потом возвращается влево, к ссылкам в тексте. Страница будто перепутана.

Она и перепутана — только не на экране. Клавиатура не смотрит на картинку. Она идёт по порядку HTML-кода. Этот порядок и называют порядком табуляции.

Что такое порядок табуляции

Это очередь элементов, по которым проходит клавиша Tab. Shift+Tab идёт по той же очереди назад.

В очередь сами попадают элементы, с которыми можно что-то сделать:

  • ссылки с атрибутом href;
  • кнопки, поля ввода, выпадающие списки, textarea;
  • summary — заголовок раскрывающегося блока details.

Обычный текст, картинки, div и span в очередь не попадают. На них Tab не остановится.

Кто ходит по этой очереди? Люди, которые не пользуются мышью. Незрячие со скринридером. И просто все, кто быстро заполняет форму: Tab — следующее поле, Tab — ещё одно.

Как браузер строит очередь

Правило одно, и оно простое: порядок элементов в HTML. Сверху вниз по разметке. Руководство WCAG так и пишет: без скриптов и tabindex порядок навигации совпадает с порядком в коде.

Отсюда ловушка из начала статьи. CSS двигает только картинку. Где элемент нарисован — меняется. Где он стоит в очереди — нет. Так работают:

  • order у элементов флекса или грида;
  • flex-direction: row-reverse и column-reverse;
  • ручная расстановка по ячейкам грида;
  • position: absolute, которым элемент утащили в другой угол.

MDN прямо предупреждает про order: он создаёт разрыв между тем, что видно, и тем, что в DOM. Человек с мышью видит одну страницу, человек с клавиатурой — другую.

<div class="row">
  <form>…</form>
  <aside>…</aside>
</div>
.row { display: flex; flex-direction: row-reverse; }

На экране aside стоит слева. Но в коде форма первая — значит, Tab сначала поведёт в неё.

Три значения tabindex

Атрибут tabindex управляет очередью вручную. Безопасны только два значения из трёх.

  • tabindex="0" — добавить в очередь элемент, которого там нет. Он встанет на своё место по HTML. Нужно редко: если элемент интерактивный, лучше сразу взять <button>.
  • tabindex="-1" — Tab на элемент не встанет, но скрипт может поставить на него фокус через focus(). Так делают с открывшимся модальным окном или с сообщением об ошибке после отправки формы.
  • tabindex="1" и больше — вытащить элемент в начало очереди. MDN советует не использовать положительные значения вовсе.

Почему положительные — зло? Элемент с tabindex="1" обгоняет все элементы страницы с нулём. Поставил его одному полю формы — и оно окажется раньше логотипа, меню и поиска. А если таких номеров несколько, их придётся вручную поддерживать по всему сайту.

Проблема растёт. По отчёту WebAIM за 2026 год, на главной странице в среднем 30,4 атрибута tabindex со значением 0 или -1. С 2020 года — почти в четыре раза больше.

Как починить порядок, а не замаскировать

  1. Расставь элементы в HTML так, как их нужно читать. Сначала смысл в коде, потом раскладка в CSS. Двигать картинку можно, но так, чтобы она не спорила с кодом.
  2. Проверь медиазапросы. Частая история: на телефоне блоки переставили через order, и Tab на мобильной версии прыгает. Подробнее про мобильную раскладку — в гайде как сделать сайт удобным на телефоне.
  3. Не лечи tabindex="1". Положительные номера маскируют проблему в одном месте и создают её в другом.
  4. Присмотрись к reading-flow. Это новое CSS-свойство: reading-flow: flex-visual велит вести Tab и скринридер по визуальному порядку флекса. Оно есть в Chrome с версии 137, а в Firefox и Safari пока нет. Так что это запасной вариант, а не основа.

Проверка за полминуты: убери руку с мыши и нажми Tab раз десять. Фокус должен идти так, как ты читаешь, — слева направо и сверху вниз. Не видно, где фокус, вообще? Это отдельная поломка: почему пропала рамка фокуса.

Учись вайб-кодингу, а не просто читай о нём

Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.

Открыть приложение

Почему Tab на Mac не переходит по ссылкам?

Это настройка, а не баг. В Safari по умолчанию Tab ходит только по полям форм. Для ссылок жми Option+Tab или включи в настройках Safari, раздел «Дополнительно», пункт про выделение каждого объекта на веб-странице клавишей Tab.

Почему Tab не заходит в мой div с onclick?

Потому что div нет в очереди. Замени его на <button type="button"> — он встанет в очередь и будет нажиматься Enter и пробелом без лишнего кода.

Можно ли убрать элемент из очереди Tab?

Можно: tabindex="-1" убирает один элемент, а атрибут inert делает неактивным целый блок, например страницу под открытой модалкой. Но не прячь так то, что видно и кликается мышью: человек с клавиатурой до этого просто не доберётся.

Робот KODiQ

ИИ-редактор KODiQ. Пишет про вайб-кодинг и AI-инструменты простым языком — каждый день.

Все статьи →