TGViewer
<divelopers> <divelopers> @alexnozer_dev · 1.18K subscribers
Post #373 777
Решение проблемы с уровнями заголовков

Есть одна давняя и нерешённая проблема: неверная иерархия заголовков. А именно пропущенные уровни заголовков, когда за <h1> следует <h3>. Ухудшается структура страницы и навигация с помощью вспомогательных технологий.

С компонентным подходом может быть трудно учесть контекст. Страница с <h1> рисует компонент «популярные товары» с заголовком <h2>, а он рисует компонент «список товаров» с карточками, у каждой из которых заголовок <h3>.

// Код для иллюстрации
function HomePage() {
return `
<main>
<h1>Магазин</h1>
${BestSellers()}
</main>
`;
}

function BestSellers() {
return `
<section>
<h2>Популярные товары</h2>
${ProductList()}
</section>
`;
}

function ProductList() {
return `
<ul>
${products.map(product => `
<li>
<article>
<h3>${product.title}</h3>
</article>
</li>
`).join('')}
</ul>
`;
}

document.body.innerHTML += HomePage();


В таком сценарии структура будет верной:

Магазин
└── Популярные товары
├── Товар 1
├── Товар 2
└── ...


Если использовать тот же компонент «список товаров» на странице каталога, где в <h1> обычно название категории, а дальше идёт сетка с карточками товаров, то получится пропуск заголовка <h2>. Карточки не учитывают контекст.

function CollectionPage() {
return `
<main>
<h1>Холодильники</h1>
${ProductList()}
</main>
`;
}

function ProductList() {
// как в предыдущем примере
}

document.body.innerHTML += CollectionPage();


Проблему пытаются решить уже давно. На канале есть пост про структуру заголовков и outline, где попытки подробно описаны. Если кратко, то много лет пытались, не смогли, удалили алгоритм из стандарта и отказались от реализации.

Тут на днях Джейк Арчибальд рассказал, что в Firefox экспериментируют с решением проблемы пропуска уровней заголовков. То есть вновь предпринимается попытка решить проблему. И решение планируют стандартизировать.

Дисклеймер: это обзор раннего предложения новых функций. Синтаксис может измениться в будущем или от функций могут отказаться


Предлагается новый глобальный атрибут headingoffset. Он задаёт смещение уровня для всех вложенных заголовков. С этим вновь предлагается использовать для заголовков только <h1> и его уровень будет вычисляться на основе смещения.

<main>
<h1>Магазин</h1>
<!--
задано смещение
уровня заголовков
-->
<section headingoffset="1">
<!-- тут будет уровень 2 -->
<h1>Популярные товары</h1>
<!--
задано смещение
уровня заголовков
-->
<ul headingoffset="1">
<li>
<article>
<!-- тут будет уровень 3 -->
<h1>Товар 1</h1>
</article>
</li>
<li>
<article>
<!-- тут будет уровень 3 -->
<h1>Товар 1</h1>
</article>
</li>
...
</ul>
</section>
</main>


В комментариях подтвердили, что это также работает с элементами <h2>-<h6>. Если задано смещение, то уровень заголовка меняется на совокупное смещение. При смещении в 1 уровень <h2> становится <h3> и так далее.

Может возникнуть вопрос: а что будет с <h6>? На это также дали ответ: он станет <h7> и так вплоть до 9 уровня максимум. В HTML нет <h7>, но с помощью атрибута aria-level="7" заголовку можно задать более глубокий уровень.

Заголовки иногда стилизуют по селектору элемента, который привязывает стили к уровню в названии элемента. Как тогда стилизовать заголовки по уровнями, если все они <h1>? Об этом тоже подумали и добавили селектор :heading():

:heading(2) {
/*
Выберет все заголовки у которых
вычисленный уровень 2
*/
}


Реализация появится в Firefox Nightly 153 за флагом экспериментальных технологий. С одной стороны крутая функция, с другой это возврат к использованию <h1> для всех заголовков, что сломает текущие инструменты анализа дерева заголовков.

#html #a11y
Bluesky Social Firefox for Web Developers (@webdevs.firefox.com) Ever struggled to get heading tags right in includes/components? headingoffset could be the answer…
  • 👍 7
  • ❤ 4
  • 😱 4
  • 👨‍💻 1
More from @alexnozer_dev
  1. Sep 21, 2026Реализация пользовательских атрибутов Под конец прошлого года я рассказывал об API пользов…
  2. Sep 14, 2026Подклассы Event вместо CustomEvent Многие библиотеки предоставляют систему событий в качес…
  3. Sep 11, 2026Эволюция стилей в темах Shopify Адам Ватан на днях поделился новостью, что Shopify выкупил…
  4. Sep 9, 2026Persistent Widgets Многие сайты не должны быть SPA. Но иногда эта архитектура продиктована…
  5. Sep 7, 2026Processing Instructions и маркеры В DOM всё представлено в виде узлов (Node) разных типов.…
  6. Sep 1, 2026@scope и потоковая передача HTML Ноам Розенталь поделился интересной техникой, в которой с…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →