Comprender la especificidad en CSS

La especificidad en CSS se refiere a la forma en que los navegadores determinan la importancia, la relevancia y la “antigüedad” de los estilos CSS. Aquí analizaremos todos los tipos de estilos CSS y utilizaremos la analogía de la empresa para comprender cómo se resuelven los estilos en competencia.
Descripción general del selector CSS
Existen varias formas de seleccionar los elementos a los que intenta aplicar estilos en CSS. Comencemos por revisar todas las opciones.
- Selectores de tipo:Seleccione el elemento deseado utilizando su tipo de elemento. Por ejemplo, para seleccionar todas las
p
etiquetas, utilicep
en su hoja de estilo CSS. - Pseudo-elementos:Como sugiere el nombre, los pseudoelementos no son elementos en sí mismos, pero permiten seleccionar parte de su HTML en relación con otro selector. Por ejemplo, seleccione la primera letra de cada párrafo con
p::first-letter
. - Selectores de clase:Los elementos pueden tener varias clases configuradas para que se puedan seleccionar en la hoja de estilo CSS. Por ejemplo,
h1 class='header'
se pueden seleccionar con.header
. Se puede aplicar la misma clase a varios elementos. - Selectores de atributos: Seleccione elementos a los que se les haya aplicado un tipo específico de atributo. Por ejemplo, seleccione entradas que solo acepten números con
input[type='number']
. - Pseudo-clases:Seleccione elementos en función del estado CSS en el que se encuentran. Por ejemplo, aplique estilo al estado de desplazamiento de un botón con
button:hover
. Consulte estos tutoriales anteriores sobre las pseudoclases :target, :hover y :active para obtener más información. - Selectores de ID: Seleccione un elemento específico con su ID único. Solo puede haber un elemento con cada ID, mientras que las clases se pueden aplicar a varios elementos. Por ejemplo, seleccione
h1 id='mainHeader'
con#mainHeader
. - Estilos en línea:Los estilos en línea se aplican a los elementos directamente con el
style
atributo, por lo que no se utilizan selectores CSS. Por ejemplo, puedes hacer que el color de la fuente del encabezado sea azul directamente conh1 style='color: blue;'
Selectores CSS y sus “pesos”
Cada tipo de selector mencionado anteriormente tiene un peso. Todos ellos se pueden dividir en cuatro grupos principales:
- peso más bajo:selectores de tipo y pseudoelemento
- bajo peso:selectores de clase, atributo y pseudoclase
- peso medio:Selectores de ID
- alto peso: estilo en línea
Si se aplican estilos de distinto peso al mismo elemento, se aplicará el estilo con el peso más alto. Si se aplican estilos de pesos iguales, se aplicarán los estilos que aparezcan al final (los más cercanos al final de la hoja de estilos). Esto se debe al efecto "en cascada" de CSS (hojas de estilo en cascada).
En el caso de cualquier elemento al que se le aplique un estilo, se aplicará el último bloque de estilo aplicable con el peso más alto. Sin embargo, el estilo en línea prevalecerá sobre el estilo del selector CSS.
Cuando se aplican dos selectores del mismo peso a un elemento, se cuenta como el doble del peso. Por ejemplo, un elemento seleccionado con dos clases tendrá un peso mayor que uno solo en el CSS.
.gator.cayman { // two classes color: purple;}.gator { // one class color: purple;}
El problema principal al que nos enfrentaremos la mayoría de los desarrolladores web en algún momento es tener múltiples estilos que interfieren entre sí. Si utiliza un marco CSS, como Material UI, es posible que intente anular algunos estilos predeterminados. Alternativamente, puede tener un styles.css
archivo antiguo (y desorganizado) en el que tenga que seguir aumentando la especificidad porque no está claro por qué sus estilos no se aplican como se espera.
Como ocurre con todo lo relacionado con el desarrollo web, si comprende bien las herramientas, podrá utilizarlas con mayor precisión. Veamos cómo las distintas combinaciones de selectores afectan la especificidad y algunos trucos para que sus estilos se apliquen como corresponde.
El problema de los selectores que compiten entre sí
Comprender que los distintos selectores tienen distintos pesos es fundamental para organizar el CSS. Pero ¿qué pasa si no está claro qué tiene un peso mayor?
Digamos que tenemos un párrafo que tiene dos bloques completos de CSS: uno con tres clases coincidentes y otro bloque con un atributo de tipo y dos clases coincidentes.
Por ejemplo, tomemos esta entrada con tres clases y un number
atributo de tipo aplicado a ella.
input type='number' class='gator cayman reptile'
Si aplicamos estos selectores en competencia (tres clases coincidentes frente a dos clases coincidentes y un atributo), ¿cuál se aplicará?
.gator.cayman.reptile { color: purple;}[type='number'].gator.cayman { color: green;}
En este caso, el “peso” de ambos bloques es completamente parejo. Los selectores de atributos y los selectores de clases tienen el mismo peso y cada bloque tiene tres de ellos en total. Como son parejos, nos basamos en el efecto cascada de CSS. Se aplica el último y el color de la fuente de entrada será verde.
Sin embargo, esto se vuelve un poco más complicado cuando se mezclan selectores de diferentes pesos.
Actualicemos nuestra entrada para tener un ID, que tiene un peso mayor que las clases y los atributos.
input type='number' id='gatorInput' class='gator cayman reptile'
Si volvemos a tener estilos en competencia y usamos el ID para uno y las clases/atributos para el otro, ¿cuál se aplicará?
#gatorInput { color: purple;}[type='number'].gator.cayman.reptile { color: green;}
En el primer bloque, solo se utiliza un ID para aplicar el estilo. En el segundo bloque, hay tres clases y un selector de atributos, y aparece al final. Aunque hay más selectores en el segundo bloque, el selector de ID tiene un peso mayor y el texto será violeta.
Los selectores con un peso mayor siempre prevalecerán sobre aquellos con un peso menor, incluso si hay varios selectores con un peso menor.
Truco para seleccionar el peso
Un truco (bueno, hack) en CSS cuando solo necesitas un poco más de peso es repetir una clase en el mismo bloque de CSS.
input.gator.gator { color: purple;}input.gator { color: green;}
Quizás le sorprenda saber que el primer bloque tiene un peso de dos clases y el segundo bloque tiene un peso de una clase, aunque el primero simplemente repite la clase .gator
. Debido a que dos clases tienen un peso mayor que una, el texto de entrada será violeta.
Nunca deberías necesitar usar este truco en código de nivel de producción porque es un indicador de que tienes estilos de pesos muy similares compitiendo. Lo ideal sería que resolvieras esos estilos para que estén más claramente definidos. Sin embargo, esta es una buena herramienta en tu caja de herramientas CSS cuando estás en un modo de "hacer que funcione". ✨
La analogía de la empresa para la especificidad de CSS
A veces, la especificidad puede parecer contraintuitiva, especialmente si estás atrapado en una espiral descendente en la que debes agregar cada vez más selectores a tu CSS. Una forma que me resulta útil de pensar en la especificidad es pensar en una empresa con niveles de antigüedad claros.
A continuación se muestran los roles de nuestra empresa en orden de antigüedad (de menor a mayor):
- empleados
- gerentes
- directores
- Vicepresidentes
- Un CEO (volveremos al tema del CEO en un momento)
Ahora vamos a asignar estos roles a nuestros selectores:
- empleados:selectores de tipo y pseudoelemento
- gerentes:selectores de clase, atributo y pseudoclase
- directores:Selectores de ID
- Vicepresidentes: estilo en línea
Veamos un nuevo ejemplo. En este caso tenemos un párrafo con dos clases y un ID.
p id='gatorParagraph' class='gator reptile' blah blah blah/p
#gatorParagraph { color: purple;}p.gator.reptile { color: green;}
Tenemos un bloque que utiliza solo un ID y otro bloque que utiliza un tipo de elemento ( p
) y dos clases. A primera vista, puede resultar difícil saber cuál se aplicará.
Si utilizamos la analogía de nuestra empresa, tenemos un director que dice que el texto debe ser violeta. Por otro lado, tenemos un empleado y dos gerentes que dicen que debe ser verde. Como el director tiene la mayor antigüedad, puede imponerse a las opiniones de los empleados y los gerentes. ¡Así que el texto tiene que ser violeta!
(No hay comentarios sobre si así es como se deben tomar las decisiones en la empresa).
Considere cada nivel de peso como una forma de escalar la decisión de qué estilos aplicar. Si no pueden decidirlo los selectores del mismo nivel, escalarlo le dará la decisión al selector de mayor antigüedad.
Como regla general, es mejor escribir CSS que sea lo suficientemente específico como para que no tengas que buscar formas de seguir aumentando su importancia. Ten en cuenta que una vez que introduzcas un nuevo nivel de antigüedad, como un ID, también podrías estar anulando otros estilos sin querer.
¡Importante es el CEO!
Hasta ahora no hemos hablado de quién es el director ejecutivo de nuestra empresa en esta analogía sobre la especificidad de CSS. ¿Qué es más importante que el estilo en línea? ¡La !important
regla!
Usando el mismo ejemplo que antes, agreguemos !important
al bloque que anteriormente tenía un peso/antigüedad menor.
#gatorParagraph { color: purple;}p.gator.reptile { color: green !important;}
La incorporación de nuevos miembros !important
siempre aumentará la antigüedad hasta el nivel más alto posible. Con nuestra analogía de la empresa, ahora tenemos un director frente a un empleado, dos gerentes y el director ejecutivo. Tan pronto como se presente al director ejecutivo, podrá imponerse a cualquier otra cosa que se sugiera.
¡Por favor no utilices !importante!
La !important
regla es una pendiente resbaladiza y verla en los estilos CSS suele ser una señal de alerta de que es necesario reorganizar la especificidad. Es poco frecuente que haya un elemento al que solo se le pueda aplicar estilo eliminando el resto de las reglas CSS que de otro modo se aplicarían.
Una vez que se introduce !important
, suele dar lugar a un uso excesivo, como en el ejemplo siguiente. Las !important
s se anulan entre sí y hay que volver a comprender el peso y el efecto en cascada de cada bloque.
#gatorParagraph { color: purple !important;}p.gator.reptile { color: green !important;}
En lugar de utilizar la !important
regla, intenta abrir tus herramientas de desarrollo en el navegador para comprender mejor qué estilos están interfiriendo con los nuevos.
Una vez que sepa qué estilos le están causando problemas, puede agregar selectores adicionales del mismo nivel de peso o actualizar su marcado para usar selectores diferentes.
El uso de !important a menudo conducirá inevitablemente a tener estilos CSS en competencia que usan !important.
Selector y Combinadores Universales
El selector universal ( *
) y los combinadores no afectan el peso de los selectores. Los combinadores incluyen selectores secundarios ( ), selectores generales hermanos (
~
) y selectores hermanos adyacentes ( +
).
Por ejemplo, si tenemos un párrafo con dos tramos, usar un combinador secundario no aumentará la especificidad respecto a no usarlo:
p id='gatorParagraph' span class='reptile'eggs/span span class='reptile'nest/span/p
#gatorParagraph .reptile { color: purple;}#gatorParagraph .reptile{ color: green;}
Estos bloques de CSS tienen la misma especificidad (el combinador secundario no hace ninguna diferencia), por lo que el texto será verde.
Enlaces útiles
Una de las mejores herramientas visuales para comprender la especificidad de CSS se llama specifishity, de Estelle Weyl. ¡Échale un vistazo!
Además, si no está interesado en sumar los pesos de especificidad usted mismo, existe una calculadora de especificidad que hará los cálculos por usted.
Deja una respuesta