Probador de Selectores CSS4 en Web Tools online

Figura
Figura. Probador de Selectores CSS4 en la herramienta Web Tools online

En la serie de temas que publiqué en enero 2013 sobre Selectores CSS se presentaban unos ejemplos interactivos para poner en práctica los distintos conceptos sobre selectores CSS nivel 3. Ahora agrupo todos esos ejemplos en esta herramienta, incluyendo algunas mejoras, especialmente en lo que se refiere a los pseudoelementos y las pseudoclases estructurales.

El documento W3C Selectors Level 3, que pasó a fase REC (Recommendation) el 06/11/2018, contiene la especificación de los selectores CSS. Lo expuesto en aquella serie de temas sobre selectores CSS y en esta nueva herramienta sigue lo expuesto en ese estándar. Actualmente se encuentra publicado el W3C Selectors Level 4 en fase WD (Working Draft). Este nuevo estándar contiene muchas cosas nuevas que quiero ir probando, permitiéndome la herramienta creada poner en práctica esas nuevas propiedades más fácilmente.

La captura de la herramienta de la Figura contiene los siguientes paneles:

  • Un desplegable en la parte superior con el que podemos seleccionar una sección entre las siguientes, secciones que siguen las expuestas en el borrador de la especificación de nivel 4:
  • Un planel lateral izquierdo con el HTML con elementos sobre los que se ejecutará el ejemplo. Generalmente los elementos seleccionados tendrán fondo amarillo y borde de color rojo.
  • Un panel lateral derecho con opciones para elegir y ejecutar un ejemplo de selector.
  • Un panel con fondo amarillo y texto que da información sobre el ejemplo. Estos textos aparecen en el resto de apartados de esta página.
  • Un panel inferior con fondo verde con el CSS en ejecución. Un botón permitirá modificar ese código y ejecutarlo.

Selectores CSS nivel 4

Figura
Figura. Web tools online: herramienta para probar selectores CSS

Se incluyen y prueban todos los selectores de CSS3 y los nuevos de CSS4, la especificación de CSS nivel 4, borrador en fase WD (Working Draft) del 21 de noviembre de 2018. Es el vigente en la fecha en que hago estas pruebas, octubre 2020. Muchas de las nuevas propiedades ya han sido acogidas por los navegadores. Pero no hay que olvidar que está en fase de borrador y que es posible que sufra cambios.

En est sección inicial se presentan los tipos de selectores simples. Los ejemplos se ejecutan en un contenedor <div id="x">. Tras seleccionar un ejemplo se inserta el código CSS en el HEAD de la página, actualizándose el estilo correspondiente.

En la Figura se observa una captura de pantalla de la herramienta en esta sección de selectores. En la parte derecha de la imagen se observan los distintos ejemplos que podemos ejecutar. En la parte izquierda tenemos el contenedor div#x con elementos en su interior que serán objeto de los distintos ejemplos de selección.

Cuando se capturó la imagen se estaba aplicando el selector div#x div con el estilo CSS siguiente:

div#x div {
    border: solid red 1px;
    background-color: yellow;
}

El selector universal se escribe con "*". Con div#x * se seleccionan todos los elementos dentro del contenedor <div id="x">.

El selector de tipo de elemento filtra por el Tag o etiqueta HTML del elemento. En este ejemplo con div#x div se seleccionan todos los DIV dentro del contenedor <div id="x">.

Un grupo o lista de selectores simples puede concatenarse con comas. En este ejemplo con div#x div, div#x p seleccionamos los DIV y los P dentro del contenedor <div id="x">.

El selector de identificador filtra elementos por su atributo id. Con div#x div#y seleccionamos el elemento <div id="y"> dentro del contenedor <div id="x">. Dado que el identificador es único en una página, el selector puede reducirse a div#y.

Podemos obviar el elemento y poner el selector universal *#y significando que se selecciona cualquier elemento con ese identificador id="y". E incluso podemos obviar también el asterisco poniendo #y entendiéndose entonces que el asterisco está implícito. De esta forma con div#x #y seleccionamos un elemento con identificador id="y" dentro del contenedor <div id="x">. Dado que el identificador es único en una página, el selector puede reducirse a #y.

El selector de clase filtra elementos por su atributo class. En ese atributo pueden ponerse varios nombres de clases separados por espacio, como se observa si tenemos los elementos <p class="z"> y <p class="a z b"> y usamos el selector div#x p.z. Se seleccionan un P con class="z" y otro class="a z b" pues contiene también el nombre de clase "z".

Con div#x .z podemos usar el selector universal *.z o bien obviarlo con .z. Puede ser aconsejable no obviarlo, pues si omitiéramos el espacio en div#x .z quedaría div#x.z (sin espacios), que es un selector diferente: DIV con id="x" y class="z".

El selector de atributo filtra un elemento que tenga un atributo con un valor. Con div#x span[data-att=abc] seleccionamos el elemento con atributo data-att="abc". En el selector podemos obviar las comillas si la cadena de texto no contiene espacios.

En este caso con div#x [data-att] filtramos elementos que tengan un atributo data-att sea cual sea su valor. Vea que [data-att] significa que usamos el selector universal *[data-att]. Pero si ignoramos el espacio quedaría div#x[data-att] que es otra cosa. Por eso quizás es recomendable no omitir el selector universal para que el selector se puede leer más fácilmente.

El selector de pseudoclase filtra por otros criterios. Con div#x div:first-child se busca un DIV que sea primer hijo en su contenedor. Se separan con ":".

El selector de pseudoelemento genera un elemento con un contenido de texto. Con div#x div:last-child::after se genera el texto "AFTER" después de un último DIV en el contenedor div#x.

Los pseudoelementos se separan con "::" para diferenciarlo de las pseudoclases. Aunque aún CSS2 permite usar ":" para los pseudoelementos, deberíamos usar la nueva nomenclatura.

Combinadores

Figura
Figura. Combinadores: div#x div div

La sección de combinadores expone como podemos combinar dos selectores usando caracteres como " " (uno o más espacios), ">", "+" y "~".

El combinador espacio selecciona descendientes. Con div#x div seleccionamos todos los DIV descendientes de div#x en cualquier nivel donde se encuentren.

Con div#x div div seleccionamos todos los DIV descendientes de div#x a partir del segundo nivel donde se encuentren. En la Figura se observa el contenedor div#x con esta selección.

Usando la pseudoclase de negación con div#x *:not(div) seleccionamos cualquier descendiente de div#x que no sea un DIV. Selecciona BLOCKQUOTE, P1, P2 y P3.

Con div#x > div usamos el combinador ">", seleccionando todos los DIV hijos directos o de primer nivel de div#x. Selecciona DIV1 y DIV5 que son hijos directos de div#x.

Con div#x > div > p seleccionamos los DIV de primer nivel y dentro de ellos los P de primer nivel. Selecciona DIV1 y DIV5 que están en primer nivel y dentro de ellos P2 y P3 en primer nivel, pero no selecciona P1 pues no está en primer nivel en DIV1.

Con div#x div + p usamos el combinador "+" de hermanos adyacentes. Selecciona los P que son precedidos inmediatamente por un hermano DIV. Selecciona P1 pues le precede DIV3, pero no selecciona P2 pues le precede BLOCKQUOTE. Ni P3 pues no le precede ningún elemento (es el primer hijo de DIV5).

Con div#x div + *:not(p) seleccionamos elementos que no sean P precedidos inmediato por un DIV. Selecciona BLOCKQUOTE pues le precede DIV2. Selecciona DIV5 pues le precede DIV1. El resto que no son P no son precedidos inmediato por un DIV.

Con div#x div ~ p usamos el combinador "~" de hermanos generales. Selecciona los P que son precedidos por un hermano DIV no necesariamente de forma inmediata. Selecciona P1 pues le precede DIV3 y P2 pues le precede DIV2, aunque no de forma inmediata. No selecciona P3 pues no le precede ningún DIV.

Combinaciones lógicas

Figura
Figura. Combinaciones lógicas: div#x p, div#x em

En esta sección de combinaciones lógicas se contemplan selecciones basadas en lógicas de unión separando con comas una lista de selectores, negaciones con :not() y otras de CSS nivel 4 como :is, :where y :has.

Una lista de selectores se separa por comas. Ejecuta la selección de todos los selectores de la lista. Con div#x p, div#x em se seleccionan los P y EM existentes en el contenedor DIV con id="x". En la Figura se observa esta selección.

Con div#x *:not(p) usamos la pseudoclase de negación del elemento P, seleccionando todos los elementos que no sean P.

Si iteramos la negación en diversos elementos podemos componer una lista. Con div#x *:not(div):not(span) seleccionamos todos los elementos que no sean DIV y, de ellos, los que no sean SPAN.

Con CSS4 usando una lista negada podemos simplificar el ejemplo anterior. Usando div#x *:not(div, span) incluiremos una lista de selectores que queremos negar. En octubre 2020 sólo Safari lo soporta.

La pseudoclase :is() de CSS4 selecciona todas las coincidencias con la lista de selectores. El uso de :is() nos evita simplificar una lista de selectores. Compare este código div#x *:is(p, em) con el del primer ejemplo div#x p, div#x em, evitándose repetir div#x en cada item de la lista. En octubre 2020 lo soporta Firefox y Safari.

La pseudoclase :where() de CSS4 trata de ajustar la especificidad del selector. Para diferenciarlo de :is(), usaremos el ejemplo div#x *:where(div.a) abbr, div#x *:is(div.b) abbr que selecciona elementos ABBR que se incluyen en dos DIV con clases "a" y "b" respectivamente.

div#x *:where(div.a) abbr, div#x *:is(div.b) abbr {
    border: solid red 1px;
    background-color: yellow;
}
div#x * abbr {
    border: blue solid 1px;
    background-color: lightblue;
}

El primer selector de la lista del ejemplo usa :where(div.a) que está dentro de DIV.a, mientras que el segundo con :is(div.b) dentro de DIV.b. Luego sobreescribimos el estilo de todos los ABBR con color azul y vemos que sólo actúa sobre el que aplicamos :where() pues tiene especificidad 0. Mientras que para :is() su especificidad es la de la clase div.b. Y div.b abbr es más específico que * abbr y por tanto no se sobrescribe.

En octubre 2020 lo soporta Firefox y Safari.

La pseudoclase relacional :has() de CSS4 selecciona un elemento que contenga alguno de la lista de su argumento. El ejemplo div#x *:has(em) selecciona el primer DIV pues es el único que contiene un EM. En octubre 2020 ningún navegador lo soporta.

Selectores de atributos

Figura
Figura. Selectores atributos: div#x [data-att=val]

En esta sección se seleccionan elementos según su atributo. Se escriben encerrando entre corchetes la pareja de nombre y valor del atributo, como *[name="value"], seleccionando elementos que posean un atributo con nombre name y valor value. Podemos omitir las comillas del valor si no contiene espacios. Si prescindimos del valor como *[nombre], se seleccionaran los que posean ese atributo sea cual sea su valor.

Como ejemplo tenemos elementos <div data-att>, con atributo data-att con o sin valor, ubicados en un contenedor <div id="x"> (ver Figura). En los ejemplos aplicamos el estilo div#x [data-att] con lo que aplicará selección sobre todos los hijos del contenedor.

Con div#x [data-att] seleccionamos elementos con atributo data-att sea cual sea su valor.

La pseudoclase de negación hace lo contrario. Con div#x :not([data-att]) selecciona elementos que no posean ese atributo. Vea que delante de la negación hay un espacio, que equivale al selector universal "*".

Con div#x [data-att=val] la selección requiere que sea exactamente igual a val. Vea que omitimos las comillas en el valor. En la Figura puede ver como la herramienta selecciona el único elemento que cumple esa condición.

Con div#x [data-att="val" i] se busca la coincidencia con val o VAL, mayúsculas o minúsculas. Con CSS4 se agrega una i (insensitive case) antes del cierre del corchete. Vea que hay que poner las comillas para aislar el valor.

Con div#x [data-att="val" s] fuerza a que sea exactamente igual a VAL, sólo mayúsculas. Con CSS4 se agrega una s (sensitive case) antes del cierre del corchete. En octubre 2020 sólo lo soporta Firefox.

Con div#x [data-att~=val] debe aparecer val en una lista de palabras separadas por espacios.

Con div#x [data-att|=val] debe aparecer val en una lista de palabras separadas por guiones.

Con div#x [data-att^=val] el valor val de aparecer al inicio del valor del atributo.

Con div#x [data-att$=val] el valor val al final del valor del atributo.

Con div#x [data-att*=val] el valor val puede aparecer en cualquier sitio.

Con div#x [data-att^=val][data-att$=val] el valor val debe aparecer al inicio y final.

Con div#x [data-att^=val][data-att$=val]:not([data-att=val]) debe aparecer val al inicio y al final pero que no sea sólo val.

Con div#x [data-att*=val]:not([data-att*=valor]) debe aparecer val pero no valor.

Con div#x [data-att*=val]:not([data-att$=val]) debe aparecer val pero no al final.

Con div#x [data-att*=val]:not([data-att^=val]) debe aparecer val pero no al principio.

Con div#x [data-att*=val]:not([data-att^=val]):not([data-att$=val]) debe aparecer val pero no al principio ni al final.

Pseudoelementos

Figura
Figura. Pseudoelementos: div#x *::after

Los pseudoelementos generan elementos en el DOM cuando se ejecuta la selección. Se separan con "::" para diferenciarlos de las pseudoclases. Aunque aún pueden escribirse con ":" pues CSS2 lo permitía.

Aunque la especificación CSS Selectores nivel 4 incluye un apartado para los pseudoelementos como parte de un selector, ahora tienen su propia especificación CSS Pseudoelementos nivel 4. También en fase de borrador con fecha 25 de febrero de 2019, comprende en estos momentos (octubre 2020) nuevos pseudoelementos relacionados con la selección de texto, marcado de errores ortográficos o gramaticales y otros.

Para probar los pseudoelementos se utiliza el siguiente HTML:

<div id="x">
    <p>Este texto...</p>
    <textarea>Este texto...</textarea>
</div>

Con div#x *::first-letter selecciona la primera letra de los descendientes de div#x. En el selector sólo puede haber un pseudoelemento y se ubicará al final del selector. Chrome o Firefox no generan el pseudoelemento en la primera letra del TEXTAREA.

Con div#x *::first-line selecciona la primera línea. El pseudoelemento se escribe con "::", a diferencia que las pseudo clases que se escriben con ":". Chrome si genera la primera línea (sin borde) en el TEXTAREA pero Firefox lo ignora.

Con div#x *::before se genera un nuevo elemento antes de cada P. Para esto se incluye un propiedad content con el texto "BEFORE".

div#x *::before {
    border: solid red 1px;
    background-color: yellow;
    content: "BEFORE";
}

Chrome y Firefox no generan estos pseudoelementos en el TEXTAREA.

Con div#x *::after se genera un nuevo elemento después de cada P con el contenido generado "AFTER".

En la Figura puede ver esta selección.

div#x *::after {
    border: solid red 1px;
    background-color: yellow;
    content: "AFTER";
}

Chrome y Firefox no generan estos pseudoelementos en el TEXTAREA.

Con div#x *::selection y CSS4 se aplica un estilo CSS de color, background-color o text-shadow al texto seleccionado, omitiéndose el aspecto que por defecto usa el navegador para texto seleccionado, usualmente color texto blanco sobre fondo azul). Para probarlo debe seleccionar texto en ambos elementos comprobando que se resaltan con fondo amarillo, aunque el borde es ignorado. Lo soportan la mayoría de navegadores.

Con div#x *::inactive-selection y CSS4 se aplica un estilo CSS de color, background-color o text-shadow al texto seleccionado de una ventana inactiva, omitiéndose el aspecto que por defecto usa el navegador, usualmente texto blanco sobre fondo gris. En octubre 2020 no es soportado.

Con div#x *::spelling-error y CSS4 se aplica un estilo CSS de background-color, cursor, outline, text-decoration, text-emphasis-color y text-shadow al marcador de error ortográfico. El navegador suele marcar estos errores en elementos de entrada de datos como el TEXTAREA, usando un subrayado ondulado de color rojo. En octubre 2020 no es soportado.

Con div#x *::grammar-error y CSS4 se aplica un estilo CSS de background-color, cursor, outline, text-decoration, text-emphasis-color y text-shadow al marcador de error gramatical. El navegador suele marcar estos errores en elementos de entrada de datos como el TEXTAREA, usando subrayados especiales. En octubre 2020 no es soportado.

Con div#x *::marker y CSS4 se aplica un estilo CSS de color o fuente al marcador de lista. En el ejemplo tenemos un elemento <p> con estilo de lista (display: list-item) y marcador numérico (list-style-type: decimal), que lo configura como una entrada de lista con un número 1, cuyo color y fuente se hereda del item de la lista. Con este pseudoelemento podemos modificar ese color y la fuente solo para el marcador.

Aplicamos el estilo:

div#x *::marker {
    border: solid red 1px;
    background-color: yellow;
    color: red;
    font-family: monospace;
    font-size: 1.25em;
}

El marcador ignora el borde y el color de fondo, aplicando el color rojo y una fuente monoespaciada de mayor tamaño. En octubre 2020 es soportado por Chrome y Firefox.

Con div#x *::placeholder y CSS4 se aplica estilo CSS al marcador de texto (placeholder) de los campos de entrada de texto, como el <input type="text" placeholder="..."> y el <textarea placeholder="...">, ambos equipados con el atributo placeholder. El marcador se muestra cuando el campo de texto esté vacío. Actualmente en octubre 2020 Chrome aplica color de fondo y borde al marcador, mientras que Firefox sólo aplica color de fondo a todo el elemento.

Pseudoclases de ubicación

Figura
Figura. Pseudoclases ubicación: div#x *:any-link

En estos ejemplos ponemos en práctica las pseudoclases de ubicación entre las que encontramos las de vínculo. Con esta opción reiniciamos el estado de los vínculos y objetivos.

En los ejemplos de la herramienta se usa el HTML siguiente:

<div id="x">
    <div>DIV <span id="V1603395270429">SPAN</span></div>
    <a href="#V1603395270429">A</a>
    <a href="http://example.com">http://example.com</a>
    <span>SPAN</span>
    <span>SPAN</span>
</div>

Tenemos un primer <div> con un <span> en su interior identificado con una marca de tiempo que será el objetivo del elemento vínculo <a> que está a continuación. Esta marcas de tiempo se reinician con la opción inicio con el objeto de quitar lo almacenado por el navegador sobre vínculos visitados y sin visitar. Otro vínculo nos lleva a una página de otro sitio. Al final hay un par de <span> que nos servirán para probar la nueva propiedad :scope.

Con div#x *:link la pseudoclase :link selecciona elementos vínculo <a> no visitados. Una vez visitado ya no aplicará ese estilo.

Con div#x *:visited la pseudoclase :visited selecciona elementos vínculo <a> ya visitados. Después de ejecutar este ejemplo pulsaremos el vínculo del primer <a> y observaremos que toma el estilo de vínculo visitado. El del sitio example.com aparecerá inicialmente visitado si ya hubo estado en ese sitio.

Con div#x *:any-link la pseudoclase :any-link de CSS4 selecciona elementos vínculo <a> visitados y sin visitar. En la Figura puede ver esta selección.

Con div#x *:local-link la pseudoclase :local-link de CSS4 selecciona elementos vínculo <a> que apunten al propio sitio. En el ejemplo no se selecciona el externo example.com. En octubre 2020 no tiene ningún soporte.

Con div#x *:target la pseudoclase :target selecciona el elemento destino de un vínculo interno. En el ejemplo el elemento <span> tiene un identificador con atributo id que sirve de destino para el elemento siguiente <a>. Cuando se visita ese destino se selecciona el estilo :target.

Con div#x div:target-within la pseudoclase :target-within de CSS4 selecciona elementos que contengan hijos que son objetivo de un vínculo. El objetivo del vínculo en el ejemplo es el primer <span>, pero en este caso el elemento que se selecciona para aplicar estilo es el padre <div>. Actualmente en octubre 2020 no es soportado. El comportamiento es similar a la pseudoclase :focus-within de la sección acción usuario, selector que si es soportado por la mayoría de navegadores.

Cuando se usa :scope de CSS4 en una hoja de estilo CSS, su resultado equivale a la pseudoclase :root (ver sección pseudoclases estructurales). La utilidad de :scope se evidencia cuando usamos métodos del DOM en JavaScript como querySelectorAll(). En este ejemplo seleccionamos los hijos directos que sean <span> dentro del contenedor <div id="x">. Selecciona los dos últimos SPAN, omitiendo el primero que no es hijo directo. Usamos :scope > span en el método querySelectorAll() de JavaScript.

En el ejemplo de la herramienta se usa el JS siguiente:

//Ejemplo JavaScript con la pseudoclase :scope
//Selecciona los SPAN hijos directos del contenedor con id="x"
let contenedor = document.getElementById("x");
let seleccion = [...contenedor.querySelectorAll(":scope > span")];
seleccion.forEach(v => {
    v.style.backgroundColor = "yellow";
    v.style.borderColor = "red";
}

Podíamos haber unificado las dos primeras sentencias con document.querySelectorAll("div#x > span"), para lo cual no necesitamos usar :scope. La necesidad por tanto de usarlo es cuando tenemos que referenciar desde un elemento en particular, como en el código desde la referencia contenedor que apunta al elemento con id="x".

Pseudoclases acción de usuario

Figura
Figura. Pseudoclases acción usuario: div#x label:focus-whitin

En esta sección de pseudoclases de acción de usuario se contemplan las que interviene la acción del usuario sobre los elementos. Son acciones como pasar el ratón por encima de un elemento (hover), hacer click (active) o entrar con el teclado en elementos como <input> (focus).

Con div#x *:hover la pseudoclave :hover selecciona elementos donde el cursor del ratón se ubique encima.

Con div#x *:active la pseudoclase :active selecciona elementos que se activan haciendo click con el ratón o con el teclado.

Con div#x *:focus la pseudoclase :focus selecciona elementos que tengan el foco, elementos como <a>, <area>, <input>, <textarea>, <select> y <button>. Algunos elementos como los <input type="checkbox"> y <input type="radio"> pueden recibir el foco, pero generalmente ignoran el CSS que se le aplique total o parcialmente.

Con div#x *:focus-visible de CSS4 la pseudoclase :focus-visible selecciona elementos que reciben el foco, aplicándose estilo cuando el navegador determine que debe hacer visible el foco. En el ejemplo de la pseudoclase *:focus todos menos el SPAN y el desactivado reciben el foco cuando lo pulsamos con el ratón. Pero con *:focus-visible no se aplica estilo en el caso del botón y del vínculo aunque reciban el foco. Esto es como funciona en Chrome (octubre 2020), pues en Firefox no funciona de forma estándar.

Con div#x label:focus-whitin de CSS4 la pseudoclase :focus-within selecciona elementos que contengan hijos que reciban el foco. En el ejemplo tenemos un <label> que contiene un <textarea>. Cuando éste recibe el foco, el padre recibirá el estilo resaltado. Funciona en la mayoría de navegadores. La Figura muestra esta selección cuando entramos en el campo de texto.

Pseudoclases de entrada de datos

Figura
Figura. Pseudoclases entrada datos: div#x *:valid

En esta sección de pseudoclases de entrada de datos se contemplan selecciones sobre elementos que permiten introducir datos. Estos son los elementos de formulario como <input>, <textarea>, <button> o <select>.

Con div#x *:enabled la pseudoclase :enabled selecciona elementos que no tienen el atributo disabled, es decir, que están activados. Responde a los controles de entrada de datos como <input>, <textarea>, <select> y <button>. Los elementos <input type="checkbox"> y <input type="radio"> generalmente ignoran estilo CSS que se le aplique.

Con div#x *:disabled la pseudoclase :disabled selecciona elementos que tienen el atributo disabled, es decir, que están desactivados. Responde a los controles de entrada de datos como <input>, <textarea>, <select> y <button>. Los elementos <input type="checkbox"> y <input type="radio"> generalmente ignoran estilo CSS que se le aplique.

Con div#x *:blank de CSS4 la pseudoclase :blank selecciona elementos tenga un valor vacío en su atributo value. Actualmente (octubre 2020) ningún navegador lo soporta. Además la especificación advierte que es posible que este selector no pase al estándar final. En caso de que funcionara, debería detectar el primer elemento <input type="text"> si le vacíamos el texto.

Con div#x *:valid de CSS4 la pseudoclase :valid selecciona elementos cuyo valor del atributo value sea reconocido como válido. Seleccionará elementos omitiendo los desactivados (disabled) o de solo lectura (readonly) que no requieran validar el valor. Seleccionará elementos <input type="text">, <input type="email"> y <select> como válidos. No selecciona el elemento <input type="text" value="" placeholder="Escriba texto" required> pues tiene el atributo required y está vacío. Tampoco selecciona el elemento <input type="number" value="-1" min="0" max="5"> pues tiene el valor -1 que no cumple el rango min="0" a max="5". La Figura muestra esta selección.

Con div#x *:invalid de CSS4 la pseudoclase :invalid selecciona elementos cuyo valor del atributo value sea reconocido como inválido. Seleccionará elementos omitiendo los desactivados (disabled) o de solo lectura (readonly) que no requieran validar el valor. Selecciona el elemento <input type="text" value="" placeholder="Escriba texto" required> como inválido, pues tiene el atributo required y está vacío. También selecciona el elemento <input type="number" value="-1" min="0" max="5"> pues tiene el valor -1 que no cumple el rango min="0" a max="5".

Con div#x *:required de CSS4 la pseudoclase :required selecciona elementos que posean el atributo required y que sean, por tanto, requeridos. Ese atributo hace que el navegador pueda dotar de un estilo particular con la finalidad de informar al usuario que debe rellenar ese campo. Selecciona el elemento <input type="text" value="" placeholder="Escriba texto" required> pues tiene el atributo value vacío y es requerido. El otro requerido es el de tipo email cuando se vacíe.

Con div#x *:optional de CSS4 la pseudoclase :optional selecciona elementos con valor opcional o no requeridos. Serán seleccionados todos menos los que tengan el atributo required. Los de tipo checkbox y radio no muestran estilo a pesar de que son también seleccionados.

Con div#x *:in-range de CSS4 la pseudoclase :in-range selecciona elementos cuyo valor esté dentro del rango permitido, como el campo de tipo number. El elemento <input type="number" value="-1" min="0" max="5"> inicialmente tiene un valor -1, fuera del rango min="0" a max="5". Si cambiamos el valor a uno en el rango entonces será seleccionado.

Con div#x *:out-of-range de CSS4 la pseudoclase :out-of-range selecciona elementos cuyo valor no esté fuera del rango permitido, como el campo de tipo number. El elemento <input type="number" value="-1" min="0" max="5"> inicialmente tiene un valor -1, fuera del rango min="0" a max="5", siendo por ello seleccionado como fuera de rango.

Con div#x *:user-invalid de CSS4 la pseudoclase :user-invalid selecciona elementos que tengan un valor inválido tras la modificación del usuario. Por ahora (octubre 2020) lo soporta Firefox, pero hay que usar -moz-ui-invalid. Se mostrará al modificar los campos requeridos cuando vacíemos el texto, con el tipo email cuando no sea un email válido y en el tipo number cuando no sea un número o no esté en el rango.

Con div#x *:checked+b::after la pseudoclase :checked selecciona elementos chequeados con el atributo checked. Este atributo se aplica a los elementos <input type="checkbox"> y <input type="radio"> para determinar si está seleccionado o bien, si no aparece el atributo es que no está seleccionado. En el ejemplo usamos el pseudoelemento ::after para generar después el texto "CHECKED", aplicándolo a unos <b> que siguen a los <input> de tipo checkbox y radio.

Con div#x *:not(:checked)+b::after la pseudoclase :not(:checked) seleccionamos elementos <input type="checkbox"> y <input type="radio"> no chequeados, que no tengan el atributo checked. En el ejemplo usamos el pseudoelemento ::after para generar el texto "UNCHECKED" después del <b> que sigue a esos <input>.

Con div#x *:indeterminate+b::after de CSS4 la pseudoclase :indeterminate selecciona elementos <input type="radio"> con una selección indeterminada. Un conjunto de elementos <input type="radio" name="a"> estará usualmente en un estado con alguna opción seleccionada. Cuando se da el caso de que no hay ninguna opción seleccionada, estará en un estado indeterminado. Con :inderminate detectamos este estado, generando un pseudoelemento después con el texto "?".

Con div#x *:default+b::after de CSS4 la pseudoclase :default se aplica a los elementos que posean el atributo checked como opción predeterminada, como los <input type="checkbox"> y <input type="radio">. Si el elemento viene con ese atributo en el HTML, se considera que es la opción predeterminada. Generamos un pseudoelemento con el texto "DEFAULT" después de unos <b> que siguen a los elementos <input> de tipo checkbox y radio.

Con div#x *:read-write de CSS4 la pseudoclase :read-write selecciona elementos que permitan modificar el texto. En el ejemplo tenemos varios elementos <input> de tipo text, email y number. El segundo tiene el atributo disabled por lo que no permite modificaciones. Hay un <textarea> también con el atributo readonly que tampoco permitirá modificaciones. Estos dos elementos de texto será a los que no aplique el estilo :read-write. En octubre 2020 Chrome aplica estilo al elemento con atributo disabled, mientras que Firefox no lo hace.

Con div#x *:read-only de CSS4 la pseudoclase :read-only selecciona elementos de sólo lectura. Deberían seleccionarse todos menos los elementos que permiten modificar texto que no tengan atributos disabled o readonly, tal como hace Firefox en octubre 2020. Chrome, sin embargo, no selecciona el desactivado.

Con div#x *:placeholder-shown de CSS4 la pseudoclase :placeholder-shown selecciona elementos con marcador de texto mostrado. Deben por tanto tener el atributo placeholder y que ese marcador esté mostrado. El elemento <input type="text" value="" placeholder="Escriba texto" required> contiene ese marcador que se mostrará pues está vacío. Finaliza la selección cuando escribimos algo y deja de mostrarse el placeholder. Y vuelve a seleccionarse cuando vacíamos el contenido y se muestre el placeholder.

Pseudoclases de idioma

Figura
Figura. Pseudoclases idioma usando elemento BDO: div#x *:dir(rtl)

Las pseudoclases de idioma seleccionan elementos por características del idioma del elemento, como el atributo lang usado en la página o elemento. También selecciona sobre la direccionalidad del texto.

Con div#x p:lang(es) la pseudoclase p:lang(es) selecciona elementos P con idioma español. Como la página tiene el raíz <html lang="es">, todos los elementos que no tengan un atributo lang son afectados por ese idioma español (es), por lo que el primer <p> está en español.

Con div#x p:lang(en) la pseudoclase p:lang(en) selecciona elementos P en idioma inglés, en este caso siendo afectado el único elemento P que tiene un atributo lang="en" específico.

El navegador determina automáticamente la direccionalidad del texto a partir del reconocimiento del idioma de los caracteres. Por defecto tiene valor izquierda a derecha (ltr). Se puede anular ese automatismo usando el elemento <bdo>. Con div#x *:dir(ltr) usando la pseudoclase :dir(ltr) de CSS4 seleccionamos elementos con direccionalidad izquierda derecha, como los tres primeros elementos. No podría conseguirse usando el atributo *[dir=ltr] puesto que es el valor por defecto y no se incluye en los elementos. No selecciona el elemento <bdo dir="rtl">. En octubre 2020 funciona en Firefox pero no en Chrome.

Con div#x *:dir(rtl) usando la pseudoclase *:dir(rtl) de CSS4 se selecciona el elemento <bdo dir="rtl">. El elemento BDO desactiva el automatismo para detectar la direccionalidad del texto, ignorando el idioma y ubicando los caracteres en el orden que especifique el atributo dir. En octubre 2020 esta pseudoclase funciona en Firefox pero no en Chrome. La Figura muestra esta selección en el navegador Firefox.

Pseudoclases temporales

Esta sección de pseudoclases temporales (time-dimensional) selecciona elementos con respecto a su actual estado de presentación o posición activa en alguna cronología, tal como durante la reproducción de voz de un documento, de un audio o de un vídeo usando la especificación WebVTT. Se incluyen en el borrador de CSS4 las pseudoclases :current, :past y :future. Dado que ningún navegador lo soporta ahora no incluiré ejemplos sobre esto.

Pseudoclases de estado de recursos

Esta sección de pseudoclases de estado de recursos aplica a elementos que representan recursos cargados, particularmente imágenes, audios o videos, y permite a los autores la selección basada en algunas cualidades de su estado. En el borrador de la CSS4 existente en octubre 2020 se observan los selectores :playing y :paused. Dado que ningún navegador lo soporta ahora no incluiré ejemplos sobre esto.

Pseudoclases estructurales

Figura
Figura. Parte del HTML para ejecutar ejemplos de las pseudoclases estructurales

Las Pseudo clases estructurales seleccionan elementos basándose en información extra que se obtiene del árbol del documento, pero que no puede representarse con otros tipos de selectores simples. Los nodos que no sean elementos HTML así como los nodos texto no se tienen en cuenta a la hora de seleccionar elementos. Los índices de numeración en la posición se cuentan siempre desde 1. Tampoco aplican a los elementos generados con pseudoelementos.

En la Figura se expone una captura de pantalla de la herramienta con la sección de pseudoclases estructurales. Para ejecutar los ejemplos disponemos de una matriz de 5 filas por 10 columnas. Podemos modificar esta matriz, siendo las dos primera filas fijas. A continuación tenemos un conjunto de controles donde configurar la selección con un botón para ejecutarlo. En la imagen se observa el ejemplo *:nth-child(2) *:first-child. Al final hay un desplegable con unos ejemplos que, cuando se selecciona uno de ellos, rellena el conjunto de controles anterior.

Esta estructura de rejilla con filas <div> y celdas <span> puede asimilarse a la estructura de tabla con filas <tr> y celdas <td>. El contenedor div#x sería entonces table#x. En los ejemplos como div#x *:nth-child(2) *:last-child que selecciona el último hijo de la segunda fila, lo trasladaríamos a una tabla con table#x tr:nth-child(2) td:last-child.

La pseudoclase :root representa la raíz del documento. En HTML es el elemento <html>. Su utilidad es que aporta mayor especificidad que otros selectores. Damos estilo de fondo amarillo y borde rojo al contenedor exterior <div id="x">. Pero antes forzamos un fondo verde con :root div#x que tiene mayor especificidad que div#x. Podemos ubicar :root div#x en cualquier lugar de la hoja de estilo que siempre va a prevalecer sobre cualquier otro selector de tipo, clase o identificador, como este caso.

:root div#x {
    background-color: lime;
}
div#x {
    border: solid red 1px;
    /* No se aplica fondo porque :root tiene mayor especificidad */
    background-color: yellow;
}

La pseudoclase :first-child selecciona elementos que sean primer hijo en su contenedor. Con div#x *:nth-child(2) *:first-child seleccionamos el primer hijo en la segunda fila (con nth-child(2) que veremos después).

La pseudoclase :last-child selecciona elemento que sean último hijo en su contenedor. Con div#x *:nth-child(2) *:last-child seleccionamos el último hijo de la segunda fila.

La pseudoclase :only-child selecciona un elemento que sea hijo único en su contenedor. Con div#x * *:only-child seleccionamos el único elemento que es hijo único, el de la primera fila, siempre que la elementos del contenedor tenga más de una columna de hijos.

Figura
Figura. Configurar ejemplos para pseudoclases con tipos como :first-of-type

Para ejecutar ejemplos con selección por tipos, como :first-of-type, :last-of-type y otros finalizados en -of-type, es conveniente modificar la configuración como se observa en la Figura. Se trata de componer la matriz de elementos con una mezcla de <div> y <p> en las filas y una mezcla de <em> y <span> en las columnas. La primera permanecerá invariable con un único hijo SPAN con objeto de usarlo con :only-child y :only-of-type.

Vea que siempre disponemos de un último elemento vacío en la segunda fila. Esto lo necesitaremos posteriormente para observar el uso de la pseudoclase :empty.

La pseudoclase :first-of-type selecciona elementos que sean primeros de tipo en su contenedor. Con div#x *:nth-child(2) *:first-of-type Seleccionamos los primeros <em> y <span> en la segunda fila. La primera fila permanece invariable.

La pseudoclase :last-of-type selecciona elementos que sean últimos de tipo en su contenedor. Con div#x *:nth-child(2) *:last-of-type seleccionaríamos los último EM y SPAN en la fila 2 en caso de mezclar estos elementos.

La pseudoclase :only-of-type selecciona elementos que sean únicos de tipo en su contenedor. Con div#x * span:only-of-type seleccionamos los SPAN que sean únicos en ese tipo en una fila. Sólo lo será el primer SPAN en la primera fila.

La pseudoclase :nth-child(an+b) selecciona elementos que sean hijos según un orden númerico dado por el argumento an+b. Para seleccionar hijos impares podemos usar div#x * *:nth-child(2n+1).

La pseudoclase :nth-child(an+b) selecciona elementos que sean hijos según un orden númerico dado por el argumento an+b. Para seleccionar hijos pares usamos div#x * *:nth-child(2n+0).

La pseudoclase :nth-of-type(an+b) selecciona elementos que sean de tipo según un orden númerico dado por el argumento an+b. Para seleccionar impares podemos usar el argumento odd, por ejemplo div#x * *:nth-of-type(odd). Si usa la configuración que mezcla EM y SPAN, se selecciona los impares de ambos tipos.

La pseudoclase :nth-of-type(an+b) selecciona elementos que sean de tipo según un orden númerico dado por el argumento an+b. Para seleccionar pares podemos usar el argumento even, por ejemplo div#x * *:nth-of-type(even).

La pseudoclase :nth-child(an+b) selecciona elementos que sean hijos según un orden númerico dado por el argumento an+b. Para seleccionar filas pares e hijos impares usaremos div#x *:nth-child(even) *:nth-child(odd).

La pseudoclase :nth-child(an+b) selecciona elementos que sean hijos según un orden númerico dado por el argumento an+b. Para seleccionar las 4 primeras columnas usamos div#x * *:nth-child(-1n+4).

La pseudoclase :nth-last-child(an+b) selecciona elementos que sean últimos hijos según un orden númerico dado por el argumento an+b. Para seleccionar las 4 últimas columnas usamos div#x * *:nth-last-child(-1n+4).

La pseudoclase :nth-child(an+b) selecciona elementos que sean hijos según un orden númerico dado por el argumento an+b. Para seleccionar desde la columna 2 a la 4 usamos div#x * *:nth-child(-1n+4):nth-child(1n+2). Observe que las columnas se seleccionan primero con el rango (-1n+4) que selecciona las 4 primeras columnas. Y a continuación con (1n+2) selecciona de esas las 2 primeras columnas, resultando finalmente un rango de la columna 2 a la 4.

La pseudoclase :nth-child(an+b) selecciona elementos que sean hijos según un orden númerico dado por el argumento an+b. Para seleccionar desde la fila 2 a la 4 usamos div#x *:nth-child(-1n+4):nth-child(1n+2) *. Observe que las filas se seleccionan primero con el rango (-1n+4) que selecciona las 4 primeras filas. Y a continuación con (1n+2) selecciona de esas las 2 primeras filas, resultando finalmente un rango de la fila 2 a la 4.

La pseudoclase :nth-child(an+b) selecciona elementos que sean hijos según un orden númerico dado por el argumento an+b. Para realizar una selección rectangular comprendiendo desde la fila 3 a la 4 y de la columna 2 a la 5 usamos div#x *:nth-child(-1n+4):nth-child(1n+3) *:nth-child(-1n+5):nth-child(1n+2). Observe el rango de selección por filas (-1n+4) y (1n+3) que supone seleccionar desde la fila 3 a la fila 4. Y el rango de selección por columnas (-1n+5) y (1n+2) que supone seleccionar desde la columna 2 a la 5.

La pseudoclase :first-child selecciona elementos que sean primer hijo en su contenedor. Usando la pseudoclase de negación :not y con div#x * *:not(:first-child) seleccionamos todos los hijos que no sean primer hijo en su contenedor.

La pseudoclase :nth-child(an+b) selecciona elementos que sean hijos según un orden númerico dado por el argumento an+b. Usando la pseudoclase de negación :not y con div#x * *:not(:nth-child(2)) seleccionamos todos los hijos que no estén en segunda columna.

La pseudoclase :empty selecciona elementos vacíos. Con div#x * *:empty seleccionamos el último hijo en la segunda fila que hemos establecido como vacío.

La pseudoclase :empty selecciona elementos vacíos. Con div#x * *:not(:empty) seleccionamos todos los elementos menos el único vacío al final de la segunda fila.

Selectores de rejilla

Los selectores de rejilla se incluyen en el borrador de CSS4 pero actualmente en octubre 2020 no tienen soporte. Parte de la necesidad de seleccionar elementos en columnas en un estructura de rejlla. Como celdas de una columna de una tabla. Una celda, es decir, el elemento <td>, es hijo de una fila, el elemento <tr>. Aunque existe un elemento columna <col>, una celda no es hijo de una columna desde el punto de vista estructural. El elemento columna en HTML sólo sirve para dotar de estilo a todas las celdas de la columna. No funcionaría algo como table#x col:first-child td:last-child para seleccionar la última celda de la primera columna, pues un <td> no es un hijo estructural de una <col>.

Esta nueva sección pretende arreglar eso. En el borrador de la especificación encontramos el nuevo combinador || y las nuevas pseudoclases :nth-col() y :nth-last-col(). Como no tienen soporte aún, no pondré ejemplos sobre esto.

Por ahora podemos usar las pseudoclases estructurales. En esa sección se expone un ejemplo interactivo usando una rejilla de filas con elementos <div> y celdas con elementos <span>. También serviría con una rejilla de tabla con filas <tr> y celdas <td>. En esa sección se exponen ejemplos de selección por columnas, como div#x * *:nth-child(-1n+4):nth-child(1n+2), seleccionando las columnas 2 a la 4. Si se aplicara a una tabla usaríamos table#x tr td:nth-child(-1n+4):nth-child(1n+2).