soy Kseso y esto EsCSS

El selector CSS. Guía a fondo para iniciados y novatos en CSS

El selector CSS. Guía a fondo para iniciados y novatos en CSS

·Por Kseso ✎ 9

En el espacio CSS, con toda su formulación y definiciones que conforman su corpus de especificaciones (W3C Recommendations) y sus propuestas en discusión, hay una parte sin la cual todo sería un montón de literatura inútil:
Es el selector CSS

El selector CSS es el nexo de unión entre la hoja de estilos y los documentos a los que se aplique dicha hoja. Ya sean (x)HTML, XLM, SVG... y con independencia del medio en que que se muestre (media type).

Del conocimiento y buen manejo que se haga del selector CSS dependerá la eficiencia de la hoja de estilos y en muchos casos el poder lograr lo deseado sin necesidad de recurrir a otros lenguajes.

Un detalle más que significativo de su importancia del selector en CSS lo da el hecho de que hemos pasado de tener unos 20 selectores en CSS2 a más de 70 en el último documento en discusión (selectores CSS level 4).

Guía a fondo del Selector CSS. 1 parte

El objetivo de este artículo (por extenso, completo y detallado) no es que te lo "aprendas". Sólo pretendo que comprendas qué son y cómo funcionan los selectores CSS. Que seas capaz de imaginártelos en su funcionamiento, tanto cuando te lo encuentres en códigos de otros como cuando necesites conformar tú un selector para hacer esa virguería[3ª y 4ª] CSS ;-)

Así que ni se te ocurra "estudiarte" este post. Una vez que lo leas sólo espero que lo tengas a mano entre tus favoritos y vuelvas a él para consultas puntuales o aclaraciones de dudas.

Este artículo también está disponible en la Wikipedia española: Selectores CSS

Sintaxis y estructura del selector CSS

Qué es el selector CSS

El selector CSS es el identificador en la hoja de estilos del elemento o elementos del DOM a los que se aplicarán las declaraciones contenidas en la regla de la que forma parte dicho selector.

Como curiosidad, en algunas partes, al elemento del DOM al que aplica el selector CSS se le llama sujeto del selector.

El término selector CSS puede referirse por igual a cualquiera de los cuatro tipo de selectores CSS que existen clasificados por la composición de su nombre:

  1. a un selector CSS simple
  2. a un selector CSS compuesto
  3. a un selector CSS complejo
  4. a una lista de selectores CSS

Tipos de selectores CSS por su composición

Selector CSS simple

Un selector simple es aquel que está formado sólo por una única cadena textual, sin ningún combinador. Son selectores simples el selector universal *, el selector por tipo de elemento del DOM div p article..., el selector de ID # y de clase ., el de atributo, el de pseudoclase : y el de pseudoelemento :: (notación actual). En la notación antigua o clásica de CSS2 los pseudoelementos también se representan como las pseudoclases :.

Los combinadores son signos intercalados entre selectores simples para acotar o hacer más preciso el alcance del selector. Estos combinadores son el espacio en blanco y los signos + ~ > entre otros.

Selector CSS compuesto

El Selector compuesto es una cadena de selectores simples sin combinadores (el espacio en blanco también queda excluido porque es un combinador):

section.noticias {} .una_clase.otra_clase {}

Entre los selectores CSS compuestos también están incluidos los que tienen un selector de pseudoclase CSS en su nombre:

a:hover {} input:checked {} .mi_clase:last-child {}

Selector CSS complejo

El Selector complejo es una secuencia o cadena de selectores separados por combinadores.

p span {} nav > a {} main:hover > h1 ~ p {}

Lista de selectores CSS

Una lista de selectores la conforman dos o más selectores de cualquier tipo separados por una coma ,

#unico, main:hover > h1, ol > li:only-child {}

Combinadores de selectores CSS

Los combinadores CSS son signos gráficos o caracteres especiales, palabras o expresiones reservadas utilizados en la formación del nombre del selector para formar los selectores CSS complejos. Estos selectores CSS aumentan la potencia del selector al relacionar varios de ellos en función de que cumplan alguna condición (que es la definida por el combinador)

Combinador CSS de descendiente: ' ' (espacio en blanco) o '>>'

En el documento sobre los selectores de nivel 4 se introduce un nuevo combinador >> equivalente al espacio en blanco.

El espacio en blanco o el doble >> separando el nombre de dos selectores CSS se utiliza para apuntar a elementos contenidos dentro de otro en el DOM del documento. a b {} o a >> b {} selecciona a todos los elementos b contenidos (dentro) de a sin importar la profundidad o los descendientes interpuestos entre 'a' y 'b'.

Combinador CSS de hijo directo '>'

a > b Sólo aplica a los elementos 'b' contenidos diréctamente en 'a'. 'b' es hijo directo de 'a'

Combinador cCSS de hermano posterior '~'

a ~ b El signo '~' en el selector obliga a que 'b' sea hermano de 'a' (estén ambos contenidos diréctamente en el mismo elemento). No importa que en el html entre ambos haya otros elementos hermanos interpuestos.

h2 ~ p {} <article> <h2>título</h2> <p>texto del primer párrafo</p> <img src='... /> <p>texto de otro párrafo</p> </article>

El selector CSS del código previo h2 ~ p {} afecta por igual a los dos párrafos ya que ambos son hermanos: están contenidos diréctamente en el mismo elemento html, ambos tienen al article como padre.

Combinador de hermano posterior adyacente '+'

a + b Representado por el signo '+' selecciona, al igual que el anterior, cada elemento 'b' que sea hermano de un 'a' y además estén adyacentes: 'b' tiene que aparecer en el DOM inmediatamente después de cerrar 'a', no puede haber ningún otro hermano que los separe o se interponga entre ellos.

En el bloque de código anterior si el combinador CSS en vez de ser el de hermano posterior ~ es el de hermano posterior adyacente h2 + p {} sólo el primer párrafo (el que sigue al h2) se vería afectado por la regla CSS.

Observa que al referirme a los combinadores CSS de hermanos incluyo la expresión hermano posterior ya que CSS no puede (de momento) remontar el DOM. Esto es, siempre serán elementos 'contenidos en' o 'posteriores a'. Nunca al 'contenedor de' o al 'precedente de'.

Combinador CSS de namespace '|' y qualified names

La barra vertical '|' se emplea para acotar el sujeto del selector al namespace (espacio de nombre) indicado. La especificación tiene su documento (status W3c Recomendation) específico para este tema: "CSS Namespaces Module" y los "nombres CSS calificados".

@namespace misitio "http://misitio.dominio.ext"; misitio|A representa el nombre A en el namespace http://misitio.dominio.ext

Nota de EsCSS: La especificación no incluye en este apartado de los combinadores de namespace. Opto por incluirlo aquí bajo mi responsabilidad

Combinador CSS de referencia '/ref/'

A título informativo. El documento sobre los selectores de nivel 4 introduce este selector.

label:matches(:hover, :focus) /for/ input {}

El combinador /ref/ en el código anterior apunta al imput al hacer :hover o :focus en su etiqueta (label). Lo vincula por el atributo 'for'.

Combinador CSS /deep/ para iluminar las sombras

El combinador /deep/ es de reciente formulación. Concebido para poder apuntar a los elementos creados o incluidos en el "Shadow DOM".

Nota: Chrome retiró recientemente el soporte a este combinador.

Combinador de columnna ||

El combinador de columnas || (representado por dos barras verticales), nuevo en el doc Selectores de nivel 4, selecciona las celdas pertenecientes a una columna dada. En caso de que una celda ocupase 2 o más columnas diferentes se verá afectado por cualquiera de éstas.

col.selected || td { background: gray; color: white; font-weight: bold; } <table> <col span="2"> <col class="selected"> <tr><td>A <td>B <td>C <tr><td colspan="2">D <td>E <tr><td>F <td colspan="2">G </table>

El selector col.selected || td afecta a las celdas C, E, y G

Identificando al sujeto del selector CSS

De forma general, se puede decir que el sujeto del selector (o elementos del DOM a los que apunta) es el último selector simple que aparece, en la cadena que lo conforma, antes del corchete de apertura del bloque de declaraciones y de cada coma ',' si es una lista de selectores.

Puntualizo lo "de forma general" debido a que de nuevo ha sido recogido en el documento de trabajo el selector de ancestro o padre que no aplica al elemento sino a su contenedor.

Puedes ampliar este aspecto con el artículo "Cómo se leen los selectores".

Conformando el nombre del selector CSS

A la hora de dar nombre a los selectores CSS hay una serie de requisitos a tener en cuenta:

  1. Por conveniencia (acuerdo no formal) se utilizan minúsculas aunque CSS no es "case sensitive". Esto es, no diferencia entre mayúsculas y minúsculas. Por lo tanto para CSS es lo mismo el selector 'div' que 'DIV'. Sin embargo hay lenguajes a los que aplica CSS que sí lo son como el XLM tanto en el nombre de los elementos como en el valor de sus atributos.
  2. Los nombres de los selectores pueden contener sólo caracteres de la 'A' a la 'Z' y del '0' al '9' y contener guiones medios '-' o bajos '_' dentro de él.
  3. El nombre del selector no puede comenzar por un dígito (número), ni por un guión ni por alguno de los caracteres reservados. Es conveniente evitar el uso de símbolos "extraños".
  4. En caso de que necesites utilizar inexcusablemente alguno de los no permitidos utiliza "codificación CSS" y escápalos usando la barra invertida '\'. Así '.2clase' sería inválido pero '.\2clase' funcionaría. El selector '#foo>a' apuntará a un enlace hijo directo del elemento con id 'foo' pero '#foo\>a' al que tenga en el html el atributo de id igual a 'foo>a'.
    En CSS la barra invertida '\' se asocia con tres tipos de caracteres de escape.

Estas restricciones de caracteres sólo aplican en el ámbito de la hoja de estilos. Hago esta puntualización porque el documento Html y el CSS son dos campos totalmente distintos. Y el no tenerlo claro conduce a falsas polémicas e ideas como negar que los ids y class pueden comenzar por un número.

Alcance del selector CSS. La pseudoclase ':scoped'

Alcance del selector CSS

En proceso de formulación y desarrollo. Lo incluyo a título informativo.

Algunas aplicaciones pueden acotar el ámbito de aplicación de los selectores a un un fragmento del documento o subárbol del DOM. Esta delimitación de alcance se puede hacer por dos métodos: 'scope-contained selectors' y 'scope-filtered selectors'.

Creo que es el equivalente en las hojas de estilos a lo que supone emplear en el html el atributo 'scoped' dentro del elemento <style> usado en el body.

Puedes ampliar este aspecto en el artículo Estilos acotados: "style scoped".

Nota: Recientemente Chrome retiró su soporte a scoped tras habérselo dado durante algún tiempo.

Combinaciones lógicas y agrupación de selectores CSS

Los selectores se pueden agrupar para simplificar las hojas de estilo cuando varios elementos comparten una serie de declaraciones iguales. Así, en vez de crear varias reglas iguales en las que sólo cambia el selector, se crea una única regla con todos los selectores necesarios para apuntar a los distintos elementos.

Las combinaciones y agrupaciones de selectores CSS recogidas en la especificación son:

Listas de selectores CSS

la conforman dos o más selectores de cualquier tipo separados por una coma ',' a los que aplica el mismo bloque de declaraciones que comparten. Visto en detalle un poco más arriba en este artículo.

El selector CSS por pseudoclase :matches()

La pseudoclase :matches() es del tipo funcional. Admite como argumento una lista de selección. Esto es, se indica dentro del paréntesis y separados por comas los casos en los que aplicará el bloque de declaraciones.

input:matches(:invalid, :out-of-range) {}

Aplicaría a los 'inputs' que cumplan con alguna de las condiciones indicadas: que su valor no sea válido o esté fuera del rango permitido en él.

El selector CSS por pseudoclase :not()

La pseudoclase de negación :not(), a contrario que la anterior, apunta a los que no cumplen con los argumentos indicados.

a:not(:focus, :visited) {}

El selector CSS por pseudoclase :has()

La pseudoclase :has() es la formulación actual de un viejo conocido: el selector de precedente o padre.

Utilizada para apuntar a los elementos que contengan lo indicado en el argumento (valor dentro del paréntesis). Así el selector a:has(img) {} sólo aplicará a los enlaces que contengan una imagen dentro de él.

El valor del argumento puede ser uno sólo o una lista separadas por comas:

section:has(h1,h2,h3,h4,h5,h6) { /*bloque declaraciones*/ }

El bloque de declaraciones se aplicará a todo section y sólo a aquellos que contengan como mínimo un encabezado (hnº) dentro de él.

Al utilizar estos selectores CSS con estas pseudoclases hay que tener presente que:

  1. No se puede anidar la misma: colocar como argumento de la función (dentro del paréntesis) la misma pseudoclase anula el selector. Es erróneo hacer :not(:not()) :matches(:matches():has(:has())
  2. Sí es lícito encadenarlas, ya sea la misma o distintas: :not(:checked):not(:required)
  3. El documento "selectors level 3" sólo permitía incluir en el argumento de :not() selectores simples. El último en desarrollo puedes anidar estas pseudoclases: el:not(:has(h1)) el:has(:not(img))
Combinaciones lógicas y agrupación de selectores

Al momento de conformar el nombre del selector CSS, o lo que es lo mismo, buscar cómo apuntar a los elementos del Html a los que queremos afectar, podemos hacerlo tomando algún tipo de información de dicho elemento, y en función de ese dato usado también se pueden clasificar los selectores CSS:

Selectores CSS elementales

Selector universal '*'

El asterisco '*' representa a cualquier elemento del DOM. Al ser utilizado como selector aplicará a cualquier elemento contenido en el documento.

Selector CSS por tipo de elemento (nombre de etiqueta o tag)

Selecciona al "sujeto del selector" por el nombre de la etiqueta (tag) que lo identifica en el html. Ejemplo de estos son div, a, ul {}

Selector CSS por valor de atributo

Un atributo es un metadato incluido dentro de la etiqueta de apertura del elemento en el HTML (o XML). Está formado por una expresión clave que indica qué tipo de metadato es, seguido del signo = y el valor del atributo entre comillas. En las hojas de estilos podemos utilizar tanto el nombre del atributo como todo su valor o una parte para utilizarlo como selector.

Selector CSS de Identificador único o id '#'

Conformado anteponiendo la almohadilla '#' al valor del atributo 'id' del elemento.

La especificación explícitamente indica que no pueden existir espacios en blanco en el valor del atributo 'id'. Por lo tanto el atributo 'id' sólo admite un único valor y además este valor debe ser único (no compartido) por otros elementos en el mismo documento o "namespace".

Por ello no pueden existir selectores compuestos de dos identificadores únicos: #id1#id2 {}. Pero si por cualquier motivo te encuentras que en el html hay un elemento con "dos id´s" en el mismo atributo (id='un dos') y no puedes subsanar ese error (en el html) aún es posible utilizar dicho valor como selector CSS:

  1. Con el uso del selector por valor de atributo en cualquiera de sus variantes: [id='un dos'] [id~='dos']
  2. Escapando el espacio en blanco #un\ dos {}. Ver demo.

Selector CSS de clase '.'

El Selector de clase se conforma en el CSS anteponiendo un punto '.' al valor que tenga el atributo 'class' del elemento en el html.

Así, el selector .miclase apuntará a todos los elementos del documento al que afecte la hoja de estilos que tengan declarado class="miclase".

El atributo 'class' admite valores múltiples separados por un espacio en blanco. Así que se puede conformar un selector de clase con un solo valor de clase o múltiples.

Si queremos seleccionar un elemento que tiene dos clases en su atributo class="una_clase otra_clase" el selector se conforma con ambos valores (precedidos de su punto '.') sin espacio en blanco de separación entre ambos:

En el html <p class="una_clase">...</p> <p class="una_clase otra_clase">...</p> En el CSS .una_clase {}Aplica por igual a los 2 'p' anteriores .una_clase.otra_clase {}Sólo aplica al segundo 'p'

En caso de colisión de estilos prevalece la segunda regla con independencia del orden por ser más específica

Selector CSS por nombre y valor de atributo

Además de la forma anterior para conformar los selectores CSS por el valor del atributo de clase o id, se pueden construir utilizando expresiones CSS encerradas entre corchetes rectos '[algo]'.

Tradicionalmente el valor del atributo se escribía entre comillas simples o dobles. Actualmente puede aparecer entre ellas o sin ellas. Ambas grafías aparecen el la documentación del consorcio y el validador las admite sin marcar error.

Puedes ampliar este apartado en el artículo Selector CSS por valor de Atributo: simplifica la hoja de estilos y el Html

[att]

Representa a cualquier elemento que tenga el atributo 'att' cualquiera que sea su valor, incluso con valor vacío.

p:not([class]) {}

Este selector CSS selecciona a todos los párrafos que no tengan el atributo 'class' en su etiqueta. <p>...</p> sí se vería afectado pero no <p class>...</p> aunque el valor de su clase esté vacío.

[att=algo]

Representa cualquier elemento en el que el valor de su atributo 'att' es exáctamente 'algo'. Ni más ni menos.

[att~=algo]

Representa un elemento cuyo valor del atributo 'att' está formado por una lista de cadenas textuales separadas por espacios en blanco y una de ellas es exáctamente 'algo'

[att|=algo]

En este caso el valor del atributo 'att' es exáctamente 'algo' o comienza por la cadena 'algo' seguida de un guión medio '-'. Pensado originalmente para identificar los atributos de tipo de lenguaje que comparten el mismo idioma:

p[lang|=es] {color: red;} dibujaría en color rojo todos los párrafos cuyo atributo 'lang' tenga el valor 'es' y ademas los 'es-algo'

En estas expresiones y las siguientes 'att' significa cualquier nombre de atributo, como puede ser 'id', 'class', 'longdesc'. 'title', étc.

Selector CSS por subcadena coincidente en el valor del atributo

El selector css de atributo además de conformase con un valor del atributo, también puede hacerlo utilizando una parte de dicho valor.

[att^=algo]

El selector CSS [att^=algo] apunta al elemento con el atributo 'att' cuyo valor comienza exáctamente por la cadena de texto 'algo'.

[att$=algo]

En este caso el valor del atributo 'att' finaliza con la cadena de texto 'algo'.

[att*=algo]

Representa un elemento con el atributo 'att' cuyo valor contiene en él al menos una vez la subcadena 'algo'.

En estos casos si 'algo' es una cadena vacía el selector es nulo, no apunta a nada.

identificador i

CSS es un lenguaje insensible al uso de mayúsculas o minúsculas (es case-insensitive). Sin embargo hay lenguajes a los que aplica CSS donde esto no ocurre. Como XML o xHTML. En ellos los atributos de los elementos y sus valores sí que son case-sensitive. Así que en ellos no es lo mismo EL que el.

Para evitar los problemas derivados de este hecho CSS define el identificador i que añadido justo antes del corchete de cierre i] convierte al selector CSS en case-insensitive para el documento de destino aunque dicho documento sí sea case-sensitive.

Más información en detalle en el artículo Selector atributo [case-insensitive i]

Pseudoclases y Pseudoelementos

El grupo de selectores CSS conformado por alguna pseudoclase o pseudoelemento es el que mayor crecimiento ha experimentado en el desarrollo de CSS3 (documentos nacidos tras el cierre del nivel 2 de CSS o CSS2.1

En algunos casos la diferencia entre una u otro es difusa y poco intuitiva y su clasificación entre unas u otros no se alcanza a ver. En la actualidad (selectores level 4) se clasifican y agrupan atendiendo a particularidades de lo más variado.

Para ver cómo definía CSS2.1 a unas y otros tienes la traducción de sidar.org. Resumiendo y para diferenciar unas de otras:

Pseudoelementos y sus selectores

Podría decirse que los pseudoelementos son parte del documento que no tienen la entidad de elemento o que símplemente no existen en él. Esto es, no están 'contenidos en' o 'marcados con' una etiqueta (tag) que lo identifique y "separe" del resto. Son abstracciones.

Si echas un vistazo al código fuente del documento no los encontrarás en él escritos y marcados.

El selector CSS de pseudoelemento es una herramienta para poder apuntar desde la hoja de estilos a una parte del documento que no tiene entidad propia (categoría de elemento u objeto en el DOM) y que por lo tanto, de no existir el selector CSS de pseudoelemento oportuno, no sería posible declararle estilos específicos.

Grafía del selector CSS de pseudoelemento

Tradicionalmente (epecidicación CSS2.1) la forma de escribir el selector de pseudoelemento era anteponer el carácter ortográfico : (dos puntos) al su nombre. Con el desarrollo de CSS3 esta grafía se cambió a duplicar los dos puntos :: para diferenciarlos de los selectores de pseudoclase. Ambas formas son funcionales y reconocidas por los navegadores en sus versiones más actuales.

Pseudoclases y sus selectores

La pseudoclase es una información contenida en el propio elemento pero fuera (no forma parte) del DOM.

El selector de pseudoclase es una herramienta para poder apuntar desde la hoja de estilos a un elemento del DOM en base a alguna información o detalle ajeno al propio elemento o al "árbol del documento".

Esta información a la que se refiere la especificación puede ser de lo más variada y en base a ella los acota y clasifica la especificación. Puede ser por el estado en que se encuentre el elemento, por el número que hace al aparece en el DOM, a resultas de alguna acción del usuario...

Todos los pseudoelementos y pseudoclases

Tradicionalmente el número de pseudoelementos y pseudoclases era muy reducido. Si visitas el enlace anterior a la traducción del SIDAR lo podrás comprobar.

Sin embargo con el paso del tiempo han ido surgiendo necesidades nuevas en este apartado de los selectores CSS y su respuesta y resultado ha sido una larga lista de ellos (de ambos tipos de selectores CSS).

En la actualidad, casi todas las diferentes pseudoclases están contenidas y explicadas en el documento que desarrolla los selectores. Casi todas.

Pero los pseudoelementos incluidos en dicho documento son minoría. Tanto algunas pseudoclases como muchos de los pseudoelementos actuales se encuentran repartidos por los distintos documentos del W3c que los desarrollan.

Hace un tiempo recopilé todos los existentes entonces (23 de Marzo de 2014) en el artículo Selectores CSS de pseudoclases y pseudoelementos. Todos los existentes, mucho más completa que el documento CSS Pseudo-Elements Module Level 4 que sólo recoge los tradicionales.

Todos los selectores CSS de pseudoelemento

Recuerda que en los elementos reemplazados no se genera contenido. Esto es, no opera la propiedad content.

Todos los selectores CSS de pseudoclases

Queda para otro artículo entrar a fondo en cada uno de estos selectores y sus semejanzas y diferencias.

avatar del Editor del blog

Ramajero Argonauta, Enredique Amanuense de CSS.
#impoCSSible inside
Dicen que, en español, EsCss es el mejor blog de CSS. Posíblemente exageren.
@Kseso EsCss Don Kseso Kseso