Selectores de pseudo-clases de CSS3

Los selectores de pseudo-clase nos permite una selección basada en información que se encuentra fuera del árbol del documento o que no puede ser expresada usando los otros selectores simples. Las que ya se encontraban en las pseudo-clases de CSS2-1 eran E:first-child, E:link, E:visited, E:hover, E:active, E:focus y E:lang.

Estos selectores y las nuevas pseudo-clases de CSS3 se clasifican como sigue, donde pondremos enlaces a apartados de este tema que desarrollan ese selector. Los que no tengan enlaces se exponen en el documento CSS2-1 indicado antes.

  • Dinámicas, que seleccionan elementos a partir de otras características que no pueden deducirse del árbol de elementos.
    • Vínculo con E:link o E:visited que actuan sobre vínculos no visitados y visitados respectivamente.
    • Acciones del usuario con E:hover, E:active o E:focus para interactuar con elementos que cambian con la respuesta del usuario. En el tema eventos css expuse otros ejemplos acerca del funcionamiento de estas pseudo-clases en varios tipos de elementos.
  • Objetivo con E:target para designar una ubicación dentro de un documento en una URI.
  • Lenguaje con E:lang(C) representa un elemento que está escrito en un lenguaje especificado por C.
  • Estado de la interfaz de usuario E:enabled, E:disabled, E:checked, E:indeterminate.
  • Negación E:not().
  • Estructurales E:root, E:nth-child(), E:nth-last-child(), E:nth-of-type(), E:nth-last-of-type(), E:first-child, E:last-child, E:first-of-type, E:last-of-type, E:only-child, E:only-of-type, E:empty. Este parte por su extensión se verá en un tema siguiente.

Selector pseudo-clase objetivo

Un fragmento identificador viene a ser un vínculo interno de una página al que podemos referirnos incluyéndolo en una URI tras el signo #. Por lo tanto podemos vincular a una página y a un cierto elemento de la misma, conociéndose como elemento objetivo. La pseudo-clase objetivo de CSS3 E:target aplica estilo al elemento E cuando es un vínculo interno y se ha llamado a la página usándolo.

Ejemplo:

Con el enlace target.html vamos a una página de ejemplo abriéndose sin dirigirse a ningún vínculo interno.

Mientras que con el enlace target.html#vinculo-interno se abre la misma página situándose al nivel del elemento con id="vinculo-interno", aplicándose el estilo de color rojo y mayor tamaño de letra a ese elemento objetivo.

El código de la página de ejemplo es muy simple, exponiendo sólo lo imprescindible:

Disponemos dos contenedores con borde azul antes y después de un elemento <span id="vinculo-interno"> que hará las veces de elemento objetivo. Esos contenedores tienen una cierta altura para forzar al navegador a que mueva el elemento objetivo al borde superior de la ventana. Cuando llamemos a la página sin el fragmento identificador #vinculo-interno no se aplicará el estilo #vinculo-interno:target. Pero si usamos el fragmento identificador entonces se aplica ese estilo a ese elemento.

Le he encontrado una utilidad a la pseudo-clase objetivo incorporándola a este sitio con este estilo:

h3.num:target{
    background-color: beige;
    }

Los encabezados <h3> de los apartados de los documentos como este que está leyendo son class="num" . Tienen un identificador con los cuáles se construye una lista de vínculos internos en la parte superior de la página. Además estos encabezados identificados también sirven para usar con el buscador interno de este sitio. Así cuando nos dirigimos a una parte de una página aparecerá resaltado el encabezado con un color que le facilitará al usuario reconocer la parte de la página donde le hemos remitido.

Selector pseudo-clase estado interfaz usuario

Algunos elementos HTML tienen atributos disabled o checked. Son atributos booleanos con la peculiaridad de que si están presentes su valor es verdadero y falso en otro caso. Para CSS esto es una contrariedad pues si estos atributos hubiesen sido implementados como disabled="true" y disabled="false" podríamos seleccionarlos y darles estilo. Por ejemplo con input[disabled="true"] pondríamos un estilo particular para el elemento desactivado y con input[disabled="false"] para el activado.

Pero HTML no reconoce sino disabled sin más. El estilo para el control desactivado lo declararíamos como input[disabled]. Pero ¿cómo ponemos el estilo detectando el control activado? Una forma es usando la nueva pseudo-clase :not() como se verá más abajo. Pero otra forma es usando las nuevas pseudo-clases de estado de la interfaz de usuario, que seleccionan elementos según su estado: E:enabled, E:disabled, E:checked, y E:indeterminate. A éste último no le veo aplicación inmediata pues por ahora las casillas de verificación y botones de radio sólo tienen dos estados. Aunque es posible que en el futuro se implemente un estado indeterminado como dice la especificación.

Hagamos un par de ejemplos para ver como funciona esta pseudo-clase:

Ejemplo:

Estos dos elementos <input type="text"> no tienen estilo añadido. El segundo tiene el atributo disabled apareciendo desactivado.
Estos tienen estilo con pseudo-clases que modifican el comportamiento por defecto del navegador.
Con los <input type="checkbox"> podemos hacer lo mismo. El primero es el comportamiento por defecto y el segundo tiene estilo incorporado. Esto funciona en Opera 12.12 pues soporta el cambio de estilo en las casillas de verificación. Otros navegadores como Firefox 17, Chrome 23 o Safari 5.1.7 no aceptan estilos sobre estos elementos. Aunque podemos aplicar estilo a un elemento hermano.

Código completo de este ejemplo

Puede ver el código completo en el desplegable anterior. Explicamos brevemente que a los dos elementos cuadros de texto le aplicamos el estilo input[type="text"]:enabled y input[type="text"]:disabled respectivamente. Con esto detectamos el estado en el que se encuentran esos elementos: activado y desactivado. Detectamos cuando están seleccionadas las casillas de verificación con input[type="checkbox"]:checked y cambiamos su estilo. Por ahora sólo Opera 12.12 permite modificar el estilo de una casilla de verificación. De todas formas la pseudo-clase funciona en los otros navegadores, pues con input[type="checkbox"]:checked + b ponemos estilo al elemento <b> hermano cuando activamos la casilla.

Ejemplo pseudo-clases interfaz usuario: un select personalizado con imágenes

Con este ejemplo intentaré buscar una aplicación práctica a las pseudo-clases de interfaz de usuario. No es díficil ver que tiene un potencialidad evidente, pues podemos cambiar el estilo de un elemento atendiendo a la interacción del usuario. Antes de esto había que recurrir a JavaScript para saber en que estado se encontraba un control de usuario. El siguiente ejemplo trata de implementar un componente similar al elemento <select>. Las limitaciones de éste es que no podemos agregar HTML en el interior de las opciones, es decir, en los elementos <option> del componente. Aquí tenemos un <select> clásico y a la derecha uno personalizado usando listas <ul><li>:

Ejemplo:

Un <select> clásico
Uno personalizado con HTML

Con un simple cambio en el estilo de las listas con display: inline-block tenemos el componente en horizontal a modo de barra de botones:

Al seleccionar una opción ejecutamos javascript para extraer el valor y depositarlo en los siguientes elementos:

Selección ejecutada con evento onchange en el elemento <select> clásico:
 
Selección ejecutada en el personalizado vertical con evento onchange en el elemento <input type="radio">:
 
Selección ejecutada en el personalizado horizontal con evento onchange en el elemento <input type="radio">:
 

Código completo de este ejemplo

El comportamiento visual de los componentes personalizados se realiza sólo con CSS. Hay JavaScript para evidenciar que estamos realizando una selección vertiendo el valor seleccionado en un elemento inferior. No voy a explicar enteramente todo el código (que puede ver en el desplegable anterior), sólo lo relacionado con este tema de selectores. La estructura básica del HTML es la siguiente:

El <input type="radio"> es el llamado botón de radio y será sobre el que se apoya el estilo. La etiqueta <label> está a continuación y se le adjudica al botón con el atributo for. Un <span> nos servirá para introducir una imagen usando sprites CSS. Finalmente está el texto de la opción. Veáse que el contenido de la etiqueta permite HTML, lo que supone una mejora con respecto a un <select> clásico donde sólo podemos poner texto plano. El CSS que básicamente hace funcionar esto es el siguiente:

Con el ul[class|="slct"] estamos realizando una selección por atributo de lista de palabras separadas por guión. Esto nos servirá para usar el mismo código base para el componente vertical (<ul class="slct-vertical">) y horizontal (<ul class="slct-horizontal">). La idea es usar un botón de radio no visible y utilizar la etiqueta asociada para captar la pulsación del usuario. Esto se puede conseguir con visibility: hidden, pero no funciona en IE8. Otra forma es ponerle transparencia total con opacity: 0 y a la vez filter: alpha(opacity:0) para que funcione en IE.

La etiqueta <label> se declara en bloque para que su ancho ocupe todo el disponible. Aunque esto nos obligará a subirlo un poco con margin-top: -1.25em;. Aplicamos la pseudo-clase :hover a la etiqueta para cuando movamos el ratón ponerle un color gris que resalte donde podemos hacer click.

Lo siguiente es captar el estado del botón de radio cuando seleccionemos una opción. Aquí entra en juego la pseudo-clase de interfaz de usuario :checked que la aplicamos al botón de radio. Entonces con input:checked + label detectaremos que el usuario ha seleccionado una opción y dotaremos al elemento hermano (la etiqueta) de un color de fondo verde oscuro y letra en amarillo.

Todo esto funciona sólo con CSS en navegadores Opera 12.12, Firefox 17, Chrome 23 o Safari 5.1.7. Navegadores como IE8 que no soportan la nueva pseudo-clase de interfaz de usuario no mostrarán el estilo aunque la selección si sigue su curso. Para evidenciar que se está ejecutando disponemos de JavaScript con manejadores del evento change en los botones de radio. Cuando seleccionamos uno aparecerán los atributos name y value en un contenedor más abajo.

Selector pseudo-clase de negación

La pseudo-clase de negación de CSS3 tiene la sintaxis E:not(X) donde el argumento X es un selector simple, seleccionándose un elemento que no sea a su vez objeto de la selección del argumento. Las negaciones no pueden anidarse :not(:not(...)). Hay que tener en cuenta que un pseudo-elemento no es un selector simple y por tanto no es un argumento válido para :not().

En el tema anterior hay un ejemplo de selector de atributo donde hacíamos uso de la pseudo-clase de negación. En un apartado anterior decíamos que también podíamos detectar un control de tipo texto activado usando :not([disabled]), pues el <input type="text"> no portaría ese atributo. En este ejemplo se presenta el control en ambos estados modificando el estilo que por defecto le pone el navegador:

Ejemplo:

usando input[type="text"]:not([disabled])

usando input[type="text"][disabled]