Существует ряд императивных методов запроса разрешения на использование таких мощных функций, как доступ к данным о местоположении в веб-приложениях. Эти методы сопряжены с рядом сложностей, поэтому команда разработчиков разрешений Chrome экспериментирует с новым декларативным методом: специальным HTML-элементом <permission> . Этот элемент находится в стадии тестирования, начиная с версии Chrome 126, и в конечном итоге мы надеемся стандартизировать его.
Императивные методы запроса разрешения
Когда веб-приложениям требуется доступ к мощным функциям , им необходимо запрашивать разрешение. Например, когда Google Maps запрашивает местоположение пользователя через API геолокации , браузеры запрашивают у пользователя разрешение, часто с возможностью сохранения этого решения. Эта концепция четко определена в спецификации разрешений.
Спрашивать неявно при первом использовании вместо явного запроса заранее
API геолокации — мощный API, основанный на неявном запросе разрешения при первом использовании. Например, когда приложение вызывает метод navigator.geolocation.getCurrentPosition() , запрос разрешений автоматически появляется при первом вызове. Другой пример — navigator.mediaDevices.getUserMedia() .
Другие API, такие как Notification API или Device Orientation and Motion API , обычно имеют явный способ запроса разрешения через статический метод, такой как Notification.requestPermission() или DeviceMotionEvent.requestPermission() .
Проблемы с императивными методами получения разрешения
Спам разрешений
Раньше веб-сайты могли вызывать такие методы, как navigator.mediaDevices.getUserMedia() или Notification.requestPermission() , а также navigator.geolocation.getCurrentPosition() сразу после загрузки. Запрос на разрешение появлялся до того, как пользователь взаимодействовал с веб-сайтом. Иногда это называют спамом с разрешениями, и он затрагивает оба подхода: как неявный запрос при первом использовании, так и явный запрос заранее.

Смягчение последствий в браузере и требования к жестам пользователя
Спам с разрешениями привёл к тому, что производители браузеров стали требовать от пользователя выполнения какого-либо жеста, например нажатия кнопки или нажатия клавиши, перед отображением запроса на разрешение. Проблема такого подхода заключается в том, что браузеру очень сложно, если не невозможно, определить, должен ли тот или иной жест пользователя приводить к отображению запроса на разрешение. Возможно, пользователь просто нажимал на страницу в раздражении, потому что она загружалась слишком долго, или, возможно, он действительно нажимал кнопку « Найти меня» . Некоторые веб-сайты также научились очень эффективно обманывать пользователей, заставляя их нажимать на контент для отображения запроса.
Другим способом снижения риска является добавление мер по предотвращению злоупотреблений запросами, например, полная блокировка функций с самого начала или отображение запроса на разрешение в немодальной, менее навязчивой форме.

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

Нет легкой отмены
Наконец, пользователи слишком легко могут завести себя в тупик. Например, после того, как пользователь заблокировал доступ к функции, ему необходимо знать о раскрывающемся списке информации о сайте, где можно либо сбросить разрешения , либо снова включить заблокированные разрешения. В худшем случае оба варианта потребуют полной перезагрузки страницы, пока обновлённые настройки не вступят в силу. Сайты не предоставляют пользователям простой и быстрой ссылки для изменения текущего состояния разрешения, и им приходится кропотливо объяснять пользователям, как изменить настройки, как показано внизу следующего снимка экрана Google Карт.

Если разрешение является ключевым для взаимодействия, например, доступ к микрофону для приложения видеоконференцсвязи, такие приложения, как Google Meet, показывают навязчивые диалоговые окна, которые инструктируют пользователя, как разблокировать разрешение.

Декларативный элемент <permission>
Чтобы решить проблемы, описанные в этой статье, команда Chrome, отвечающая за разрешения, запустила пробную версию нового HTML-элемента <permission> . Этот элемент позволяет разработчикам декларативно запрашивать разрешение на использование (на данный момент) лишь части мощных функций, доступных веб-сайтам. В простейшем случае он используется, как показано в следующем примере:
<permission type="camera" />
До сих пор ведутся активные споры о том, следует ли использовать элемент <permission> как элемент void. Элемент void — это самозакрывающийся элемент в HTML, который не может иметь дочерних узлов, что в HTML означает отсутствие у него закрывающего тега.
Атрибут type
Атрибут type содержит список запрашиваемых вами разрешений, разделённых пробелами. На момент написания статьи допустимыми значениями являются 'camera' , 'microphone' и camera microphone (разделённые пробелом). Этот элемент по умолчанию отображается аналогично кнопкам с минимальным стилем пользовательского агента.

Атрибут type-ext
Для некоторых разрешений, которые допускают дополнительные параметры, атрибут type-ext принимает пары «ключ-значение», разделенные пробелами, например, precise:true для разрешения геолокации.
Атрибут lang
Текст кнопки предоставляется браузером и должен быть единообразным, поэтому его нельзя настроить напрямую. Браузер изменяет язык текста на основе унаследованного языка документа, цепочки родительских элементов или необязательного атрибута lang . Это означает, что разработчикам не нужно локализовать элемент <permission> самостоятельно. Если элемент <permission> выходит за рамки стадии тестирования исходного кода, для каждого типа разрешения может поддерживаться несколько строк или значков для повышения гибкости. Если вы заинтересованы в использовании элемента <permission> и вам нужна конкретная строка или значок, свяжитесь с нами !
Поведение
Когда пользователь взаимодействует с элементом <permission> , он может циклически проходить различные этапы:
Если они ранее не разрешили какую-либо функцию, они могут разрешить ее при каждом посещении или разрешить ее для текущего посещения.

Если они уже разрешили эту функцию, они могут разрешить ее использование и дальше или запретить ее.

Если они ранее запретили какую-либо функцию, они могут и дальше не разрешать ее или разрешить на этот раз.

Текст элемента <permission> автоматически обновляется в зависимости от статуса. Например, если разрешение на использование функции предоставлено, текст меняется на «Функция разрешена». Если разрешение необходимо предоставить, текст меняется на «Приглашает пользователя использовать функцию». Сравните предыдущий скриншот со следующим, чтобы увидеть два состояния.

CSS-дизайн
Чтобы пользователи могли легко распознать кнопку как средство доступа к мощным функциям, стили элемента <permission> ограничены. Если ограничения по стилю не подходят для вашего варианта использования, мы будем рады узнать , как и почему! Хотя не все требования к стилю могут быть удовлетворены, мы надеемся найти безопасные способы разрешить больше стилей для элемента <permission> после запуска пробной версии. В следующей таблице подробно описаны некоторые свойства, к которым применяются ограничения или особые правила. В случае нарушения любого из правил элемент <permission> будет отключен, и с ним нельзя будет взаимодействовать. Любые попытки взаимодействия с ним приведут к исключениям, которые можно перехватить с помощью JavaScript. Сообщение об ошибке будет содержать более подробную информацию об обнаруженном нарушении.
| Свойство | Правила |
|---|---|
| Можно использовать для задания цвета текста и фона соответственно. Контраст между двумя цветами должен быть достаточным для чёткого чтения текста (коэффициент контрастности не менее 3). Значение альфа-канала должно быть равно 1. |
| Должен быть установлен в пределах эквивалента small и xxxlarge . В противном случае элемент будет отключен. Масштаб будет учитываться при вычислении font-size . |
| Отрицательные значения будут исправлены на 0 . |
margin (все) | Отрицательные значения будут исправлены на 0 . |
| Значения ниже 200 будут исправлены до 200 . |
| Значения, отличные от normal и italic будут исправлены до normal . |
| Значения более 0.5em будут исправлены до 0.5em . Значения менее 0 будут исправлены до 0 . |
| Значения, отличные от inline-block и none будут исправлены на inline-block . |
| Значения свыше 0.2em будут скорректированы до 0.2em . Значения ниже -0.05em будут скорректированы до -0.05em . |
| Значение по умолчанию — 1em . Если указано, будет учитываться максимальное вычисленное значение между значением по умолчанию и заданными значениями. |
| Значение по умолчанию — 3em . Если указано, будет использоваться минимальное вычисленное значение между значением по умолчанию и заданными значениями. |
| Будет иметь значение по умолчанию fit-content . Если указано, будет учитываться максимальное вычисленное значение между значением по умолчанию и заданными значениями. |
| Значение по умолчанию будет равно утроенному значению fit-content . Если указано, будет учитываться минимальное вычисленное значение между значением по умолчанию и заданным значением. |
| Действует только если для height задано значение auto . В этом случае значения свыше 1em будут исправлены до 1em , а padding-bottom будет установлено значение padding-top . |
| Действует только если для width задано значение auto . В этом случае значения свыше 5em будут исправлены до 5em , а padding-right будет установлено равным значению padding-left. |
| Искажающие визуальные эффекты не допускаются. На данный момент мы принимаем только 2D-трансляцию и пропорциональное масштабирование. |
Следующие свойства CSS можно использовать как обычно:
-
font-kerning -
font-optical-sizing -
font-stretch -
font-synthesis-weight -
font-synthesis-style -
font-synthesis-small-caps -
font-feature-settings -
forced-color-adjust -
text-rendering -
align-self -
anchor-name aspect-ratio -
border(и все свойстваborder-*) -
clear -
color-scheme -
contain -
contain-intrinsic-width -
contain-intrinsic-height -
container-name -
container-type -
counter-* -
flex-* -
float -
height -
isolation -
justify-self -
left -
order -
orphans -
outline-*(за исключением, отмеченным ранее дляoutline-offset) -
overflow-anchor -
overscroll-behavior-* -
page -
position -
position-anchor -
content-visibility -
right -
scroll-margin-* -
scroll-padding-* -
text-spacing-trim -
top -
visibility -
x -
y -
ruby-position -
user-select -
width -
will-change -
z-index
Кроме того, можно использовать все логически эквивалентные свойства (например, inline-size эквивалентно width ) в соответствии с теми же правилами, что и их эквиваленты.
Псевдоклассы
Существует два специальных псевдокласса, которые позволяют стилизовать элемент <permission> на основе состояния:
-
:granted: Псевдокласс:grantedпозволяет задать специальный стиль при предоставлении разрешения. -
:invalid: Псевдокласс:invalidпозволяет задать специальную стилизацию, когда элемент находится в недопустимом состоянии, например, когда он обслуживается в кросс-источниковом iframe.
permission {
background-color: green;
}
permission:granted {
background-color: light-green;
}
/* Not supported during the origin trial. */
permission:invalid {
background-color: gray;
}
События JavaScript
Элемент <permission> предназначен для использования совместно с API разрешений . Существует ряд событий, которые можно отслеживать:
onpromptdismiss: Это событие вызывается, когда запрос на разрешение, вызванный элементом, был отклонен пользователем (например, путем нажатия кнопки закрытия или щелчка за пределами запроса).onpromptaction: это событие срабатывает, когда запрос на разрешение, вызванный элементом, был разрешён пользователем, выполнившим какое-либо действие в отношении самого запроса. Это не обязательно означает, что состояние разрешения изменилось; пользователь мог выполнить действие, сохраняющее статус-кво (например, продолжить предоставлять разрешение).onvalidationstatuschange: это событие срабатывает, когда элемент меняет состояние с"valid"на"invalid". Элемент считается"valid"если браузер доверяет целостности сигнала при щелчке по нему пользователем, и"invalid"в противном случае, например, если элемент частично перекрыт другим HTML-содержимым.
Вы можете зарегистрировать прослушиватели событий для этих событий непосредственно в HTML-коде ( <permission type="…" onpromptdismiss="alert('The prompt was dismissed');" /> ) или с помощью addEventListener() в элементе <permission> , как показано в следующем примере.
<permission type="camera" />
<script>
const permission = document.querySelector('permission');
permission.addEventListener('promptdismiss', showCameraWarning);
function showCameraWarning() {
// Show warning that the app isn't fully usable
// unless the camera permission is granted.
}
const permissionStatus = await navigator.permissions.query({name: "camera"});
permissionStatus.addEventListener('change', () => {
// Run the check when the status changes.
if (permissionStatus.state === "granted") {
useCamera();
}
});
// Run the initial check.
if (permissionStatus.state === "granted") {
useCamera();
}
</script>
Обнаружение особенностей
Если браузер не поддерживает HTML-элемент, он его не отобразит. Это означает, что если в вашем HTML-коде есть элемент <permission> , ничего не произойдёт, если браузер его не распознает. Вы всё равно можете использовать JavaScript для определения поддержки, например, для создания запроса на разрешение, который будет запускаться при нажатии обычной кнопки <button> .
if ('HTMLPermissionElement' in window) {
// The `<permission>` element is supported.
}
Пробный запуск
Чтобы протестировать элемент <permission> на своём сайте с реальными пользователями, зарегистрируйтесь в пробной версии Origin . Инструкции по подготовке сайта к использованию пробных версий Origin см. в статье «Начало работы с пробными версиями Origin ». Пробная версия Origin будет доступна для версий Chrome 126–131 (19 февраля 2025 г.).
Демо
Ознакомьтесь с демо-версией и исходным кодом на GitHub. Вот скриншот работы в поддерживаемом браузере.

Обратная связь
Мы будем рады узнать, как <permission> работает в вашем случае. Не стесняйтесь ответить на один из вопросов в репозитории или создать новый. Публичные сигналы в репозитории для элемента <permission> дадут нам и другим браузерам знать, что вы заинтересованы в нём.
Часто задаваемые вопросы
- Чем это лучше обычной
<button>в сочетании с API разрешений? Нажатие кнопки<button>— это пользовательский жест, но браузеры не могут проверить, связано ли оно с запросом разрешения. Если пользователь нажал на кнопку<permission>, браузер может быть уверен, что нажатие связано с запросом разрешения. Это позволяет браузеру упростить процессы, которые в противном случае были бы гораздо более рискованными. Например, пользователь может легко отменить блокировку разрешения. - Что делать, если другие браузеры не поддерживают элемент
<permission>? Элемент<permission>можно использовать в качестве прогрессивного улучшения. В браузерах, не поддерживающих его, можно использовать классический процесс получения разрешений, например, основанный на нажатии обычной<button>. Команда разработчиков разрешений также работает над полифиллом. Добавьте репозиторий GitHub в звёздочку, чтобы получать уведомления о его готовности. - Обсуждался ли этот вопрос с другими производителями браузеров? Элемент
<permission>активно обсуждался на конференции W3C TPAC в 2023 году на отдельном заседании . Вы можете ознакомиться с заметками к открытому заседанию . Команда Chrome также запросила у обоих производителей официальные позиции по стандартам (см. раздел «Ссылки по теме» ). Элемент<permission>постоянно обсуждается с другими браузерами, и мы надеемся стандартизировать его. - Должен ли этот элемент быть пустым? Споры о том, должен ли
<permission>быть пустым, всё ещё ведутся . Если у вас есть отзывы, поделитесь ими в Issue.
Ссылки по теме
Благодарности
Этот документ рецензировали Балаж Энгеди , Томас Нгуен , Пенелопа Маклахлан , Мариан Харбах , Дэвид Уоррен и Рэйчел Эндрю .