Grid: доступность и порядок элементов

Расположение элементов в Grid через grid-column и grid-row меняет только визуальный порядок — DOM-порядок (и порядок для скринридеров/клавиатуры) остаётся неизменным.

Зачем нужно

Grid позволяет визуально переставлять элементы независимо от их места в HTML. Это мощно, но опасно: скринридеры и Tab-навигация следуют DOM-порядку. Неправильное использование Grid для переупорядочивания интерактивных элементов создаёт серьёзные проблемы доступности.

Где используется

  • Адаптивные макеты с разным порядком на мобиле/десктопе
  • Карточки с изображением и заголовком
  • Перегруппировка блоков лендинга
  • Дашборды с переставляемыми виджетами

Основной контент

Проблема: визуал vs DOM-порядок

/* Визуально: Image | Title | Description */
/* DOM: Title, Description, Image */

.card {
  display: grid;
  grid-template-areas:
    "image"
    "title"
    "description";
}

.card__title       { grid-area: title; }
.card__description { grid-area: description; }
.card__image       { grid-area: image; }
<!-- DOM-порядок (для Tab): Title → Description → Image -->
<div class="card">
  <h2 class="card__title">Заголовок</h2>      <!-- 1-й в DOM -->
  <p class="card__description">Текст</p>       <!-- 2-й в DOM -->
  <img class="card__image" src="..." alt="..."><!-- 3-й в DOM -->
</div>

Для нефокусируемых элементов (img, текст) это допустимо. Для кнопок и ссылок — нет.

Безопасное переупорядочивание

/* OK — изображение декоративное, нет фокусируемых элементов */
.article {
  display: grid;
  grid-template-areas:
    "img"
    "heading"
    "text";
}

/* ОПАСНО — кнопки в grid-order не совпадает с DOM */
.wizard {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

.wizard .next()  { grid-column: 1; } /* Визуально первая */
.wizard .prev  { grid-column: 2; } /* Визуально вторая */
/* Но Tab идёт: .next() → .prev если DOM именно такой */

Рекомендации WCAG

/* WCAG 1.3.2: порядок фокуса должен соответствовать логическому порядку */

/* Если нужно изменить порядок для мобиля */
@media (max-width: 768px) {
  /* Меняйте DOM-порядок через JS или используйте flex-direction */
  /* Не полагайтесь только на grid-row для интерактивных элементов */
}

order vs grid-placement

/* order — как в Flexbox, меняет визуальный порядок */
.item { order: -1; } /* Опасно для интерактивных элементов */

/* grid-column/grid-row — явное позиционирование */
.item { grid-column: 2; grid-row: 1; } /* Те же проблемы */

/* Оба способа создают разрыв DOM vs visual */

Тестирование порядка

// Проверить логический порядок через Tab
// document.activeElement покажет текущий элемент
// Или использовать скринридер (NVDA, VoiceOver)

Частые ошибки

  • Переставлять кнопки через grid без изменения DOM — Tab-порядок нарушается; использовать tabindex как патч — плохая практика
  • Считать, что grid-area влияет на скринридер — нет; DOM-порядок определяет порядок чтения
  • Не тестировать с клавиатурой — после изменения макета всегда проверяйте Tab-навигацию

Связанные темы

Ресурсы