有许多命令式方法可用于请求在 Web 应用中使用位置信息访问权限等强大功能的权限。这些方法存在诸多挑战,因此 Chrome 权限团队正在尝试一种新的声明式方法:专用 HTML <permission> 元素。此元素从 Chrome 126 开始进入源试用阶段,我们最终希望将其标准化。
用于请求权限的命令式方法
当 Web 应用需要访问强大的功能时,需要请求权限。例如,当 Google 地图使用 Geolocation API 请求用户的位置信息时,浏览器会向用户发出提示,通常会提供存储该决定的选项。这是权限规范中定义明确的概念。
在首次使用时隐式询问,而不是预先明确请求
Geolocation 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> 是否应为空元素。无效元素是 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)。Alpha 渠道必须为 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-kerningfont-optical-sizingfont-stretchfont-synthesis-weightfont-synthesis-stylefont-synthesis-small-capsfont-feature-settingsforced-color-adjusttext-renderingalign-selfanchor-name aspect-ratioborder(以及所有border-*属性)clearcolor-schemecontaincontain-intrinsic-widthcontain-intrinsic-heightcontainer-namecontainer-typecounter-*flex-*floatheightisolationjustify-selfleftorderorphansoutline-*(outline-offset除外,如前所述)overflow-anchoroverscroll-behavior-*pagepositionposition-anchorcontent-visibilityrightscroll-margin-*scroll-padding-*text-spacing-trimtopvisibilityxyruby-positionuser-selectwidthwill-changez-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> 元素应与 Permissions API 搭配使用。您可以监听多种事件:
onpromptdismiss:当用户关闭由元素触发的权限提示(例如,点击关闭按钮或点击提示之外的区域)时,系统会触发此事件。onpromptaction:当用户对该元素触发的权限提示执行某些操作来解决该提示时,系统会触发此事件。这并不一定意味着权限状态已更改,用户可能已执行某项操作来维持现状(例如继续允许使用某项权限)。onvalidationstatuschange:当元素从"valid"切换为"invalid"时,系统会触发此事件。如果浏览器信任信号的完整性(即用户点击该元素),则该元素被视为"valid";否则(例如,当该元素被其他 HTML 内容部分遮挡时),则被视为"invalid"。
您可以直接在 HTML 代码 (<permission type="…" onpromptdismiss="alert('The prompt was dismissed');" />) 中内嵌注册这些事件的事件监听器,也可以对 <permission> 元素使用 addEventListener(),如以下示例所示。
<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> 元素,请注册参与源代码试用。如需了解如何准备网站以使用源代码试用版,请参阅源代码试用版使用入门。源试用将从 Chrome 126 到 Chrome 131 进行(2025 年 2 月 19 日)。
演示
浏览 演示并查看 GitHub 上的源代码。下面是支持的浏览器中的体验的屏幕截图。

反馈
我们非常期待您分享 <permission> 在您的用例中的运作方式。您可以随时回复代码库中的问题,或提交新的问题。在 <permission> 元素的repo中发出公开信号,可让我们和其他浏览器知道您对该元素感兴趣。
常见问题解答
- 这与与 Permissions API 搭配使用的常规
<button>相比有何优势?点击<button>是一种用户手势,但浏览器无法验证它是否与请求权限的请求相关联。如果用户点击了<permission>,浏览器可以确定该点击与权限请求相关。这样一来,浏览器便能简化原本风险更高的流程。例如,允许用户轻松撤消对某项权限的屏蔽。 - 如果其他浏览器不支持
<permission>元素,该怎么办?<permission>元素可用作渐进增强功能。在不受支持的浏览器中,可以使用传统权限流程。例如,基于常规<button>的点击。权限团队也在开发 polyfill。为 GitHub 代码库添加星标,以便在该版本推出时收到通知。 - 是否与其他浏览器供应商讨论过此问题?2023 年,W3C TPAC 在一个分组讨论会中积极讨论了
<permission>元素。您可以阅读公开会话记录。Chrome 团队还要求这两家供应商提供正式的标准立场,请参阅相关链接部分。<permission>元素是我们与其他浏览器持续讨论的话题,我们希望对其进行标准化。 - 这实际上应该是一个空元素吗?我们仍在积极争论
<permission>是否应为空元素。如果您有反馈,请参与该问题的讨论。
相关链接
致谢
此文档由 Balázs Engedy、Thomas Nguyen、Penelope McLachlan、Marian Harbach、David Warren 和 Rachel Andrew 审核。