HTML глобальный атрибут inert

Определение и применение

Глобальный атрибут inert (англ. inert — инертный, неактивный) делает элемент и его потомков недоступными для обычного взаимодействия пользователя. Браузер исключает эту область из клавиатурной навигации и дерева доступности — представления страницы для вспомогательных технологий. При этом содержимое остаётся в документе и само по себе не исчезает с экрана.

Например, у карточки ещё загружаются данные, а её кнопки и поля уже видны. В этом случае можно временно сделать всю карточку инертной, оставив сообщение о загрузке и кнопку отмены снаружи. Другой сценарий — боковая панель, которую сдвинули за край экрана: одного перемещения через CSS недостаточно, чтобы убрать её ссылки из обхода клавишей Tab.

Поддержка браузерами

Спецификация: multipage

Поддерживается во всех основных браузерах с 2023 года.

Отдельные значения (1) поддерживаются не везде — смотрите таблицу.

Показать браузеры
Совместимостьhtml.global_attributes.inert
ВозможностьКомпьютерыМобильные
ChromeEdgeFirefoxOperaSafariChrome AndroidFirefox for AndroidOpera AndroidSafari on iOSSamsung BrowserWebView AndroidWebView on iOS
inert✓102✓102✓112✓88✓15.5✓102✓112✓70✓15.5✓19.0✓102✓15.5
Element is ignored for the purposes of find-in-page.✓124✓124✓120✓110×✓124✓120✓82×✓27.0✓124×

поддерживаетсяс ограниченияминет поддержкинет данных≤31 — не позднее версии 31

Строка «Element is ignored for the purposes of find-in-page» означает «Элемент не участвует в поиске по странице». Речь о встроенном поиске браузера: Ctrl + F или Command + F на macOS. При поддержке этого поведения браузер пропускает текст внутри инертной области. Отметка «Нет» в этой строке относится только к исключению из поиска, а не к поддержке самого атрибута inert.

Проверка наличия свойства:

JavaScript
const supportsInert = 'inert' in HTMLElement.prototype;

В старом браузере неизвестный HTML-атрибут не отключит интерфейс. Если блокировка обязательна, нужен проверенный полифил либо иной сценарий с доступными нативными элементами. Замена одним pointer-events: none не обеспечивает клавиатурную доступность.

Синтаксис и значения

HTML
<section inert>
  <h2>Настройки доставки</h2>
  <label>Город <input name="city"></label>
  <button type="button">Применить</button>
</section>

inert — логический атрибут: значение определяется его наличием. Записи inert, inert="" и inert="inert" равнозначны. Чтобы снять инертность, удалите атрибут. Если атрибута нет, элемент всё ещё может быть инертным из-за предка или открытого модального диалога.

Что происходит с инертной областью

  • Ссылки, кнопки и поля не получают фокус при обходе клавишей Tab; обычный вызов focus() тоже не переносит в них фокус.
  • Пользователь не может активировать вложенные элементы кликом или отредактировать их содержимое, включая область с contenteditable (атрибутом, разрешающим пользователю редактировать содержимое элемента прямо на странице).
  • Элемент и его потомки исключаются из дерева доступности: средство чтения с экрана не должно предлагать их как доступную часть интерфейса.
  • Обычное выделение текста пользователем подавляется. По стандарту текст также исключается из поиска по странице. В браузерах, где эта часть поведения не реализована, поиск может находить текст даже внутри инертной области. Поддержка указана в отдельной строке таблицы — пояснение к поиску по странице.
  • Размеры, расположение, цвета и прозрачность не меняются автоматически. Видимое объяснение недоступности задаёт автор страницы.

Действие распространяется на потомков в плоском дереве (flat tree): это дерево с учётом распределения содержимого через слоты Shadow DOM. Поэтому inert применим и к контейнерам веб-компонентов. Добавленные позже потомки тоже попадают под ограничение; вручную обновлять каждому tabindex не нужно.

Сравните активную и инертную области в базовом примере. Проверяйте не только мышь, но и Tab, Shift + Tab и редактирование поля.

Управление через JavaScript

JavaScript
const panel = document.querySelector('#settings');

panel.inert = true;  // Добавить атрибут.
panel.inert = false; // Удалить атрибут.

panel.toggleAttribute('inert'); // Переключить наличие атрибута.
console.log(panel.inert);      // Проверить собственный атрибут.

Свойство HTMLElement.inert отражает атрибут самого элемента, а не вычисляет его фактическую доступность. Если inert задан контейнеру, у вложенной кнопки button.inert может быть false, хотя кнопка недоступна. Присваивание button.inert = false не отменяет инертность предка. Удалите атрибут с нужного контейнера либо разместите действующую кнопку вне него.

Метод toggleAttribute('inert') добавляет атрибут inert, если его нет, и удаляет, если он есть. Метод removeAttribute('inert') удаляет атрибут; если его нет, ничего не меняется. Эти методы изменяют только атрибут самого элемента и не отменяют инертность, вызванную его предком.

Фокус и доступное объяснение

Фокус определяет, какой элемент сейчас получает ввод с клавиатуры. Например, пользователь вводит текст в поле внутри карточки. Если нужно сделать карточку инертной, сначала вызовите focus() у доступной кнопки «Отмена» за пределами карточки, а затем добавьте inert. Так пользователь сможет продолжить работу с клавиатуры, а фокус не останется в отключаемом поле.

После удаления inert не нужно автоматически возвращать фокус в прежнее поле. За время загрузки пользователь мог перейти к другому полю и начать печатать там. Неожиданный перенос фокуса ему помешает. Возвращайте фокус, когда пользователь сам выбрал продолжение работы с карточкой, например нажал кнопку «Продолжить редактирование».

Сообщение «Загрузка…», объяснение причины блокировки и кнопку «Повторить попытку» размещайте за пределами элемента с inert. Если оставить их внутри, кнопка тоже перестанет работать, а программа чтения с экрана не сможет прочитать сообщение.

Блоку с изменяющимся сообщением можно задать role="status": это позволяет программе чтения с экрана озвучить новый текст без переноса фокуса на него. Атрибут aria-busy="true" сообщает такой программе, что содержимое области ещё обновляется. Он не блокирует кнопки и ссылки и не заменяет inert.

Визуальное обозначение инертной области

Атрибут inert сам по себе не меняет внешний вид элемента. Чтобы показать, что область временно недоступна, можно сделать её полупрозрачной с помощью свойства opacity:

CSS
[inert] {
  opacity: 0.5;
}

Такой стиль делает изменение заметным, но не объясняет его причину. Дополните его текстом за пределами контейнера. Селектор [inert] выбирает только элементы с явным атрибутом, а не всех фактически инертных потомков. В примере переключения области кнопка управления и сообщение остаются доступны при обоих состояниях.

Отличия от других способов отключения и скрытия

Когда выбирать inert, disabled, hidden и другие средства
СредствоНазначение и отличие
inertВременно исключает целую область из взаимодействия и дерева доступности, сохраняя её отображение.
disabledОтключает поддерживающий его элемент формы. Отключённое поле не участвует в отправке и проверке ограничений формы. Для группы полей есть fieldset disabled; обычные ссылки внутри группы он не отключает.
readonlyЗапрещает изменение значения поддерживаемого текстового поля, сохраняя возможность фокусировки, копирования и отправки значения. Не блокирует произвольный контейнер.
hiddenСкрывает неактуальное содержимое визуально и от вспомогательных технологий. Режим until-found имеет отдельные правила раскрытия.
aria-hidden="true"Убирает содержимое из дерева доступности, но само по себе не препятствует кликам и фокусу. Нельзя оставлять внутри доступные с клавиатуры элементы.
aria-disabled="true"Сообщает о недоступности элемента, но не отключает его автоматически. Поведение, фокус и оформление реализует автор.
pointer-events: noneМеняет обработку указателя; не исключает ссылки из клавиатурной навигации и дерева доступности.
tabindex="-1"Исключает один элемент из последовательного обхода. Не отключает его потомков, клики или программную фокусировку.

Связь с dialog и popover

Нативный <dialog>, открытый через showModal(), автоматически делает остальной документ инертным. Вручную добавлять inert на все соседние блоки не требуется. Метод show() и обычный атрибут open не создают такую модальность.

Модальный диалог — специальное исключение: он может выйти из инертности предков. При этом явный inert на самом диалоге отключит и его. У обычного потомка такого исключения нет. Это различие можно проверить в примере модального диалога.

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

Ограничения и типичные ошибки

  • Не помещайте единственную кнопку включения внутрь отключаемого контейнера: пользователь не сможет её нажать.
  • Не используйте inert для важного пояснения, которое нужно прочитать во время блокировки.
  • Не считайте атрибут защитой данных: скрипты могут читать и менять DOM, выполнять обработчики через программную отправку событий. Таймеры и сетевые запросы не останавливаются.
  • Не принимайте element.inert === false за универсальную проверку интерактивности: учитывайте предков и модальные диалоги.
  • Сам атрибут не создаёт диалог, не назначает ему доступное имя, не управляет прокруткой и не реализует весь жизненный цикл модального окна.

Спецификация

HTML Living Standard: inert и инертные поддеревья.

Примеры, попробуйте сами

Активная и инертная область

Сравните ввод текста и обход элементов клавишей Tab. Удалите inert у второй области: её элементы станут доступны. Затем попробуйте inert="false" — наличие атрибута снова отключит область. Пример требует нативной поддержки inert.

index.html
HTML
<h2>Активная область</h2>
<div>
  <label>Город <input value="Казань"></label>
  <label><input type="checkbox"> Нужна доставка</label>
  <button type="button">Продолжить</button>
</div>

<h2>Область для проверки inert</h2>
<p>Измените атрибут контейнера и сравните доступность элементов.</p>
<div inert>
  <label>Город <input value="Томск"></label>
  <label><input type="checkbox"> Нужна доставка</label>
  <button type="button">Продолжить</button>
</div>
style.css
CSS
[inert] {
  opacity: 0.5;
}

Переключение инертности

Нажмите ▶, затем отключите область внешней кнопкой. Проверьте поле и Tab, после чего включите область. Кнопка внутри области показывает безопасный порядок действий: сначала перенос фокуса наружу, затем inert = true.

index.html
HTML
<button id="toggle" type="button" disabled>Отключить область</button>
<p id="status" role="status">Запустите пример, чтобы проверить inert.</p>

<section id="settings" aria-labelledby="settings-title">
  <h2 id="settings-title">Настройки</h2>
  <p><label>Название проекта <input id="project" value="Мой сайт"></label></p>
  <p><label><input type="checkbox"> Получать уведомления</label></p>
  <button id="lock" type="button" disabled>Отключить изнутри</button>
</section>
main.js
JavaScript
const panel = document.querySelector('#settings');
const toggle = document.querySelector('#toggle');
const lock = document.querySelector('#lock');
const statusMessage = document.querySelector('#status');

if (!('inert' in HTMLElement.prototype)) {
  statusMessage.textContent = 'Браузер не поддерживает inert. Откройте пример в более новом браузере.';
} else {
  toggle.disabled = false;
  lock.disabled = false;
  statusMessage.textContent = 'Область доступна.';

  function setLocked(locked) {
    // Переносим фокус до отключения области, если он находится внутри неё.
    if (locked && panel.contains(document.activeElement)) {
      toggle.focus();
    }
    panel.inert = locked;
    toggle.textContent = locked ? 'Включить область' : 'Отключить область';
    statusMessage.textContent = locked ? 'Область временно недоступна.' : 'Область доступна.';
  }

  toggle.addEventListener('click', () => {
    setLocked(!panel.inert);
  });

  lock.addEventListener('click', () => {
    setLocked(true);
  });
}
style.css
CSS
[inert] {
  opacity: 0.5;
}

Модальный диалог внутри inert

Нажмите ▶ и откройте диалог: showModal() позволяет ему работать внутри инертного предка, а фон становится недоступен. Закройте его кнопкой или Escape. Замените showModal() на show() и повторите: немодальный диалог останется инертным; закройте его внешней кнопкой.

index.html
HTML
<button id="open" type="button" disabled>Открыть диалог</button>
<button id="close-outside" type="button" disabled>Закрыть снаружи</button>
<p id="status" role="status">Запустите пример.</p>

<div inert>
  <p>Этот контейнер инертен.</p>
  <button type="button">Недоступная кнопка</button>
  <dialog id="dialog" aria-labelledby="dialog-title">
    <h2 id="dialog-title">Проверка диалога</h2>
    <p>Модальный диалог может выйти из инертности предка.</p>
    <button id="close" type="button" autofocus>Закрыть</button>
  </dialog>
</div>
main.js
JavaScript
const dialog = document.querySelector('#dialog');
const openButton = document.querySelector('#open');
const closeButton = document.querySelector('#close');
const closeOutside = document.querySelector('#close-outside');
const statusMessage = document.querySelector('#status');

if (!('inert' in HTMLElement.prototype) || typeof dialog.showModal !== 'function') {
  statusMessage.textContent = 'Для примера нужны inert и dialog.showModal().';
} else {
  openButton.disabled = false;
  closeOutside.disabled = false;
  statusMessage.textContent = 'Откройте диалог и проверьте фокус.';

  openButton.addEventListener('click', () => {
    // Замените на show(), чтобы сравнить с немодальным диалогом.
    dialog.showModal();
  });

  closeButton.addEventListener('click', () => {
    dialog.close();
  });

  // Нужна для закрытия инертного диалога после замены showModal() на show().
  closeOutside.addEventListener('click', () => {
    dialog.close();
  });
}