针对新 HTML <permission> 元素的源试用

您可以使用多种命令式方法请求权限,以便在 Web 应用中使用强大的功能(如位置信息使用权)。这些方法面临着诸多挑战,因此 Chrome 权限团队正在尝试一种新的声明式方法:专用的 HTML <permission> 元素。从 Chrome 126 开始,此元素正处于源试用阶段,我们最终希望将其标准化。

请求权限的命令式方法

当 Web 应用需要访问强大功能时,需要申请相应权限。例如,当 Google 地图使用 Geolocation API 请求用户的位置信息时,浏览器会提示用户,并且通常会提供存储该决定的选项。这是“权限”规范中明确定义的概念

首次使用时隐式询问与预先明确请求

Geolocation API 是一个功能强大的 API,依赖于首次使用时隐式询问的方法。例如,当应用调用 navigator.geolocation.getCurrentPosition() 方法时,权限提示会在首次调用时自动弹出。另一个示例是 navigator.mediaDevices.getUserMedia()

其他 API(例如 Notification APIDevice Orientation and Motion API)通常可以通过 Notification.requestPermission()DeviceMotionEvent.requestPermission() 等静态方法明确请求权限。

对请求权限的命令式方法存在挑战

权限无效

过去,网站可以调用 navigator.mediaDevices.getUserMedia()Notification.requestPermission() 等方法,但在加载网站时也可以立即调用 navigator.geolocation.getCurrentPosition()。在用户与网站互动之前,系统会弹出权限提示。这有时被描述为权限垃圾,对这两种方法都有影响,它们会在首次使用时隐式询问,也会明确预先请求。

加载网站时显示的麦克风权限提示。

浏览器缓解措施和用户手势要求

垃圾权限导致浏览器供应商要求用户手势(例如按钮点击或 keydown 事件)才会显示权限提示。这种方法的问题在于,即使并非不可能,浏览器也很难确定给定的用户手势是否应显示权限提示。或许用户只是因为网页加载时间过长而感到沮丧地点击页面,也可能是他们确实点击了找到我按钮。一些网站还非常善于诱骗用户点击内容来触发提示。

另一种缓解措施是添加即时滥用缓解措施,例如完全阻止功能开始,或以非模态、干扰较小的方式显示权限提示。

Chrome 浏览器,显示了

权限上下文

另一个挑战(尤其是在大屏幕上)是权限提示的常用显示方式:在终止线上方,即应用可绘制到的浏览器窗口区域之外。用户只是点击窗口底部的按钮时,会错过浏览器窗口顶部的提示,这并不奇怪。实施浏览器垃圾内容缓解措施后,该问题通常会加剧。

打开了位置信息权限提示的 Google 地图。触发提示的位置信息使用权按钮很远。

无法轻松撤消

最后,用户太容易进入死胡同。例如,用户禁止访问某项功能后,就需要知道网站信息下拉列表,他们可以在其中重置权限或将被屏蔽的权限重新开启。在最坏的情况下,这两个选项都需要完全重新加载页面,直到更新后的设置生效。网站无法为用户提供更改现有权限状态的简单快捷方式,而且必须向用户费力地解释如何更改其设置,如以下 Google 地图屏幕截图底部所示。

Chrome 网站可在 Google 地图上使用控件撤消权限。

如果权限对用户体验至关重要(例如视频会议应用的麦克风使用权限),Google Meet 等应用会显示侵入性对话框,以指导用户如何取消屏蔽权限。

关于如何打开 Chrome 网站控件的 Google Meet 说明。

声明式 <permission> 元素

为了应对这篇博文中所描述的挑战,Chrome 权限团队启动了针对新 HTML 元素 <permission> 的源试用。此元素允许开发者以声明方式请求权限,以便目前使用网站可用的部分强大功能。您可以采用最简单的形式来使用它,如以下示例所示:

<permission type="camera" />

对于 <permission> 是否应为 void 元素,目前仍处于积极讨论。空元素是 HTML 中的自闭合元素,它不能包含任何子节点;在 HTML 中,这意味着它可能没有结束标记。

type 属性

type 属性包含您要请求的权限列表(以空格分隔)。在撰写本文时,允许的值包括 'camera''microphone'camera microphone(以空格分隔)。默认情况下,此元素的呈现效果类似于采用准用户代理样式的按钮。

各种权限元素按钮,包括摄像头、麦克风和摄像头以及麦克风权限。

type-ext 属性

对于某些允许使用额外参数的权限,type-ext 属性接受以空格分隔的键值对,例如用于地理定位权限的 precise:true

lang 属性

按钮文字由浏览器提供,旨在保持一致,因此无法直接自定义。浏览器会根据继承的文档或父元素链的语言或可选的 lang 属性更改文本的语言。这意味着开发者无需自行本地化 <permission> 元素。如果 <permission> 元素进入原始试用阶段之后,则可以针对每种权限类型支持多个字符串或图标,以提高灵活性。如果您有兴趣使用 <permission> 元素并需要特定字符串或图标,请与我们联系

行为

当用户与 <permission> 元素互动时,他们可以循环经历各个阶段:

  • 如果他们之前未允许访问某个功能,则可以在每次访问时都允许,或者在当前访问中允许该功能。

    权限提示,让您在本次或每次访问时都允许使用某项功能。

  • 如果用户之前曾允许使用该功能,则可以继续允许,也可以不再允许。

    权限提示:继续允许或不再允许。

  • 如果他们之前禁止过某项功能,则可以继续不允许或者这次允许该功能。

    权限提示,表示不允许或允许这次继续。

<permission> 元素的文本会根据状态自动更新。例如,如果已授予某项功能的使用权限,文本会更改为允许该功能。如果首先需要授予权限,文本会更改以邀请用户使用此功能。将之前的屏幕截图与下面的屏幕截图进行比较,了解两种状态。

带有相关文本的权限按钮

CSS 设计

为了确保用户能够轻松地将按钮识别为使用强大功能的 Surface,我们对 <permission> 元素的样式进行了限制。如果样式限制不适用于您的用例,我们很乐意了解具体方法和原因!虽然并非所有样式需求都可以得到满足,但我们希望在源试用结束后找到一些安全的方法,以允许对 <permission> 元素进行更多样式设置。下表详细说明了一些应用了限制或特殊规则的属性。如果违反了任何规则,<permission> 元素将被停用,并且无法与之交互。任何尝试与其交互都会导致可由 JavaScript 捕获的异常。错误消息中将包含有关检测到的违规行为的更多详细信息。

属性 规则

colorbackground-color

可用于分别设置文本和背景颜色。这两种颜色的对比度必须足够大,以确保文字清晰可辨(对比度至少为 3)。Alpha 渠道的值必须为 1。

font-sizezoom

必须在 smallxxxlarge 的等效项内设置。否则,该元素将被停用。在计算 font-size 时,系统会考虑缩放。

outline-offset

负值将更正为 0
margin(所有) 负值将更正为 0

font-weight

200”下的值将更正为“200”。

font-style

normalitalic 以外的值将更正为 normal

word-spacing

超过 0.5em 的值将更正为 0.5em0 下的值将更正为 0

display

inline-blocknone 以外的值将更正为 inline-block

letter-spacing

超过 0.2em 的值将更正为 0.2em-0.05em 下的值将更正为 -0.05em

min-height

默认值为 1em。如果提供,将考虑默认值和所提供的值之间的最大值。

max-height

默认值为 3em。如果提供,将考虑默认值和所提供的值之间的最小计算值。

min-width

默认值为 fit-content。如果提供,将考虑默认值和所提供的值之间的最大计算值。

max-width

默认值为 fit-content 的三倍。如果提供,将考虑默认值和所提供值之间的最小计算值。

padding-top

只有在 height 设置为 auto 时才会生效。在这种情况下,超过 1em 的值将更正为 1empadding-bottom 将设置为 padding-top 的值。

padding-left

只有在 width 设置为 auto 时才会生效。在这种情况下,超过 5em 的值将更正为 5empadding-right 将设置为 padding-left. 的值

transform

不允许扭曲视觉效果。目前,我们只接受 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> 元素应与 Permissions API 结合使用。可监听多种事件:

  • onpromptdismiss:当用户关闭由元素触发的权限提示时(例如,通过点击关闭按钮或在提示以外的位置点击),会触发此事件。

  • onpromptaction:如果用户对提示本身采取了某种操作,从而解决了由元素触发的权限提示,则会触发此事件。这并不一定意味着权限状态发生了变化,用户可能采取了维持现状的操作(例如继续允许某项权限)。

  • onvalidationstatuschange:当元素从 "valid" 切换为 "invalid" 时会触发此事件。如果用户点击信号时浏览器信任该信号的完整性,该元素会被视为 "valid";否则,会被视为 "invalid"(例如,当元素被其他 HTML 内容部分遮挡)。

您可以直接以内嵌方式在 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> 元素的代码库中的公开信号可让我们和其他浏览器知道您对该元素感兴趣。

常见问题解答

  • 这比将常规 <button> 与 Permissions API 结合使用有何优势?点击 <button> 是一种用户手势,但浏览器无法验证它是否已关联到请求权限的请求。如果用户点击了 <permission>,浏览器可以确定该点击与权限请求相关。这样,浏览器就可以推进风险更高的流程。例如,让用户能够轻松撤消权限屏蔽操作。
  • 如果其他浏览器不支持 <permission> 元素,该怎么办?<permission> 元素可用作渐进式增强。在不支持的浏览器上,可以使用传统权限流程。例如,基于常规 <button> 的点击。权限团队也在处理 polyfill。为 GitHub 代码库加注星标,以便在其准备就绪时收到通知。
  • 您是否与其他浏览器供应商讨论过此问题?2023 年的 W3C TPAC 已在分组会议中积极讨论了 <permission> 元素。您可以阅读公开会话说明。Chrome 团队还曾要求这两个供应商提供正式的标准排名,具体请参阅相关链接部分。我们一直在与其他浏览器讨论 <permission> 元素,我们希望将其标准化。
  • 这实际上应该是空元素吗?对于 <permission> 是否应为 void 元素,我们仍然有争议。如果您有反馈意见,请就相应问题进行说明。

致谢

本文档由 Balázs EngedyThomas NguyenPenelope McLachlanMarian HarbachDavid WarrenRachel Andrew 审核。