El panel de computados y de dónde sale cada valor
La diferencia entre valor especificado, computado y usado, cómo leer el origen de cada propiedad en el panel, y por qué computados es el primer sitio donde mirar y no el último.
El panel de estilos responde a por qué; el de computados responde a qué. Y en depuración el orden correcto es el inverso al que usa casi todo el mundo: primero verifica cuál es el valor final, y solo cuando ese valor te sorprenda te preguntes de dónde viene. Empezar por la explicación de algo que no has confirmado es la fuente de la mitad de las investigaciones que van a ninguna parte, y el panel de computados es la confirmación que cuesta tres segundos.
- Distinguir valor especificado, computado, usado y resuelto, y saber cuál devuelve cada herramienta.
- Localizar en el panel de computados qué regla concreta produjo cada valor final.
- Diagnosticar valores que vienen de la herencia y encontrar el ancestro responsable.
- Resolver una cadena de custom properties hasta su valor efectivo.
Cuatro valores, no uno
La especificación distingue varias etapas por las que pasa el valor de una propiedad, y confundirlas produce discusiones estériles.
El valor especificado es lo que pone en la declaración ganadora de la cascada: width: 50%, font-size: 1.5em, color: currentColor.
El valor computado es el resultado de aplicar la herencia y de resolver todo lo que se puede resolver sin conocer el layout: las unidades relativas al tamaño de fuente se convierten a píxeles absolutos, las palabras clave heredadas se sustituyen por el valor del padre, y las custom properties se sustituyen por su contenido. Un 1.5em con un padre de 16 píxeles computa a 24px.
El valor usado es el que resulta después del layout, cuando ya se conocen las dimensiones. Un width: 50% computa a 50% y se usa como 320px.
El valor resuelto es el que devuelve getComputedStyle, y aquí está la sutileza que hay que memorizar: para unas propiedades devuelve el computado y para otras devuelve el usado. Para las de dimensión y posición devuelve el usado, es decir, píxeles reales. Para el resto devuelve el computado.
El panel de computados de las DevTools muestra el valor resuelto, igual que getComputedStyle. Por eso ahí ves píxeles y no porcentajes.
// La misma propiedad, tres representaciones distintas
const el = $0;
console.log(el.style.width); // especificado en linea, o cadena vacia
console.log(getComputedStyle(el).width); // resuelto, en pixeles
console.log(el.getBoundingClientRect().width); // usado real, incluye transformaciones
Ese tercer valor merece atención: getBoundingClientRect devuelve la caja después de aplicar transformaciones, mientras que getComputedStyle devuelve la dimensión de layout. Un elemento con transform: scale(2) tiene 100 píxeles según uno y 200 según el otro, y los dos tienen razón. Cuando dos mediciones no cuadran, esta es la explicación en un porcentaje alto de los casos.
Leer el panel
El panel lista todas las propiedades del elemento en orden alfabético, con su valor resuelto. Tres controles cambian lo que muestra.
Mostrar todo, que incluye las propiedades cuyo valor es el inicial. Por defecto están ocultas y el panel muestra solo las que alguien ha tocado. Activarlo produce una lista de varios cientos de entradas que es incómoda de leer y a veces necesaria.
Agrupar por categoría, que sustituye el orden alfabético por bloques temáticos: layout, texto, apariencia. Cuál prefieras depende de si buscas una propiedad concreta o exploras.
El filtro, que es lo que se usa el noventa por ciento de las veces. Escribir pad deja los cuatro rellenos, color deja todo lo cromático.
Cada propiedad con un valor que no sea el inicial tiene un triángulo de expansión. Al abrirlo aparecen todas las declaraciones que intentaron definirla, con su selector y su origen, la ganadora arriba y las perdedoras tachadas. Y cada una es un enlace que salta a esa regla en el panel de estilos.
Ese despliegue es la respuesta directa y completa a “de dónde sale este valor”, y es la razón por la que el panel de computados no es un visor pasivo sino la entrada principal al diagnóstico de cascada.
El despliegue de origen funciona también para propiedades heredadas: en vez de una regla que casa con este elemento, muestra la regla que casaba con el ancestro, con un enlace que lleva hasta él. Es lo que convierte “este texto tiene un color que no he puesto en ningún sitio” en “lo puso esta regla en este ancestro” sin subir el árbol a mano.
Diagnosticar herencia
La herencia produce una clase de bug particularmente escurridiza porque el valor problemático no está declarado en ningún sitio cercano al elemento afectado. Alguien puso un line-height en el body hace tres años, y hoy un componente concreto se ve mal por eso.
El procedimiento con el panel es directo. Localiza la propiedad en computados, expándela, y el origen te lleva al ancestro. Si quieres verlo en el otro sentido, el panel de estilos agrupa las reglas heredadas bajo encabezados con el nombre del elemento del que vienen, y cada encabezado es un enlace al nodo.
Merece la pena recordar qué se hereda y qué no, porque marca dónde buscar. Se heredan las propiedades de texto y tipografía —color, font, line-height, letter-spacing, text-align, visibility, cursor, white-space— y no se hereda nada de layout, caja, fondo ni borde. Si el problema es de una propiedad no heredable, el culpable está en una regla que casa con el elemento y no hay que subir el árbol.
Y hay una tercera vía, la fuerza bruta selectiva, que es rápida cuando el árbol es profundo.
// Recorre los ancestros y muestra quien declara un valor distinto de una propiedad
function origenHeredado(el, prop) {
const filas = [];
for (let n = el; n; n = n.parentElement) {
filas.push({ nodo: n.tagName + (n.id ? '#' + n.id : ''), valor: getComputedStyle(n).getPropertyValue(prop) });
}
console.table(filas);
}
origenHeredado($0, 'line-height');
El punto donde el valor cambia entre una fila y la siguiente es el ancestro que lo declaró.
Custom properties
Las variables CSS tienen una peculiaridad que las hace distintas de todo lo demás: su valor computado es el texto de la sustitución, no un valor tipado. Eso significa que una custom property puede contener basura y no dar ningún error hasta que se usa.
El panel de computados las lista con su valor resuelto en ese elemento, que puede ser distinto del que tienen en otro elemento del mismo documento porque las variables se heredan. Al pasar el cursor sobre un var() en el panel de estilos, aparece el valor sustituido, y con la tecla modificadora se puede saltar a la declaración que la define.
El caso que confunde es la cadena de sustituciones: una variable que se define en términos de otra que a su vez usa una tercera. El panel resuelve la cadena entera y muestra el valor final, que es lo que quieres, pero para encontrar el eslabón roto hay que recorrer los enlaces.
// Todas las custom properties visibles en un elemento, con su valor resuelto
const cs = getComputedStyle($0);
console.table(
Array.from(cs).filter(p => p.startsWith('--'))
.map(p => ({ variable: p, valor: cs.getPropertyValue(p).trim() }))
);
Vale la pena volver a la distinción del primer nivel entre hechos reportados e interpretaciones del frontend, porque aquí tiene su aplicación más rentable. El valor computado viene del motor de estilos: es un hecho. El panel de estilos, con su orden, sus tachados y sus avisos, es la reconstrucción que las DevTools hacen del razonamiento que llevó a ese hecho, y esa reconstrucción es buena pero es reconstrucción. Cuando ambas cosas parecen contradecirse —el panel de estilos muestra una regla ganando con un valor y computados muestra otro— el que tiene razón es computados, siempre, y la discrepancia significa que hay algo que la vista de reglas no está mostrando. Las causas habituales: una animación o transición en curso, que sobrescribe el valor durante su ejecución sin aparecer como regla; una hoja de estilos construible adoptada por un shadow DOM; una propiedad registrada con @property cuyo tipo fuerza una interpolación distinta de lo que esperabas; o simplemente que estás mirando un momento distinto, porque el panel de estilos no se refresca con la misma frecuencia que el de computados. La consecuencia práctica es un hábito muy simple que resuelve muchísimo: cuando dudes, cierra el panel de estilos y evalúa getComputedStyle($0) en la consola. Es la fuente más directa que existe, no pasa por ninguna capa de presentación, y devuelve exactamente lo que el motor cree. Si ese número te sorprende, tienes un problema de CSS de verdad. Si es el que esperabas, tu problema está en otro sitio y llevas veinte minutos mirando el panel equivocado.