CSS
Cascada y especificidad
Buscar..
Observaciones
La especificidad de CSS pretende promover la concisión del código al permitir que un autor defina algunas reglas de formato generales para un conjunto amplio de elementos y luego las anule para un determinado subconjunto.
En cascada
La cascada y la especificidad se utilizan juntas para determinar el valor final de una propiedad de estilo CSS. También definen los mecanismos para resolver conflictos en conjuntos de reglas CSS.
CSS orden de carga
Los estilos se leen de las siguientes fuentes, en este orden:
- Hoja de estilo del agente de usuario (los estilos suministrados por el proveedor del navegador)
- Hoja de estilo del usuario (el estilo adicional que un usuario ha establecido en su navegador)
- Hoja de estilo del autor (Autor aquí significa el creador de la página web / sitio web)
- Tal vez uno o más archivos
.css
- En el elemento
<style>
del documento HTML
- Tal vez uno o más archivos
- Estilos en línea (en el atributo de
style
en un elemento HTML)
El navegador buscará los estilos correspondientes al renderizar un elemento.
¿Cómo se resuelven los conflictos?
Cuando solo un conjunto de reglas CSS intenta establecer un estilo para un elemento, entonces no hay conflicto y se usa ese conjunto de reglas.
Cuando se encuentran varios conjuntos de reglas con configuraciones en conflicto, primero las reglas de Especificidad y luego las reglas en cascada se usan para determinar qué estilo usar.
Ejemplo 1 - Reglas de especificidad
.mystyle { color: blue; } /* specificity: 0, 0, 1, 0 */
div { color: red; } /* specificity: 0, 0, 0, 1 */
<div class="mystyle">Hello World</div>
¿De qué color será el texto? (pasa el cursor para ver la respuesta)
azul
Primero se aplican las reglas de especificidad, y la que tiene la mayor especificidad "gana".
Ejemplo 2 - Reglas de cascada con selectores idénticos
Archivo css externo
.class {
background: #FFF;
}
Css interno (en archivo HTML)
<style>
.class {
background: #000;
}
<style>
En este caso, donde tiene selectores idénticos, la cascada se activa y determina que el último cargado "gana".
Ejemplo 3 - Reglas en cascada después de las reglas de especificidad
body > .mystyle { background-color: blue; } /* specificity: 0, 0, 1, 1 */
.otherstyle > div { background-color: red; } /* specificity: 0, 0, 1, 1 */
<body class="otherstyle">
<div class="mystyle">Hello World</div>
</body>
¿De qué color será el fondo?
rojo
Después de aplicar las reglas de especificidad, todavía hay un conflicto entre azul y rojo, por lo que las reglas en cascada se aplican sobre las reglas de especificidad. En cascada se analiza el orden de carga de las reglas, ya sea dentro del mismo archivo .css
o en la colección de fuentes de estilo. El último cargado anula los anteriores. En este caso, la regla .otherstyle > div
"gana".
Una nota final
- La especificidad del selector siempre tiene prioridad.
- Hoja de estilo para romper lazos.
- Los estilos en línea triunfan sobre todo.
La! Declaración importante
La declaración !important
se utiliza para anular la especificidad habitual en una hoja de estilo al dar mayor prioridad a una regla. Su uso es: property : value !important;
#mydiv {
font-weight: bold !important; /* This property won't be overridden
by the rule below */
}
#outerdiv #mydiv {
font-weight: normal; /* #mydiv font-weight won't be set to normal
even if it has a higher specificity because
of the !important declaration above */
}
Se recomienda encarecidamente evitar el uso de !important
(a menos que sea absolutamente necesario), ya que perturbará el flujo natural de las reglas de CSS que pueden generar incertidumbre en su hoja de estilo. También es importante tener en cuenta que cuando se aplican varias declaraciones !important
a la misma regla en un elemento determinado, la que tenga una mayor especificidad será la aplicada.
Aquí hay algunos ejemplos donde se puede justificar el uso de !important
declaración !important
:
- Si sus reglas no deberían ser anuladas por ningún estilo en línea del elemento que está escrito dentro del atributo de
style
del elemento html. - Para dar al usuario un mayor control sobre la accesibilidad de la web, como aumentar o disminuir el tamaño del tamaño de fuente, anulando el estilo de autor usando
!important
. - Para pruebas y depuración utilizando el elemento inspeccionar.
Ver también:
Cálculo de la especificidad del selector
Cada selector de CSS individual tiene su propio valor de especificidad. Cada selector en una secuencia aumenta la especificidad general de la secuencia. Los selectores se clasifican en uno de tres grupos de especificidad diferentes: A , B y c . Cuando múltiples secuencias de selección seleccionan un elemento dado, el navegador utiliza los estilos aplicados por la secuencia con la mayor especificidad general.
Grupo | Compuesto de | Ejemplos |
---|---|---|
UNA | selectores de identificación | #foo |
segundo | selectores de clase selectores de atributos pseudo-clases | .bar [title] , [colspan="2"] :hover :nth-child(2) |
do | selectores de tipo pseudo-elementos | div , li ::before , ::first-letter |
El grupo A es el más específico, seguido del grupo B y , finalmente, el grupo c .
El selector universal ( *
) y los combinadores (como >
y ~
) no tienen especificidad.
Ejemplo 1: Especificidad de varias secuencias de selección
#foo #baz {} /* a=2, b=0, c=0 */
#foo.bar {} /* a=1, b=1, c=0 */
#foo {} /* a=1, b=0, c=0 */
.bar:hover {} /* a=0, b=2, c=0 */
div.bar {} /* a=0, b=1, c=1 */
:hover {} /* a=0, b=1, c=0 */
[title] {} /* a=0, b=1, c=0 */
.bar {} /* a=0, b=1, c=0 */
div ul + li {} /* a=0, b=0, c=3 */
p::after {} /* a=0, b=0, c=2 */
*::before {} /* a=0, b=0, c=1 */
::before {} /* a=0, b=0, c=1 */
div {} /* a=0, b=0, c=1 */
* {} /* a=0, b=0, c=0 */
Ejemplo 2: Cómo se usa la especificidad por el navegador
Imagina la siguiente implementación de CSS:
#foo {
color: blue;
}
.bar {
color: red;
background: black;
}
Aquí tenemos un selector de ID que declara el color
como azul , y un selector de clase que declara el color
como rojo y el background
como negro .
Un elemento con un ID de #foo
y una clase de .bar
será seleccionado por ambas declaraciones. Los selectores de ID tienen una especificidad de Grupo A y los selectores de clase tienen una especificidad de Grupo B. Un selector de ID supera cualquier número de selectores de clase. Por eso, color:blue;
desde el selector #foo
y el background:black;
Desde el selector .bar
se aplicará al elemento. La mayor especificidad del selector de ID hará que el navegador ignore la .bar
de color
del selector .bar
.
Ahora imagine una implementación diferente de CSS:
.bar {
color: red;
background: black;
}
.baz {
background: white;
}
Aquí tenemos dos selectores de clase; uno de los cuales declara el color
como rojo y el background
como negro , y el otro declara el background
como blanco .
Un elemento con ambas clases .bar
y .baz
se verá afectado por estas dos declaraciones, sin embargo, el problema que tenemos ahora es que tanto .bar
como .baz
tienen una especificidad idéntica al Grupo B. La naturaleza en cascada de CSS resuelve esto por nosotros: como .baz
se define después de .bar
, nuestro elemento termina con el color
rojo de .bar
pero el background
blanco de .baz
.
Ejemplo 3: Cómo manipular la especificidad.
El último fragmento del Ejemplo 2 anterior se puede manipular para garantizar que se .bar
la declaración de color
del selector de clase .bar
lugar de la del selector de clase .baz
.
.bar {} /* a=0, b=1, c=0 */
.baz {} /* a=0, b=1, c=0 */
La forma más común de lograr esto sería averiguar qué otros selectores se pueden aplicar a la secuencia del selector .bar
. Por ejemplo, si el .bar
clase sólo se aplicó nunca a span
elementos, podríamos modificar el .bar
selector para span.bar
. Esto le daría una nueva especificidad para el Grupo C , que anularía la falta del mismo .baz
selector:
span.bar {} /* a=0, b=1, c=1 */
.baz {} /* a=0, b=1, c=0 */
Sin embargo, es posible que no siempre sea posible encontrar otro selector común que se comparta entre cualquier elemento que use la clase .bar
. Debido a esto, CSS nos permite duplicar los selectores para aumentar la especificidad. En lugar de solo .bar
, podemos usar .bar.bar
en .bar.bar
lugar (Ver La gramática de los selectores, Recomendación W3C ). Esto aún selecciona cualquier elemento con una clase de .bar
, pero ahora tiene el doble de especificidad de Grupo B :
.bar.bar {} /* a=0, b=2, c=0 */
.baz {} /* a=0, b=1, c=0 */
Declaraciones de estilo !important
y en línea.
Se considera que la !important
en una declaración de estilo y los estilos declarados por el atributo de style
HTML tienen una mayor especificidad que cualquier selector. Si existen, la declaración de estilo que afectan anulará otras declaraciones independientemente de su especificidad. Es decir, a menos que tenga más de una declaración que contenga un indicador !important
para la misma propiedad que se aplica al mismo elemento. Luego, las reglas de especificidad normales se aplicarán a esas propiedades en referencia entre sí.
Debido a que anulan completamente la especificidad, el uso de !important
está mal visto en la mayoría de los casos de uso. Uno debería usarlo lo menos posible. Para mantener el código CSS eficiente y mantenible a largo plazo, casi siempre es mejor aumentar la especificidad del selector circundante que utilizarlo !important
Una de esas raras excepciones en las que lo !important
no está mal visto, es cuando se implementan clases auxiliares genéricas como una .hidden
o .background-yellow
que se supone que siempre anulan una o más propiedades donde sea que se encuentren. E incluso entonces, necesitas saber lo que estás haciendo. Lo último que desea, al escribir CSS mantenible, es tener !important
todo su CSS.
Una nota final
Un error común acerca de la especificidad de CSS es que los valores de los grupos A , B y c deben combinarse entre sí ( a=1, b=5, c=1
=> 151). Este no es el caso. Si este fuera el caso, tener 20 de un selector de grupo B o c sería suficiente para anular un solo selector de grupo A o B , respectivamente. Los tres grupos deben considerarse como niveles individuales de especificidad. La especificidad no puede ser representada por un solo valor.
Al crear su hoja de estilo CSS, debe mantener la menor especificidad posible. Si necesita hacer que la especificidad sea un poco más alta para sobrescribir otro método, hágalo más alto pero lo más bajo posible para hacerlo más alto. No deberías tener un selector como este:
body.page header.container nav div#main-nav li a {}
Esto hace que los cambios futuros sean más difíciles y contaminan esa página css.
Puedes calcular la especificidad de tu selector aquí
Ejemplo de especificidad más compleja.
div {
font-size: 7px;
border: 3px dotted pink;
background-color: yellow;
color: purple;
}
body.mystyle > div.myotherstyle {
font-size: 11px;
background-color: green;
}
#elmnt1 {
font-size: 24px;
border-color: red;
}
.mystyle .myotherstyle {
font-size: 16px;
background-color: black;
color: red;
}
<body class="mystyle">
<div id="elmnt1" class="myotherstyle">
Hello, world!
</div>
</body>
¿Qué bordes, colores y tamaño de fuente será el texto?
tamaño de fuente:
font-size: 24;
, dado que#elmnt1
reglas#elmnt1
tiene la mayor especificidad para el<div>
en cuestión, todas las propiedades aquí se establecen.
frontera:
border: 3px dotted red;
. Elred
color del borde se toma del conjunto de reglas#elmnt1
, ya que tiene la mayor especificidad. Las otras propiedades del borde, grosor de borde y estilo de borde son del conjunto de reglasdiv
.
color de fondo:
background-color: green;
. Elbackground-color
se establece en los conjuntos debody.mystyle > div.myotherstyle
div
,body.mystyle > div.myotherstyle
y.mystyle .myotherstyle
. Las especificidades son (0, 0, 1) vs. (0, 2, 2) vs. (0, 2, 0), por lo que el medio "gana".
color:
color: red;
. El color se establece en los conjuntos de reglasdiv
y.mystyle .myotherstyle
. Este último tiene la especificidad más alta de (0, 2, 0) y "gana".