wandres.dev
HERENCIA · inherit, initial, unset, revert

inherit, initial, unset y revert

Las cuatro palabras clave que cualquier propiedad acepta, la diferencia crítica entre el valor inicial y el valor por defecto que ves, y qué hace realmente la propiedad all.

⏱ 16 min

Cualquier propiedad de CSS, sin excepción, acepta cuatro palabras clave que no describen un valor concreto sino un comportamiento de defecto. Se parecen lo bastante como para que se usen indistintamente y son lo bastante distintas como para que esa confusión produzca resultados desconcertantes. La que más problemas causa es initial, porque casi todo el mundo cree que significa “como estaba antes de que yo tocara nada”, y significa otra cosa.

🎯 Al terminar esta lección sabrás
  • Diferenciar las cuatro palabras clave globales por la pregunta que responde cada una.
  • Explicar por qué display: initial no devuelve el comportamiento por defecto de un div.
  • Usar la propiedad all conociendo las dos propiedades que no toca.
  • Escribir un control despojado sin destruir su accesibilidad.

Cuatro palabras, cuatro preguntas

Palabra Qué hace Pregunta que responde
inherit Toma el valor calculado del padre ¿Y si me pongo lo mismo que mi padre?
initial Toma el valor inicial definido en la especificación de la propiedad ¿Cuál es el valor de fábrica del lenguaje?
unset inherit si la propiedad es heredable, initial si no ¿Y si esta declaración no existiera?
revert Retrocede al origen anterior de la cascada ¿Y si mi CSS de autor no existiera?

inherit funciona con cualquier propiedad, también con las que no son heredables. Es la manera de forzar que un hijo tome el borde, el fondo o el ancho de su padre:

.icono { fill: inherit; }        /* el SVG toma el color del contenedor */
.celda { border-color: inherit; } /* aunque border-color no se herede */

unset es el que borra tu declaración de la ecuación: deja la propiedad exactamente como habría quedado si nunca hubieras escrito nada, con la salvedad de que sigue ganando la cascada, así que también borra las declaraciones anteriores de la misma propiedad.

revert es distinto y más profundo: no borra tu declaración, borra tu origen entero para esa propiedad y ese elemento. Desde el origen de autor, retrocede al nivel de usuario, de modo que el valor resultante es el que habría si ninguna hoja de autor hubiera dicho nada. Y ahí es donde aparece la diferencia que casi nadie tiene clara.

initial no es el valor por defecto que ves

El valor inicial de una propiedad es el que su especificación declara como punto de partida del lenguaje. El valor por defecto que observas en un navegador es el que resulta de aplicar la hoja de estilos del agente de usuario encima de ese valor inicial. No son lo mismo, y en varias propiedades importantes ni se parecen.

El caso canónico:

/* El valor inicial de display es inline, para todos los elementos */
div { display: initial; }   /* el div pasa a ser inline */

/* revert deshace tu origen y deja actuar a la hoja del navegador */
div { display: revert; }    /* el div vuelve a ser block */

El valor inicial de display es inline porque así lo define la especificación de la propiedad, y la hoja del navegador es la que asigna block a los div. initial ignora esa hoja; revert la respeta. Lo mismo pasa con font-size en un h1, con list-style en un ul, con font-weight en un strong o con el subrayado de un enlace: todo eso lo pone el navegador, no el valor inicial.

La consecuencia es una recomendación bastante tajante: cuando quieras “dejarlo como estaba”, casi siempre quieres revert, no initial. initial es útil cuando lo que buscas es realmente el punto de partida del lenguaje, y eso ocurre menos veces de las que la palabra sugiere.

all: initial produce un elemento que no existe en ningún navegador

Lleva el razonamiento anterior al extremo y verás por qué all: initial es una herramienta que conviene no usar casi nunca. Al aplicarla, todas las propiedades del elemento vuelven al valor inicial de la especificación: display pasa a inline, color a negro, font-family a la genérica del motor, font-size a medio, visibility a visible, y así con centenares de propiedades. El resultado es un elemento que no se parece a nada que exista en ningún navegador, porque los navegadores nunca muestran los valores iniciales puros: siempre hay una hoja de agente de usuario encima. Y como all es una abreviada que expande a todas las propiedades, cada una de esas declaraciones entra en la cascada y gana a cualquier cosa que hubieras escrito antes, así que el elemento queda además blindado contra la herencia: color, font-family y todo lo demás dejan de bajar desde arriba, cosa que casi nunca es lo que se pretendía. Hay dos usos legítimos y muy acotados. El primero, aislar una isla de contenido ajeno —el HTML de un correo, la salida de un editor de terceros— de la que quieras que ningún estilo tuyo se filtre; ahí all: initial es defendible porque el aislamiento total es exactamente el objetivo, y aun así conviene comprobar el resultado con lupa. El segundo, ninguno más. Para todo lo demás las opciones correctas son all: revert, que deja el elemento tal y como lo mostraría el navegador sin tu CSS, o all: unset, que además permite que siga heredando del contexto, que es lo que normalmente se desea. Un último apunte que evita sustos: all no afecta a direction ni a unicode-bidi, precisamente para no romper el texto bidireccional, y tampoco toca las custom properties, así que las variables definidas en ese elemento sobreviven al reseteo.

La propiedad all

all es una abreviada que expande a todas las propiedades del lenguaje, con las dos excepciones mencionadas, y solo acepta las palabras clave globales. Su uso más frecuente y más útil es despojar un control nativo para reconstruirlo:

.boton-enlace {
  all: unset;

  /* Todo lo que sigue hay que devolverlo a mano */
  cursor: pointer;
  color: oklch(52% 0.18 258);
  text-decoration: underline;
}

.boton-enlace:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
  border-radius: 2px;
}

Aquí hay una advertencia de accesibilidad que no es opcional. all: unset elimina también el indicador de foco por defecto y el aspecto pulsable del control. Un botón sin indicador de foco visible es inutilizable con teclado, y el problema no se ve en desarrollo porque quien prueba usa el ratón. Si despojas un control, la regla de :focus-visible va en el mismo bloque y en el mismo momento, no en una tarea pendiente.

Ten en cuenta también que all: unset deja display en su valor inicial, inline, porque display no es heredable. Para un botón de texto eso suele estar bien; si necesitas otra cosa, decláralo después.

Cuándo usar cada una

inherit cuando quieres acoplar deliberadamente un hijo a su padre en una propiedad que no se acoplaría sola. El caso más habitual es la tipografía de los controles de formulario, que es la excepción notable a la herencia natural:

input, button, textarea, select { font: inherit; }

unset cuando quieres anular una declaración anterior tuya sin sustituirla por nada, típicamente dentro de una consulta de medios o de una variante.

.tarjeta { border: 1px solid; }

@media (prefers-contrast: less) {
  .tarjeta { border: unset; }
}

revert cuando quieres devolver el control al navegador. Es la palabra correcta para desactivar un reset demasiado agresivo en una zona concreta, como el contenido que genera un editor y que sí quiere sus viñetas y sus márgenes de vuelta:

.contenido-editor :is(ul, ol) { list-style: revert; padding-inline-start: revert; }

initial cuando de verdad quieres el valor de fábrica del lenguaje y sabes cuál es. Es la menos usada de las cuatro con diferencia, y hay un caso especial que merece conocerse: aplicada a una custom property, la devuelve a su valor inicial, que en el caso de las variables equivale a no tener valor, con lo que cualquier var() que la lea pasará a usar su valor de reserva.

Falta una quinta palabra, que retrocede por capas en vez de por orígenes y que solo tiene sentido si has entendido el nivel anterior: revert-layer, la siguiente lección.