Guía educativa de selectores de semántica del documento
Selecciona lo que el documento significa
Compara idioma, dirección, definición y niveles de encabezado sin confundir atributos, estilos y semántica calculada.
Modelo mental
Estas pseudoclases consultan información que el navegador obtiene del documento; el atributo visible no siempre cuenta toda la historia.
:lang() · :dir()Valores efectivos
:lang() puede coincidir por herencia o por una variante regional. :dir() consulta la dirección semántica heredada o calculada con dir="auto", no la propiedad CSS direction.
:definedUn estado que cambia de verdad
Los elementos HTML integrados ya están definidos. Un custom element pasa a :defined cuando se registra; ese nombre no puede desregistrarse y el reinicio usa otro.
:heading · :heading()Encabezado semántico
:heading selecciona elementos con nivel de encabezado; :heading() filtra niveles enteros, incluso varios separados por comas. Su soporte todavía es experimental.
headingoffset · headingreset · aria-levelNivel HTML, etiqueta y ARIA
HTML permite desplazar o reiniciar el nivel con headingoffset y headingreset, por lo que el nivel puede diferir de h1–h6. aria-level expresa semántica de accesibilidad, pero no convierte por sí solo un div en coincidencia de estos selectores. Safari 27.2 aún seleccionó un h1 desplazado como nivel 1; la demo usa encabezados nativos sin offset.
Idioma y dirección
Compara el valor semántico efectivo con los atributos escritos en cada elemento.
:lang()
:lang(<language-range>)Elementos cuyo idioma efectivo coincide con el rango indicado.
Especificidad(0, 1, 0)
:lang()
:lang(<language-range>)Comportamiento
- El idioma puede heredarse de un ancestro aunque el elemento no tenga atributo lang.
- :lang(fr) también abarca variantes regionales como fr-CA; lang="en" explícito interrumpe esa herencia.
Ejemplos
:lang(fr)Coincide: <section lang="fr">
Coincide: <p>Bonjour</p>
<p lang="en">Hello</p>
</section>:lang(fr)Coincide: <div lang="fr-CA">
Coincide: <p>Salut</p>
</div>Errores frecuentes
- No equivale a [lang="fr"], que solo compara un atributo presente en el propio elemento.
- El idioma no se deduce del texto visible: lo determina el idioma asignado al elemento.
:dir()
:dir(ltr | rtl)Elementos con la dirección semántica efectiva solicitada.
Especificidad(0, 1, 0)
:dir()
:dir(ltr | rtl)Comportamiento
- Un descendiente puede heredar rtl sin tener dir="rtl" en su propia etiqueta.
- dir="auto" calcula la dirección desde el contenido; el texto árabe del ejemplo da rtl.
Ejemplos
:dir(rtl)Coincide: <div dir="rtl">
Coincide: <p>مرحبا</p>
<p dir="ltr">Hello</p>
</div>:dir(rtl)<div dir="ltr">
Coincide: <p dir="auto">مرحبا</p>
<p dir="auto">Hello</p>
</div>Errores frecuentes
- No equivale a [dir="rtl"], que solo encuentra atributos explícitos.
- La propiedad CSS direction cambia la presentación, pero no el resultado de :dir().
Definición del elemento
Observa la diferencia entre HTML integrado y un custom element antes y después de registrarlo.
:defined
Elementos integrados y custom elements que ya tienen una definición registrada.
Especificidad(0, 1, 0)
:defined
Comportamiento
- Un botón HTML integrado coincide desde el principio; un custom element autónomo empieza sin definir.
- Tras customElements.define(), el mismo nodo pasa a coincidir. El segundo ejemplo representa ese momento posterior.
Ejemplos
button:defined<div>
Coincide: <button type="button">Botón integrado</button>
<demo-card>Pendiente</demo-card>
</div>demo-card:defined<!-- after customElements.define("demo-card", ...) -->
Coincide: <demo-card>Definido</demo-card>Errores frecuentes
- No significa que el elemento sea válido, visible o que su contenido haya terminado de cargar.
- customElements.define() no puede deshacerse para el mismo nombre: la demo reinicia con un nombre nuevo.
Encabezados y niveles
Los ejemplos muestran la intención de Selectors Level 5; el playground solo cuenta coincidencias si este navegador las produce de forma nativa.
:heading
Elementos con nivel de encabezado según la semántica del lenguaje del documento.
Especificidad(0, 1, 0)
:heading
Comportamiento
- La forma sin paréntesis abarca todos los niveles de encabezado y aporta especificidad (0, 1, 0).
- Un div con role="heading" y aria-level no pasó el matching nativo observado; la demo usa h1–h3.
Ejemplos
:heading<section>
Coincide: <h1>Título principal</h1>
Coincide: <h2>Título de sección</h2>
<p>Contenido</p>
</section>:heading<section>
<div role="heading" aria-level="2">Texto con rol de encabezado ARIA</div>
Coincide: <h3>Título de apartado</h3>
</section>Errores frecuentes
- No asumir que el rol ARIA hace coincidir un elemento arbitrario con :heading.
- No confundir sintaxis parseable con soporte de matching CSS y DOM.
Soporte y compatibilidad
Prueba del 25-09-2026: Safari 27.2 coincidió; Firefox 156, incluso con la preferencia activada, y Chrome 153 rechazaron esta forma. El playground exige una coincidencia nativa positiva.
:heading()
:heading(<integer>#)Encabezados cuyo nivel semántico pertenece a la lista de enteros indicada.
Especificidad(0, 1, 0)
:heading()
:heading(<integer>#)Comportamiento
- :heading(2) filtra el nivel 2; :heading(1, 2) admite varios niveles en una sola forma funcional.
- La pseudoclase aporta (0, 1, 0); añadir un tipo como h2 aporta también (0, 0, 1).
Ejemplos
:heading(2)<section>
<h1>Título principal</h1>
Coincide: <h2>Título de sección</h2>
<h3>Título de apartado</h3>
</section>:heading(1, 2)<article>
Coincide: <h1>Título principal</h1>
Coincide: <h2>Título de sección</h2>
<h3>Título de apartado</h3>
</article>Errores frecuentes
- No admite una lista vacía ni nombres como :heading(foo): requiere enteros.
- HTML define niveles desplazados con headingoffset, pero Safari 27.2 aún no los aplicó al matching observado. No se simula ese caso.
Soporte y compatibilidad
Prueba del 25-09-2026: Safari 27.2 coincidió con :heading(2); Firefox 156 con preferencia y Chrome 153 lo rechazaron. El playground prueba cada nivel elegido con un encabezado nativo.