CSS :scope Pseudoclase
La pseudoclase CSS :scope representa los elementos de ámbito. Lee sobre ella y practica con ejemplos.
La pseudoclase CSS :scope coincide con el elemento contra el que se resuelve un selector — su elemento de referencia. En consultas DOM simples, ese elemento de referencia es el elemento sobre el que llamas al método de consulta; dentro de un Shadow DOM, es la raíz del shadow.
Esta página explica qué significa "ámbito" para un selector, por qué :scope es principalmente una herramienta de JavaScript en lugar de una herramienta de hoja de estilos, los dos lugares principales donde cambia el comportamiento y los problemas a tener en cuenta.
Qué es el elemento de referencia
Cada selector se evalúa de forma relativa a algún elemento. Cuando escribes CSS en una hoja de estilos, el elemento de referencia es la raíz del documento, por lo que :scope equivale a :root y raramente es útil por sí solo.
:scope cobra significado cuando el elemento de referencia no es la raíz — principalmente cuando consultas el DOM desde JavaScript:
element.querySelector(selector)yelement.querySelectorAll(selector)resuelven el selector contraelement. Aquí:scopehace referencia al propioelement.- Los métodos de consulta de un
ShadowRootutilizan la raíz del shadow como elemento de referencia.
Sin :scope, un selector pasado a element.querySelector() aún se evalúa contra el subárbol completo, sin anclarse a element. Esto sorprende a muchos desarrolladores — véase el problema habitual a continuación.
Por qué usarlo
La razón principal para recurrir a :scope es anclar un selector al elemento que estás consultando, de modo que puedas seleccionar hijos directos o expresar "relativo a aquí":
// Match only sections that are direct children of container.
container.querySelectorAll(':scope > section');:scope tiene sentido dentro de los métodos de consulta listados anteriormente (querySelector, querySelectorAll y la comprobación en vivo Element.matches()). No tiene ningún efecto especial en closest() ni en reglas de hoja de estilos normales.
Nota: el antiguo atributo <style scoped>, que en su momento permitía que un bloque <style> se aplicara únicamente dentro de su elemento padre, fue eliminado de los navegadores. El ámbito de estilos hoy en día se hace con Shadow DOM (o herramientas de compilación), y :scope sobrevive como ayudante para consultas DOM.
Versión
Sintaxis
En una hoja de estilos, la sintaxis es la misma que la de cualquier otra pseudoclase:
:scope {
/* declarations — equivalent to :root in a normal stylesheet */
}En JavaScript se pasa dentro de la cadena del selector:
element.querySelectorAll(':scope > .child');Ejemplo: anclar una consulta a su elemento
En el ejemplo siguiente, container.querySelector(':scope > section') selecciona únicamente el <section> que es un hijo directo de .container. La sección seleccionada cambia de color para confirmar que la consulta la encontró.
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
<style>
.container {
margin: 40px auto;
max-width: 700px;
background-color: #eeeeee;
padding: 20px;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.25);
}
section {
padding: 30px;
}
</style>
</head>
<body>
<h2>:scope selector example</h2>
<div class="container">
<section>
<p>
Inside the scope.
</p>
</section>
</div>
<script>
const container = document.querySelector('.container');
const scopeElement = container.querySelector(':scope > section');
scopeElement.style.backgroundColor = '#1c87c9';
scopeElement.style.color = '#fff';
</script>
</body>
</html>Problema habitual: seleccionar hijos directos
La razón más común para usar :scope es seleccionar los hijos inmediatos del elemento que estás consultando. Un combinador como > .x no puede aparecer solo — element.querySelector('> .x') lanza un SyntaxError. Se necesita un lado izquierdo, y :scope lo proporciona:
<ul id="list">
<li>A</li>
<li>
<ul>
<li>B (nested)</li>
</ul>
</li>
</ul>const list = document.getElementById('list');
// SyntaxError — "> li" is not a complete selector:
// list.querySelectorAll('> li');
// Correct: only the direct <li> children of #list (A and the one wrapping the nested list),
// NOT "B (nested)".
list.querySelectorAll(':scope > li');Sin :scope, list.querySelectorAll('li') también devolvería el elemento anidado B, porque un selector de descendientes simple alcanza todo el subárbol. :scope > es la forma idiomática de decir "hijos directos del elemento que estoy consultando".
Compatibilidad con navegadores
:scope es compatible con todos los navegadores modernos para los métodos de consulta del DOM. No tiene ningún efecto como regla de estilo en una hoja de estilos normal más allá de comportarse como :root.
Capítulos relacionados
- CSS Selectors — la referencia completa de selectores.
- CSS Selector — fundamentos de la sintaxis de selectores.