Existe el eterno debate si CSS es un lenguaje de programación o no y aunque está evolucionando constantemente con características potentes, habrá quienes menosprecian un poco al lenguaje por no poder enfocarse a lógica de negocio tradicional.
El debate siempre estará sobre la mesa y mientras tanto mostraré algunos elementos que han llamado mi atención, unas pseudo-clases de CSS muy útiles:
:is(), :where(), :has()
- Probadas en Chrome 105
¿Qué es una Pseudo-clase?
Es una palabra clave que se le puede añadir a los selectores para para especificar un estado que pudiera sufrir o cambiar su estilo, por ejemplo un botón con una acción hover:
button:hover {
background-color: red;
}
Las pseudo-clases solían ser un poco anticuadas y se enfocaban en acciones ejecutadas por un usuario dentro de un navegador. Ahora ya contienen una lógica de toma de decisiones para la especificidad de CSS, algo parecido a que en un lenguaje de programación tradicional se declare una sentencia if.
El ejercicio
Primero quiero que veas el ejemplo completo con el siguiente código HTML:
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]> <html class="no-js"> <![endif]-->
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Pseudo-classes CSS</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
@import url('https://fonts.googleapis.com/css2?family=Handlee&display=swap');
body {
font-family: 'Handlee', cursive;
font-size: 18px;
color: #1d1a9e;
background-color: #f5f3ea;
}
h1 {
font-size: 24px;
text-align: center;
color: #484848;
padding: 16px;
line-height: 50px;
background: radial-gradient(#bfbfbf, transparent);
box-shadow: 2px 2px 6px #bfbfbf;
border-radius: 8px;
}
h1:has(span) {
color: #1d1a9e;
}
h1:has(span) span {
color: #eb0707;
}
@counter-style repeating-emoji {
system: cyclic;
symbols: "😱""😎""🥳""🧐""🤩";
suffix: " ";
}
:where(ul) ul {
list-style-type: repeating-emoji;
color: #0f9014;
font-weight: bold;
}
/* con esto tendriamos el mismo resultado que where() */
/* :is(ul) ul {
list-style-type: repeating-emoji;
color: #0f9014;
font-weight: bold;
} */
</style>
</head>
<body>
<h1>Pseudo <span>- Clasess</span></h1>
<h1>No tenemos un tag <strong>
<"span">
</strong></h1>
<h1>:where() <span>and</span> :is()</h1>
<container>
<ul>
<li>Javascript</li>
<li>HTML</li>
<li>CSS
<ul>
<li>Pseudo-classes</li>
<li>Pseudo-elements</li>
<li>Selectores</li>
<li>Modules</li>
<li>Etc...</li>
</ul>
</li>
</ul>
</container>
</body>
</html>
Tendrás que colocar el archivo con nombre index.html dentro de una carpeta nueva y ejecutar el siguiente comando:
docker run --rm -i -t --name server-test-css -p 8080:80 -v "$PWD":/usr/local/apache2/htdocs/ httpd:2.4
Esto iniciará un servidor apache2 en localhost:8080.
:has()
La pseudo-clase :has() cumplirá con la condición si alguno de los selectores recibidos en los parámetros se encuentra como hijo del selector principal, como tal lo haría una compuerta lógica OR:
:has(inserte_selector1, inserte_selector2, inserte_selector3)
En el ejemplo tenemos esto:
h1:has(span) {
color: #1d1a9e;
}
Indica que los selectores principales h1 que contenga un hijo con selector span definen el color: #1d1a9e.
Mientras:
h1:has(span) span {
color: #eb0707;
}
Indica que los selectores h1 que contenga un hijo con selector span, los elementos span dentro del h1, modificará el color: #eb0707.
is() y where()
Estas pseudo-clases son similares y cumplen el mismo fin:
:where(ul) ul {
list-style-type: repeating-emoji;
color: #0f9014;
font-weight: bold;
}
/* con esto tendríamos el mismo resultado que where() */
:is(ul) ul {
list-style-type: repeating-emoji;
color: #0f9014;
font-weight: bold;
}
Es decir, las siguientes declaraciones de estilos tendrían el mismo efecto en el navegador. En este ejemplo nos indica que los selector ul que contengan un hijo con selector ul, el hijo ul será estilizado con lo definido.
La diferencia entre estas dos pseudo-clases radica en otro contexto diferente donde la especificidad es importante. :where() no tiene especificidad y si hay una especificidad mayor en algún selector dentro de los parámetros recibidos, esta se vuelve 0. Mientras :is() tiene una especificidad de 1, también puede tomar la especificidad de su selector de los parámetros, siempre y cuando sea mayor.
Conclusión
Si después de realizar el ejemplo no te queda muy claro que CSS tiene características de un lenguaje de programación, tendrás que imaginar estás pseudo-clases como funciones, las cuales realizan una tarea de agrupamiento de selectores para tomar decisiones a la hora de estilizar elementos HTML.