Saltar enlaces

Alternativas a la palabra clave !importante

De vez en cuando, me topo con un antiguo proyecto mío, o peor aún, de otra persona, y recuerdo lo desordenado que puede volverse CSS con el tiempo. En la mayoría de estos casos, !important Las palabras clave parecen estar involucradas de una forma u otra. Y es fácil ver por qué los desarrolladores confían en él. Proporciona soluciones inmediatas y obliga a que las reglas tengan prioridad en la cascada.

Esto no quiere decir !important No hay lugar para ello. El problema es que una vez que empiezas a usarlo ya no funciona. y Cascada; lo estás pasando por alto. En proyectos grandes con varias personas involucradas, esto puede salirse de control rápidamente y cada nueva anulación hace que la siguiente sea más difícil.

Las capas en cascada, los trucos de especificidad, la clasificación más inteligente e incluso algunos trucos de selección inteligentes a menudo pueden reemplazar !important Explícale algo más limpio, más predecible y menos embarazoso para tu yo futuro.

Hablemos de estas alternativas.

especificidad y !important

La especificidad del selector es una profunda madriguera y no es el objetivo de esta discusión. Es decir, entender por qué. !important Ahora que existe, primero debemos ver cómo CSS decide qué reglas aplicar. escribí un breve descripción general La especificidad es un buen punto de partida. Chris también tiene un artículo interesante. encima de eso. Si realmente desea profundizar en todos los casos extremos, Frontend Guru tiene una Colapso completo.

En resumen, CSS le da “peso” a cada selector. Cuando dos reglas apuntan al mismo elemento, gana la regla con mayor especificidad. Si la especificidad es la misma, entonces Reglas declaradas más adelante en la hoja de estilo. prioridad.

  • estilos en línea (style="...") es el más pesado.
  • selector de identificación (#header) es más fuerte que los selectores de clase o tipo.
  • Selectores de categorías, atributos y pseudoclases. (.btn, (type="text"), :hover) tiene un peso medio.
  • Selectores de tipo y pseudoelementos (div, p, ::before) tiene el peso más bajo. A pesar de, * Un selector con especificidad 0-0-0 es incluso menor que un selector de tipo con especificidad 0-0-1.
/* Low specificity (0,0,1) */
p {
  color: gray;
}

/* Medium specificity (0,1,0) */
.button {
  color: blue;
}

/* High specificity (1,1,0) */
#header .button {
  color: red;
}
<!-- Inline style (1,0,0) -->
<p style="color: green;">Hello</p>

La pesadez de los estilos en línea también explica por qué a menudo están mal vistos y no se consideran CSS “limpios”, ya que pasan por alto gran parte de la estructura normal que intentamos mantener.

!important Cambie este comportamiento. Omite la especificidad normal y el orden de origen, empujando la declaración a la parte superior de sus capas original y en cascada:

p {
  color: red !important;
}

#main p {
  color: blue;
}

A pesar de #main p Más específicamente, el párrafo aparecerá en rojo porque !important La declaración lo anula.

Por qué !important Puede haber un problema

Este es un ciclo de vida típico. !important En un proyecto que involucra a varios desarrolladores:

“¿Por qué esto no funciona? Agregar !important. Vale, solucionado. “

Luego llega alguien más e intenta cambiar el mismo componente. Sus reglas no se aplicaban y después de investigar un poco descubrieron !important. Ahora tienen una opción:

  • Quítelo y corre el riesgo de romper algo más,
  • o agregar otro !important Cúbrelo.

Dado que nadie está completamente seguro de por qué se agregó el primero, el movimiento más seguro a menudo parece agregar otro. En proyectos grandes, esta situación puede salirse de control rápidamente.

Desde una perspectiva más técnica, la cuestión fundamental es !important es que rompe el orden esperado de la cascada. CSS está diseñado para resolver conflictos de forma predecible mediante la especificidad y el orden del código fuente. Las reglas posteriores anulan las reglas anteriores y los selectores más específicos anulan los selectores menos específicos.

El cambio de tema es un lugar común donde esto se hace evidente. Considere el siguiente ejemplo:

.button {
  color: red !important;
}

.dark .button {
  color: white;
}

Incluso en el tema oscuro, el botón permanece rojo. Esto hace que sea más difícil razonar sobre las hojas de estilo porque la cascada ya no es predecible.

Especialmente en equipos grandes, esto puede dificultar el mantenimiento y la depuración. Nada de esto significa !important nunca debe usarse. Existen casos legítimos para ello, especialmente en clases de utilidad, anulaciones de accesibilidad u hojas de estilo de usuario. Sin embargo, si lo está utilizando como su método preferido para resolver conflictos de selector/estilo, generalmente es una señal de que algo más en la cascada necesita atención.

Veamos las alternativas.

capa en cascada

Las capas en cascada son una característica más avanzada de CSS y tienen una mucho teorías sobre ellos. A los efectos de esta discusión, nos centraremos en cómo pueden ayudarle a evitar !important. Si quieres saber más, Miriam Susana escribió un La guía completa de capas en cascada CSS Está bastante detallado arriba.

En resumen, las capas en cascada le permiten definir grupos prioritarios claros en tu CSS. En lugar de confiar en la especificidad del selector, usted decide de antemano categoría El estilo debe tener prioridad. Puede predefinir el orden de las capas:

@layer reset, defaults, components, utilities;

Esto establece un orden de prioridad de menor a mayor. Ahora puedes agregar estilos a estas capas:

@layer defaults {
  a:any-link {
    color: maroon;
  }
}

@layer utilities {
  (data-color="brand") {
    color: green;
  }
}

A pesar de (data-color="brand") especificidad inferior a a:any-linkeste utilities La capa tiene prioridad ya que se define más adelante en la pila de capas.

En particular, la especificidad aún se mantiene en capa. pero entre Capas, el orden de las capas tiene prioridad.

Las capas en cascada le permiten priorizar categorías enteras de estilos en lugar de una sola regla. Por ejemplo, la capa “Superposición” siempre tiene prioridad sobre la capa “Base”. Este tipo de pensamiento arquitectónico, en lugar de soluciones reactivas, puede evitar muchos dolores de cabeza.

Un ejemplo muy común es la integración de CSS de terceros. Si el marco viene con selectores muy específicos, puedes hacer esto:

@layer framework, components;

@import url('framework.css') layer(framework);

@layer components {
  .card {
    padding: 2rem;
  }
}

Los estilos de sus elementos ahora anulan automáticamente los estilos de marco siempre que no se utiliza el marco, independientemente de su especificidad del selector. !important.

Mientras hablamos de ello, vale la pena señalar que el uso !important y Las capas en cascada son en realidad contradictorias. eso es porque !important de hecho contrarrestar Orden de capas. Ya no es una forma rápida de saltar a la cima de las prioridades, sino una parte integral de nuestra estratificación en cascada; una manera de bajar niveles persistir en Algunos de sus estilos son esenciales.

Entonces, si ordenáramos un conjunto de capas como este:

  1. utilities (el más poderoso)
  2. components
  3. defaults (más débil)

usar !important Pon las cosas patas arriba:

  1. !important defaults (el más poderoso)
  2. !important components
  3. !important utilities
  4. Común utilities
  5. Común components
  6. Común defaults (más débil)

Observe lo que está sucediendo allí: crea tres capas de importancia nuevas e invertidas que reemplazan las tres originales, al tiempo que invierten todo el orden.

este :is() falso

este :is() Las pseudoclases son interesantes porque asumen la especificidad de los parámetros más específicos. Digamos que tienes un elemento que debe coincidir con el peso de un selector más específico en otra parte de tu código base:

/* somewhere in your styles */
#sidebar a {
  color: gray;
}

/* your component */
.nav-link {
  color: blue;
}

en lugar de usar !importantpuedes chocar .nav-link envuélvelo :is() Hay un argumento más específico:

:is(#some_id, .nav-link) {
  color: blue;
}

Ahora tiene especificidad de nivel de identificación y solo coincide .nav-link. Vale la pena señalar que el selector en el interior. :is() No es necesario que coincida con los elementos reales. estamos usando #some_id Simplemente para agregar especificidad en este caso.

notas: si #some_id realmente existe en su marcado, este selector también se ajustará a ese elemento. Por lo tanto, es mejor utilizar una identificación no utilizada para evitar efectos secundarios.

por otro lado, :where() Lo contrario es cierto. Siempre se resuelve en (0,0,0), sin importar lo que haya dentro. Esto es útil para reinicios o estilos básicos que desees. cualquier cosa Aguas abajo se puede cubrir fácilmente.

Doble selector

Una forma muy sencilla de aumentar la especificidad del selector es repetir el selector. Esto generalmente se hace a través de cursos. Por ejemplo:

.button {
  color: blue;
}

.button.button {
  color: red;  /* higher specificity */
}

Por lo general, no conviene hacer esto con demasiada frecuencia, ya que puede convertirse en una pesadilla de legibilidad.

Reordenar

CSS resuelve las relaciones de especificidad en el orden de origen, por lo que las reglas que aparecen más tarde tienen prioridad. Esto es fácil de pasar por alto, especialmente en hojas de estilo más grandes donde los estilos se distribuyen en varios archivos.

Si reglas más generales siguen anulando reglas más específicas con la misma especificidad, verifique si las reglas generales se cargan después de sus reglas. Invertir el orden resuelve los conflictos sin aumentar la especificidad.

Por eso vale la pena pensar en la organización de las hojas de estilo desde el principio. Un patrón común es de lo general a lo específico (restablecer y estilos básicos primero, luego diseño, luego componentes, luego utilidades).

Al usar !important Tiene sentido

Después de todo, vale la pena aclarar: !important De hecho, existen casos de uso legítimos. Chris habló de esto no hace mucho.también vale la pena leer la reseña.

El caso más común es la categoría de servicios públicos. Por ejemplo, el curso se centra en .visually-hidden En todas partes sólo hacen una cosa. En este caso, no querrás que el selector más específico lo deshaga silenciosamente en otro lugar. Lo mismo ocurre con categorías de estatus como .disabled o un estilo de componente genérico como .button.

.visually-hidden {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  overflow: hidden !important;
  clip-path: inset(50%) !important;
}

La cobertura de terceros es otro escenario común. !important Esto se puede usar aquí para anular los estilos en línea establecidos en JavaScript o los estilos normales en una hoja de estilo que no se puede editar.

Desde una perspectiva de accesibilidad, !important Es insustituible para las hojas de estilo de usuario. Dado que se aplican a todas las páginas web y realmente no hay garantía de que el selector de la hoja de estilo siempre tenga la mayor especificidad, !important Básicamente, la única forma confiable de garantizar que sus estilos siempre tengan prioridad.

Otro buen ejemplo es respetar las preferencias del navegador del usuario, p.e. Reducir el ejercicio:

@media screen and (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

Resumir

La diferencia entre buen y mal uso !important Realmente todo se reduce a la intención. ¿Lo está utilizando porque comprende CSS Cascade y esta declaración debería aplicarse siempre? ¿O lo usas como curita? Esto último inevitablemente causará problemas.

lectura adicional

Home
Account
Cart
Search
¡Hola! ¡Pregúntame lo que quieras!
Explore
Drag