В веб-интерфейсах часто скрывают контент, чтобы сделать их удобнее, сэкономить место на экране или повысить скорость загрузки страницы. Традиционные методы, такие как display: none или visibility: hidden, позволяют скрыть контент визуально, но они также делают его полностью недоступным для программ чтения с экрана и функций браузера, таких как "Найти на странице".
Чтобы скрыть контент, но оставить его доступным для поиска и ссылок на контент с помощью фрагментов URL и ссылок "Прокрутка до текстового фрагмента", можно использовать элемент HTML <details> или атрибут hidden="until-found". Обычно рекомендуется использовать элемент <details>, поскольку его проще внедрить и поддерживать. Однако в некоторых сложных случаях элемента <details> недостаточно и требуется hidden="until-found".
Пример:
- Если вы хотите полностью контролировать стиль механизма показа/скрытия.
- Если элементы управления пользовательского интерфейса, позволяющие показывать или скрывать контент, находятся в другой части DOM.
- Если вы не хотите поддерживать скрытие контента после его показа.
Рекомендации по внедрению
Элемент <details> по умолчанию содержит текст, доступный для поиска и специальных возможностей, и не требует специальной реализации. По возможности используйте <details> вместо hidden="until-found".
Если вам нужно использовать hidden="until-found", следуйте этим инструкциям:
- Примените атрибут. Добавьте HTML-атрибут
hidden="until-found"непосредственно к элементам, содержащим контент, который нужно скрыть. - Синхронизируйте состояние интерфейса. Если в интерфейсе есть связанные состояния, которые зависят от видимости контента (например, обновляются атрибуты ARIA, переключаются классы CSS или поворачиваются значки аккордеона):
- ОБЯЗАТЕЛЬНО добавьте прослушиватель событий для события
beforematch. - Зарегистрируйте прослушиватель событий
beforematchнепосредственно в элементе, содержащем атрибутhidden="until-found". Поскольку событие всплывает, вы можете использовать делегирование событий, зарегистрировав один прослушиватель в родительском элементе (например, в контейнере вкладок), чтобы управлять несколькими скрытыми разделами одновременно. - Внутри прослушивателя событий выполните логику для синхронизации связанных элементов пользовательского интерфейса (например, закройте другие открытые вкладки или измените состояние переключателя).
- ОБЯЗАТЕЛЬНО добавьте прослушиватель событий для события
Пример кода
Цель. Создать скрытый контейнер, контент которого остается невидимым для пользователя, пока он не выполнит поиск по слову в этом разделе.
Использование элемента <details>
<details>
<summary>Click to expand</summary>
<p>This content is visually hidden.</p>
</details>
Взаимоисключающие сведения
При работе с взаимоисключающими областями контента, такими как эксклюзивный аккордеон, используйте нативный элемент HTML <details> с общим атрибутом name.
<div class="accordion-group">
<!-- The name attribute creates an exclusive disclosure group -->
<details class="disclosure" name="my-accordion">
<summary>Section 1</summary>
<p>Section 1 content</p>
</details>
<details class="disclosure" name="my-accordion" open>
<summary>Section 2</summary>
<p>Section 2 content</p>
</details>
<details class="disclosure" name="my-accordion">
<summary>Section 3</summary>
<p>Section 3 content</p>
</details>
</div>
Использование атрибута hidden="until-found"
<!-- The browser automatically removes hidden="until-found" upon a search match -->
<div class="hidden-container" hidden="until-found">
<p>This content is visually hidden.</p>
</div>
Взаимоисключающие настраиваемые сообщения о раскрытии информации
При работе с настраиваемыми взаимоисключающими областями, управляемыми внешними кнопками, убедитесь, что видна только соответствующая панель. В обработчике событий beforematch необходимо синхронизировать связанные состояния ARIA, например задать aria-expanded="true" для кнопки управления.
<div class="custom-accordion">
<div class="controls">
<button aria-expanded="true" aria-controls="panel-1" id="btn-1">Section 1</button>
<button aria-expanded="false" aria-controls="panel-2" id="btn-2">Section 2</button>
</div>
<div id="panel-1" class="panel">
<p>Section 1 content (visible)</p>
</div>
<div id="panel-2" class="panel" hidden="until-found">
<p>Section 2 content (hidden)</p>
</div>
</div>
const accordion = document.querySelector('.custom-accordion');
accordion.addEventListener('beforematch', (e) => {
// Hide all panels and synchronize button states before the browser reveals the matched panel
accordion.querySelectorAll('.panel').forEach((panel) => {
if (panel !== e.target) {
panel.hidden = 'until-found';
}
});
accordion.querySelectorAll('button').forEach((btn) => {
const controls = btn.getAttribute('aria-controls');
btn.setAttribute('aria-expanded', controls === e.target.id ? 'true' : 'false');
});
});
Рекомендации для цели "hidden="until-found""
- РЕКОМЕНДУЕТСЯ применять границы, поля и фоны к вложенным дочерним контейнерам, а не непосредственно к элементу с атрибутом
hidden="until-found". Это предотвращает непреднамеренные сдвиги макета или визуальные остатки, пока элемент скрыт. - НЕ применяйте свойства CSS
display: none,visibility: hiddenили любые связанные с ними свойстваdisplayилиvisibilityнепосредственно к элементам с атрибутомhidden="until-found". Это нарушает работу встроенных функций и навсегда скрывает контент из индекса Google Поиска. - НЕ используйте
hidden="until-found"для конфиденциальной информации, токенов внутренних данных или нерелевантных данных, которые не должны быть доступны через поиск. - НЕ используйте
hidden="until-found"вместо текста, предназначенного только для программ чтения с экрана (.sr-only).
Поддержка браузеров и резервные стратегии
НЕ отказывайтесь от hidden="until-found" из-за отсутствия поддержки в браузере, поскольку преимущества специальных возможностей намного перевешивают затраты на реализацию резервного варианта.
hidden="until-found" резервное объявление
Для стандартных элементов интерфейса, таких как аккордеоны или разделы "Читать далее", используйте JavaScript, чтобы определить, поддерживается ли функция, и показать весь контент, если нет.
if (!('onbeforematch' in HTMLElement.prototype)) {
// Expand all hidden content for unsupported browsers
document.querySelectorAll('[hidden="until-found"]').forEach((el) => {
el.removeAttribute('hidden');
// MANDATORY: also update any aria references to this element.
});
}
Если элементы интерфейса являются взаимоисключающими (например, настраиваемые эксклюзивные панели, где контент находится в одной и той же визуальной области), резервный вариант должен извлекать и показывать весь контент линейно под основной интерактивной областью, используя фрагменты якорей URL, чтобы пользователи могли переходить непосредственно к соответствующим разделам.