Convertir RGB a Hex: padding, mayúsculas y la trampa del alpha
RGB a hex es la inversa de una conversión que ya era fácil. Los bugs vienen de olvidar el cero a la izquierda en un valor de un dígito y de inventar una convención de mayúsculas que pelea con tu linter.
Tres números, seis caracteres
Un trío RGB tipo rgb(15, 136, 250) se convierte a hex pasando cada canal a base 16 y concatenando. 15 es f, 136 es 88, 250 es fa. Pegado da f88fa que está mal, porque 15 tenía que ser 0f y no f.
El padding es la regla. Cada canal, por pequeño que sea, debe producir exactamente dos caracteres. 0 se vuelve 00, 5 se vuelve 05, 15 se vuelve 0f. El one liner estándar en cualquier lenguaje es el equivalente de (n).toString(16).padStart(2, "0"). Te saltas el pad y uno de cada dieciséis colores válidos produce un hex de cinco caracteres que ningún parser acepta.
El otro detalle es la almohadilla inicial. CSS la requiere, la mayoría de parsers acepta el hex con o sin ella. Producirla por defecto es más amable que no, los que quieran quitarla siempre pueden.
La minúscula gana por convención
Tanto #FF8800 como #ff8800 son CSS válido y producen el mismo color. La W3C no elige bando. La convención en la práctica es minúscula, porque la mayoría de formateadores (Prettier el primero) normaliza a minúscula, porque las letras hex pegadas a números se leen mejor en minúscula, y porque las herramientas de diseño (Figma, Sketch, Adobe moderno) exportan minúscula por defecto.
Si tu equipo tiene otra regla, elige una y mete linter. Mezclar mayúsculas y minúsculas en la misma hoja de estilos hincha cualquier diff cuando alguien toca un color, porque el formateador lo reescribe a tu convención y el diff explota. Fija la convención una vez, normaliza en la entrada.
Alpha y la sintaxis color() moderna
rgba(15, 136, 250, 0.5) se convierte en #0f88fa80. El cuarto par es el byte alpha, calculado como Math.round(alpha * 255).toString(16).padStart(2, "0"). 0.5 se vuelve 128 que es 80. 0.8 se vuelve 204 que es cc. El mismo redondeo de float a byte muerde aquí igual que en la conversión inversa.
CSS Color Module Level 4 introduce color(srgb 0.06 0.53 0.98 / 0.5) y la nueva sintaxis con espacios rgb(15 136 250 / 0.5). Son equivalentes, la forma moderna compone mejor con sintaxis de color relativo (color-mix, theming basado en oklch). El hex de ocho dígitos sigue siendo la representación más compacta y suele ser la salida correcta para un conversor. Las formas nuevas son para cuando quieres hacer matemáticas de color en CSS en lugar de congelar el resultado.
Bordes en código: clamp, round, tipo
Los dos bugs de producción en cualquier conversor RGB a hex son entradas sin acotar y floats. Los diseñadores pegan rgb(259, 136, 0) desde una herramienta que se equivocó al calcular, y un snippet ingenuo devuelve #10388800 (porque 259 se vuelve el string hex 103 de tres chars). Un snippet correcto acota a 0..255 primero.
Los floats llegan cuando una librería de animación pasa valores interpolados tipo 136.7. Pasa Math.round antes del toString o sale #88.b333... que no existe. El snippet de abajo acota, redondea, rellena y pone en minúscula. Pégalo tal cual.
Ejemplo completo
javascript// RGB a hex. Acota a 0..255, redondea floats, alpha opcional 0..1.
function rgbToHex(r, g, b, a = 1) {
const clamp = (n) => Math.max(0, Math.min(255, Math.round(Number(n) || 0)));
const pad = (n) => clamp(n).toString(16).padStart(2, "0");
const hex = "#" + pad(r) + pad(g) + pad(b);
if (a >= 1) return hex;
const alpha = Math.max(0, Math.min(1, Number(a) || 0));
const aHex = Math.round(alpha * 255).toString(16).padStart(2, "0");
return hex + aHex;
}
// rgbToHex(15, 136, 250) -> "#0f88fa"
// rgbToHex(15, 136, 250, 0.5) -> "#0f88fa80"
// rgbToHex(259, -3, 136.7) -> "#ff0089" (acotado, redondeado)
// rgbToHex(0, 0, 0, 0) -> "#00000000" ¿Solo necesitas el resultado?
Pega el valor rgb() en el convertidor de color en aldeacode.com y el hex, la forma de ocho dígitos en minúscula con alpha y el rgb() moderno con barra aparecen a la vez. La matemática viene acotada y redondeada, la caja normalizada, y la conversión corre entera en tu navegador.
Abrir Convertidor de Color (Hex / RGB / HSL) →Preguntas frecuentes
¿La salida hex en minúscula o mayúscula?
Minúscula por convención. Prettier, los defaults de stylelint y la mayoría de exports de herramientas de diseño normalizan a minúscula. Elige una, mete linter, ahorra a tu equipo una clase entera de diffs sin sentido.
¿Qué pasa si paso 256 o un número negativo?
Un conversor correcto acota al rango válido 0..255. El snippet aquí usa Math.max y Math.min antes del toString. Una implementación ingenua produce un hex de tres caracteres que rompe todos los parsers que vengan después.
¿Pongo el alpha como cuarto par o como rgba aparte?
El hex de ocho dígitos hoy tiene soporte amplio (Chrome desde 2017, Safari desde 13). Es la forma más compacta y la más cómoda para copiar y pegar. Usa rgba() cuando el alpha sea dinámico y quieras que el CSS se lea claro.