Existen varios métodos imperativos para solicitar permiso para usar funciones potentes, como el acceso a la ubicación, en las apps web. Estos métodos presentan una serie de desafíos, por lo que el equipo de permisos de Chrome está experimentando con un nuevo método declarativo: un elemento <permission>
HTML dedicado. Este elemento está en prueba de origen desde Chrome 126 y, en última instancia, esperamos estandarizarlo.
Métodos imperativos para solicitar permisos
Cuando las apps web necesitan acceso a funciones potentes, deben solicitar permiso. Por ejemplo, cuando Google Maps requiere la ubicación del usuario con la API de Geolocation, los navegadores le solicitan al usuario, a menudo con la opción de almacenar esa decisión. Este es un concepto bien definido en la especificación de permisos.
Solicitar de forma implícita en el primer uso en lugar de solicitarlo de forma explícita de antemano
La API de Geolocation es una API potente y se basa en el enfoque de solicitud implícita en el primer uso. Por ejemplo, cuando una app llama al método navigator.geolocation.getCurrentPosition()
, el mensaje de permisos aparece automáticamente en la primera llamada.
Otro ejemplo es navigator.mediaDevices.getUserMedia()
.
Otras APIs, como la API de notificaciones o la API de orientación y movimiento del dispositivo, suelen tener una forma explícita de solicitar permiso a través de un método estático, como Notification.requestPermission()
o DeviceMotionEvent.requestPermission()
.
Desafíos con los métodos imperativos para solicitar permisos
Spam de permisos
En el pasado, los sitios web podían llamar a métodos como navigator.mediaDevices.getUserMedia()
o Notification.requestPermission()
, pero también a navigator.geolocation.getCurrentPosition()
inmediatamente cuando se cargaba un sitio web. Aparecería un mensaje de permiso antes de que el usuario interactuara con el sitio web. Esto a veces se describe como spam de permisos y afecta a ambos enfoques, ya que se solicita de forma implícita en el primer uso y de forma explícita por adelantado.
Mitigación del navegador y requisito de gesto del usuario
El spam de permisos llevó a que los proveedores de navegadores exigieran un gesto del usuario, como hacer clic en un botón o un evento de tecla presionada, antes de mostrar un mensaje de permiso. El problema con este enfoque es que es muy difícil, si no imposible, que el navegador determine si un gesto determinado del usuario debe mostrar o no un mensaje de permiso. Tal vez el usuario solo estaba haciendo clic en la página con frustración porque esta tardaba mucho en cargar, o tal vez realmente estaba haciendo clic en el botón Localizarme. Algunos sitios web también se volvieron muy buenos para engañar a los usuarios y hacer que hagan clic en el contenido para activar la solicitud.
Otra mitigación es agregar mitigaciones de abuso de instrucciones, como bloquear por completo las funciones para comenzar o mostrar la solicitud de permiso de forma no modal y menos invasiva.
Contextualización de permisos
Otro desafío, especialmente en pantallas grandes, es la forma en que se suele mostrar el mensaje de permiso: sobre la línea de la muerte, es decir, fuera del área de la ventana del navegador en la que la app puede dibujar. No es raro que los usuarios no vean el mensaje en la parte superior de la ventana del navegador cuando acaban de hacer clic en un botón en la parte inferior de la ventana. Este problema suele empeorar cuando se implementan mitigaciones de spam del navegador.
No se puede deshacer fácilmente
Por último, es demasiado fácil para los usuarios llegar a un callejón sin salida. Por ejemplo, una vez que el usuario bloquea el acceso a una función, debe estar al tanto del menú desplegable de información del sitio, en el que puede Restablecer permisos o volver a activar los permisos bloqueados. En el peor caso, ambas opciones requieren una recarga completa de la página hasta que se aplique el parámetro de configuración actualizado. Los sitios no pueden proporcionar un atajo fácil para que los usuarios cambien un estado de permiso existente y deben explicarles con mucho cuidado cómo cambiar su configuración, como se muestra en la parte inferior de la siguiente captura de pantalla de Google Maps.
Si el permiso es clave para la experiencia, por ejemplo, el acceso al micrófono para una aplicación de videoconferencia, las apps como Google Meet muestran diálogos intrusivos que le indican al usuario cómo desbloquear el permiso.
Un elemento <permission>
declarativo
Para abordar los desafíos descritos en esta publicación, el equipo de permisos de Chrome lanzó una prueba de origen para un nuevo elemento HTML, <permission>
. Este elemento permite que los desarrolladores soliciten de forma declarativa permiso para usar, por ahora, un subconjunto de las funciones potentes disponibles para los sitios web. En su forma más simple, se usa como en el siguiente ejemplo:
<permission type="camera" />
Aún se debate activamente si <permission>
debe ser un elemento vacío o no. Un elemento nulo es un elemento de cierre automático en HTML que no puede tener ningún nodo secundario, lo que, en HTML, significa que puede no tener una etiqueta de cierre.
El atributo type
El atributo type
contiene una lista de permisos separados por espacios que solicitas. En el momento de escribir este artículo, los valores permitidos son 'camera'
, 'microphone'
y camera microphone
(separados por espacios). De forma predeterminada, este elemento se renderiza de manera similar a los botones con diseño de usuario-agente básico.
El atributo type-ext
En el caso de algunos permisos que permiten parámetros adicionales, el atributo type-ext
acepta pares clave-valor separados por espacios, como, por ejemplo, precise:true
para el permiso de geolocalización.
El atributo lang
El navegador proporciona el texto del botón y debe ser coherente, por lo que no se puede personalizar directamente. El navegador cambia el idioma del texto según el idioma heredado del documento o la cadena de elementos superior, o un atributo lang
opcional. Esto significa que los desarrolladores no necesitan localizar el elemento <permission>
por su cuenta. Si el elemento <permission>
avanza más allá de la etapa de prueba de origen, es posible que se admitan varias cadenas o íconos para cada tipo de permiso para aumentar la flexibilidad. Si te interesa usar el elemento <permission>
y necesitas una cadena o un ícono específicos, comunícate con nosotros.
Comportamiento
Cuando el usuario interactúa con el elemento <permission>
, puede alternar entre varias etapas:
Si no había permitido una función antes, puede permitirla en cada visita o permitirla solo en la visita actual.
Si antes había permitido la función, puede seguir permitiéndola o dejar de permitirla.
Si antes no permitió una función, puede seguir sin permitirla o permitirla esta vez.
El texto del elemento <permission>
se actualiza automáticamente según el estado. Por ejemplo, si se otorgó permiso para usar una función, el texto cambia para indicar que la función está permitida. Si primero se debe otorgar permiso, el texto cambia para invitar al usuario a usar la función. Compara la captura de pantalla anterior con la siguiente para ver los dos estados.
Diseño de CSS
Para garantizar que los usuarios puedan reconocer fácilmente el botón como una superficie para acceder a funciones potentes, se restringe el diseño del elemento <permission>
. Si las restricciones de diseño no funcionan para tu caso de uso, nos encantaría saber cómo y por qué. Si bien no se pueden satisfacer todas las necesidades de diseño, esperamos descubrir formas seguras de permitir más diseños del elemento <permission>
después de la prueba de origen. En la siguiente tabla, se detallan algunas propiedades a las que se les aplican restricciones
o reglas especiales. En caso de que se incumpla alguna de las reglas, el elemento <permission>
se inhabilitará y no se podrá interactuar con él. Cualquier intento de interactuar con él generará excepciones que se pueden detectar con JavaScript. El mensaje de error contendrá más detalles sobre la infracción detectada.
Propiedad | Reglas |
---|---|
|
Se puede usar para establecer el color del texto y del fondo, respectivamente. El contraste entre los dos colores debe ser suficiente para que el texto sea legible (proporción de contraste de al menos 3). El canal alfa debe ser 1. |
|
Se debe establecer dentro del equivalente de small y xxxlarge . De lo contrario, se inhabilitará el elemento. Se tendrá en cuenta el zoom cuando se calcule font-size . |
|
Los valores negativos se corregirán a 0 . |
margin (todo) |
Los valores negativos se corregirán a 0 . |
|
Los valores inferiores a 200 se corregirán a 200 . |
|
Los valores distintos de normal y italic se corregirán a normal . |
|
Los valores superiores a 0.5em se corregirán a 0.5em . Los valores inferiores a 0 se corregirán a 0 . |
|
Los valores que no sean inline-block y none se corregirán a inline-block . |
|
Los valores superiores a 0.2em se corregirán a 0.2em . Los valores inferiores a -0.05em se corregirán a -0.05em . |
|
Tendrá un valor predeterminado de 1em . Si se proporciona, se considerará el valor máximo calculado entre los valores predeterminados y los proporcionados. |
|
Tendrá un valor predeterminado de 3em . Si se proporciona, se considerará el valor mínimo calculado entre los valores predeterminados y los proporcionados. |
|
Tendrá un valor predeterminado de fit-content . Si se proporciona, se considerará el valor máximo calculado entre los valores predeterminados y los proporcionados. |
|
Tendrá un valor predeterminado de tres veces fit-content . Si se proporciona, se considerará el valor mínimo calculado entre los valores predeterminados y los proporcionados. |
|
Solo tendrá efecto si height se establece como auto . En este caso, los valores superiores a 1em se corregirán a 1em y padding-bottom se establecerá en el valor de padding-top . |
|
Solo tendrá efecto si width se establece como auto . En este caso, los valores superiores a 5em se corregirán a 5em y padding-right se establecerá en el valor de padding-left. . |
|
No se permitirán los efectos visuales distorsionantes. Por ahora, solo aceptamos la traducción 2D y el aumento proporcional. |
Las siguientes propiedades de CSS se pueden usar de forma normal:
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
(y todas las propiedadesborder-*
)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-*
(con la excepción que se indicó antes paraoutline-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
Además, se pueden usar todas las propiedades lógicamente equivalentes (por ejemplo, inline-size
es equivalente a width
), siguiendo las mismas reglas que sus equivalentes.
Seudoclases
Existen dos pseudoclases especiales que permiten aplicar diseño al elemento <permission>
según el estado:
:granted
: La pseudoclase:granted
permite aplicar diseños especiales cuando se otorga un permiso.:invalid
: La pseudoclase:invalid
permite aplicar diseños especiales cuando el elemento está en un estado no válido, por ejemplo, cuando se entrega en un iframe de origen cruzado.
permission {
background-color: green;
}
permission:granted {
background-color: light-green;
}
/* Not supported during the origin trial. */
permission:invalid {
background-color: gray;
}
Eventos de JavaScript
El elemento <permission>
se debe usar junto con la API de Permissions.
Hay varios eventos que se pueden escuchar:
onpromptdismiss
: Este evento se activa cuando el usuario descarta el mensaje de permiso que activó el elemento (por ejemplo, haciendo clic en el botón de cierre o fuera del mensaje).onpromptaction
: Este evento se activa cuando el usuario resuelve el mensaje de permiso activado por el elemento realizando alguna acción en el mensaje. Esto no significa necesariamente que el estado del permiso haya cambiado, ya que el usuario podría haber realizado una acción que mantenga el statu quo (como seguir permitiendo un permiso).onvalidationstatuschange
: Este evento se activa cuando el elemento cambia de"valid"
a"invalid"
. El elemento se considera"valid"
cuando el navegador confía en la integridad del indicador si el usuario hace clic en él y"invalid"
de lo contrario, por ejemplo, cuando otro contenido HTML ocluye parcialmente el elemento.
Puedes registrar objetos de escucha de eventos para estos eventos directamente intercalados en el código HTML (<permission type="…" onpromptdismiss="alert('The prompt was dismissed');" />
) o con addEventListener()
en el elemento <permission>
, como se muestra en el siguiente ejemplo.
<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>
Detección de atributos
Si un navegador no admite un elemento HTML, no lo mostrará. Esto significa que, si tienes el elemento <permission>
en tu código HTML, no sucederá nada si el navegador no lo conoce. Es posible que desees detectar la compatibilidad con JavaScript, por ejemplo, para crear un mensaje de permiso activado con un clic en un <button>
normal.
if ('HTMLPermissionElement' in window) {
// The `<permission>` element is supported.
}
Prueba de origen
Para probar el elemento <permission>
en tu sitio con usuarios reales,
regístrate en la prueba de origen.
Lee Comienza a usar las pruebas de origen para obtener instrucciones sobre cómo preparar tu sitio para usar las pruebas de origen. La prueba de origen se ejecutará de la versión 126 a la 131 de Chrome (19 de febrero de 2025).
Demostración
Explora la demo y consulta el código fuente en GitHub. Esta es una captura de pantalla de la experiencia en un navegador compatible.
Comentarios
Nos encantaría saber cómo funciona <permission>
en tu caso de uso. No dudes en responder a uno de los problemas del repositorio o en presentar uno nuevo. Los indicadores públicos en el repo del elemento <permission>
nos permitirán a nosotros y a otros navegadores saber que te interesa.
Preguntas frecuentes
- ¿En qué se diferencia de un
<button>
normal vinculado a la API de Permissions? Un clic en un<button>
es un gesto del usuario, pero los navegadores no tienen forma de verificar que esté conectado a la solicitud para solicitar permiso. Si el usuario hizo clic en un<permission>
, el navegador puede asegurarse de que el clic esté relacionado con una solicitud de permiso. Esto permite que el navegador facilite flujos que, de otro modo, serían mucho más riesgosos. Por ejemplo, permitir que el usuario deshaga fácilmente el bloqueo de un permiso. - ¿Qué sucede si otros navegadores no son compatibles con el elemento
<permission>
? El elemento<permission>
se puede usar como mejora progresiva. En los navegadores que no son compatibles, se puede usar un flujo de permisos clásico. Por ejemplo, según el clic de un<button>
normal. El equipo de permisos también está trabajando en un polyfill. Destaca el repositorio de GitHub para recibir una notificación cuando esté listo. - ¿Se habló de esto con otros proveedores de navegadores? El elemento
<permission>
se analizó de forma activa en el TPAC del W3C en 2023 en una sesión grupal. Puedes leer las notas de la sesión pública. El equipo de Chrome también solicitó posiciones formales sobre los estándares a ambos proveedores. Consulta la sección Vínculos relacionados. El elemento<permission>
es un tema en discusión con otros navegadores, y esperamos estandarizarlo. - ¿Debe ser un elemento nulo? Aún se está debatiendo activamente si
<permission>
debe ser un elemento vacío o no. Si tienes comentarios, comunícate con el equipo sobre el problema.
Vínculos relacionados
- Explicaciones
- Posición de WebKit con respecto a los estándares
- Posición de Mozilla sobre los estándares
Agradecimientos
Este documento fue revisado por Balázs Engedy, Thomas Nguyen, Penelope McLachlan, Marian Harbach, David Warren y Rachel Andrew.