Назад

📌 Сноски на полях с помощью CSS Anchor Positioning

Сноски на полях без JavaScript: типизированный attr(), anchor(), max() и фолбэк для узких экранов.

📌 Сноски на полях с помощью CSS Anchor Positioning

Венсан Берна применил CSS Anchor Positioning для создания сносок, которые без единой строчки JavaScript располагаются на полях страницы точно напротив нужного фрагмента текста.

💡 Как это устроено?

Разметка строится на обычных HTML-элементах и data-атрибутах:

<!-- Знак сноски в тексте -->
<sup data-anchor="note-1">1</sup>

<!-- Текст сноски (сразу под абзацем) -->
<aside role="note" data-anchor="note-1">1. Текст заметки...</aside>

Связывание через attr() и CSS Custom Properties

В CSS используются типизированные attr() (с указанием типа <dashed-ident>), благодаря чему значение data-anchor сразу превращается в имя якоря без хардкода в стилях:

sup[data-anchor] {
  /* Динамически создаем имя якоря из дата-атрибута */
  anchor-name: attr(data-anchor type(<dashed-ident>));
}

aside[role="note"][data-anchor] {
  /* Привязываем сноску к соответствующему якорю */
  position-anchor: attr(data-anchor type(<dashed-ident>));
}

Позиционирование на широких экранах

На десктопах сноска уходит в правое поле страницы. Но главное — выравнивание по высоте с помощью anchor() и защита от наложения заметок друг на друга (max()):

@media (min-width: 60rem) {
  aside[role="note"] {
    position: absolute;
    /* Выносим в правое поле */
    left: calc(100% + 2rem);
    width: 15rem;

    /* Делаем саму сноску якорем для ДРУГИХ сносок */
    anchor-name: --sidenote;

    /* Выбираем максимальную высоту: 
       либо верх знака сноски anchor(top), 
       либо низ предыдущей сноски anchor(--sidenote bottom) + отступ */
    top: max(anchor(top), anchor(--sidenote bottom, 0px) + 1rlh);
  }
}

🧠 В чём фишка с max()?

Если две сноски стоят слишком близко в одном абзаце, вторая могла бы перекрыть первую. С помощью anchor(--sidenote bottom) CSS видит нижнюю границу предыдущей сноски. Функция max() сравнивает: если знак сноски находится ниже предыдущей сноски — используем его высоту; если же знак сноски выше — сноска «отталкивается» от предыдущей и опускается ниже.

🛡 Фолбэк для узких экранов и старых браузеров

Без медиа-запроса и поддержи anchor positioning (или на мобильных), элементы aside[role="note"] остаются в блочном потоке сразу под своим абзацем: они оформляются чуть более приглушённым цветом и меньшим шрифтом. Разметка читается естественно и красиво на любых устройствах!

Полный разбор в блоге автора

Скопировано