Ir al contenido
Allin

Embellecer o minificar: para qué sirve cada uno y qué le hace al peso

Publicado el 10/8/2026 · 15 min de lectura · Herramientas para desarrolladores

Daniel Okonkwo

Daniel OkonkwoDesarrollador front-end y redactor de Tecnología en Allin

Rendimiento web · Formatos de archivo

Verificado con 4 fuentes

Ver perfil
En resumen

Embellecer sirve para leer; minificar sirve para publicar. El argumento del peso es mucho más débil de lo que sugiere el recuento de bytes en crudo, porque todo lo que publicas va comprimido con gzip y gzip ya se ocupa de la repetición: y la sangría es el texto más repetitivo que existe. Cuatro hojas de estilo pasaron por este minificador, anotando ambos tamaños. Un componente de tarjeta escrito a mano pasó de 1 612 a 1 118 bytes, un recorte del 30,6%; con gzip, de 659 a 555, un ahorro de 104 bytes. Separar las dos pasadas es la lección de verdad. Sobre esos mismos cuatro archivos, quitar solo los espacios ahorró 48, 103, 104 y 147 bytes comprimidos: un centenar aproximado, sea cual sea el tamaño, de 1,6 kB a 22 kB. Quitar solo los comentarios ahorró 57, 1 358, 2 420 y 1 042. En un archivo muy comentado los comentarios son el 96% del ahorro real; los espacios, un error de redondeo. Minifica por los comentarios y el código muerto, no por los saltos de línea, y nunca a costa de la corrección. Este minificador son cinco expresiones regulares y rompe cinco cosas: borra el espacio que el CSS exige a ambos lados del + dentro de calc(), así que calc(100% + 16px) queda como una declaración inválida que el navegador descarta; edita el interior de las cadenas y convierte content: "a; b" en "a;b"; borra una cadena que solo parece un comentario; se come una secuencia de comentario dentro de un data URI; y reescribe a[title="hello, world"]. El mismo sitio ofrece css-compressor, un analizador que no rompe ninguna y pesa 2 bytes más en un archivo de 22 746 bytes.

Cuatro hojas de estilo reales pasadas por el minificador, medidas en crudo y tras gzip. Quitar todos los espacios ahorró 48, 103, 104 y 147 bytes comprimidos; quitar los comentarios, 57, 1 358, 2 420 y 1 042. Y las cinco entradas que este minificador rompe.

La medida que casi todos los artículos se saltan: después de gzip

Un minificador informa del recuento de bytes en crudo porque es el único que sabe calcular. No es el que viaja. Toda hoja de estilos servida por HTTP llega comprimida, y las dos operaciones se solapan: gzip codifica una secuencia de bytes repetidos como una referencia corta hacia atrás, y cuatro espacios de sangría repetidos trescientas veces son lo más barato que verá jamás. Quitar esa sangría antes de comprimir elimina un trabajo que gzip hacía gratis.

Así que se separaron las dos pasadas y se midió cada una por su cuenta. Quitar solo los comentarios, luego solo los espacios, luego ambos, en cuatro archivos: un componente de tarjeta escrito a mano de 1 612 bytes y tres hojas de estilo tomadas tal cual del repositorio de este sitio. Comprimida con gzip nivel 9, la pasada de espacios ahorró 48, 103, 104 y 147 bytes. No porcentajes: bytes, y aproximadamente el mismo centenar tanto si el archivo pesaba 1,6 kB como 22 kB, porque en una hoja de estilos solo hay un número limitado de sangrías distintas por larga que sea. La pasada de comentarios, en los mismos cuatro archivos, ahorró 57, 1 358, 2 420 y 1 042 bytes comprimidos.

Un solo archivo lo demuestra. El globals.css de este sitio pesa 7 148 bytes, buena parte de ellos prosa que explica por qué se eligió cada color. Quitar los espacios lo llevó de 3 140 bytes gzipados a 3 036: 104 bytes, un 3,3%. Quitar los comentarios lo dejó en 720, un ahorro de 2 420 bytes, el 77%. El noventa y seis por ciento de la ganancia real venía de los comentarios, y nada de los saltos de línea. Ahí está todo el argumento en un archivo: minifica para quitar lo que el navegador no puede usar, no para quitar lo que el compresor ya gestiona.

Embellecer no cuesta casi nada una vez comprimido

La simetría vale en el otro sentido, y esa es la parte útil. El ejemplo que trae el embellecedor de HTML es una página minificada de 485 bytes. Embellecida con sangría de dos espacios queda en 627 bytes: 142 más, un aumento del 29,3%, la cifra que pone nervioso a cualquiera. Con gzip, pasa de 343 a 369 bytes: 26 bytes, un 7,6%. Veintiséis bytes no son nada. Si publicas una página legible por algún motivo —un ejemplo de documentación, una plantilla de correo que alguien tiene que editar, una página cuyo código fuente quieres que se pueda ver—, el coste comprimido de dejarla legible es menor que una petición de favicon.

El embellecedor de HTML también merece entenderse por lo que se niega a hacer. Copia el contenido de pre y textarea byte a byte, porque su espaciado se renderiza. Conserva un espacio único entre dos elementos en línea, porque quitarlo pegaría dos palabras en pantalla. Y no toca un atributo entrecomillado, así que title="a > b" sobrevive intacto en vez de cortarse en el signo de mayor. Los tres comportamientos se comprobaron directamente y los tres se cumplen.

Sí tiene un punto ciego, y es justo el que su propio comentario dice haber cerrado. Dos botones separados por un espacio —<div><button>A</button> <button>B</button></div>— salen del minificador como <button>A</button><button>B</button>. Los botones son inline-block, así que ese espacio se dibuja, y el hueco entre los dos botones desaparece. La regla que aplica es que el espacio entre dos etiquetas de bloque es invisible, y su lista de elementos en línea contiene a, b, span, code y una veintena más, pero no button, ni select, ni una imagen dentro de un enlace. Revisa cualquier fila de botones después de minificar.

Cinco entradas que este minificador de CSS trata mal

La página css-minifier son cinco expresiones regulares: quitar comentarios, reducir las secuencias de espacios a uno solo, eliminar los espacios alrededor de un conjunto de signos de puntuación, quitar un punto y coma antes de una llave de cierre y recortar. Basta para una hoja de estilos que escribiste hace una hora y no basta para nada más, porque una expresión regular no distingue la estructura del contenido.

El primer fallo es el grave. CSS Values and Units Level 3 dice, en la sintaxis de calc(), que hace falta un espacio a ambos lados de los operadores + y -. La lista de puntuación aquí incluye el +, así que calc(100% + 16px) sale como calc(100%+16px) y la declaración entera queda inválida: el navegador la descarta y vuelve a lo que hubiera antes. Como el - no está en la lista, calc(100% - 16px) sobrevive intacto, lo que es peor: la mitad de tus expresiones calc funcionan y la otra mitad desaparece en silencio. No es un caso inventado. El archivo apps/web/components/app/app-shell.module.css de este repositorio contiene calc(74px + env(safe-area-inset-bottom)), el relleno que mantiene la barra de pestañas móvil separada del indicador de inicio. Pásalo por esta herramienta y ese relleno ya no está.

Las otras cuatro vienen de la misma raíz: las cadenas y los data URI son contenido, y las pasadas los tratan como estructura. content: "a; b" se convierte en content:"a;b", porque el punto y coma está en la lista de puntuación. content: "{ }" se convierte en content:"{}". a[title="hello, world"] se convierte en a[title="hello,world"] y el selector deja de coincidir. Una hoja de estilos cuya cadena content contiene los caracteres que abren y cierran un comentario CSS —content: "/* not a comment */"— sale como content:"", con la cadena vaciada. Y una imagen de fondo escrita como data URI que por casualidad contiene esa misma secuencia de dos caracteres pierde todo lo que hay entre ellos: url("data:image/svg+xml,...%3E/*x*/%3C...") llega con el centro borrado y la imagen muerta.

Dos cosas que no rompe, por equilibrio. Las propiedades personalizadas sobreviven: --shadow: 0 2px 8px rgba(0, 0, 0, 0.1) sale como --shadow:0 2px 8px rgba(0,0,0,0.1), que es el mismo valor. Las consultas de medios también sobreviven: @media screen and (min-width: 600px) queda en @media screen and (min-width:600px), sigue siendo válida, y la sintaxis de rango moderna @media (400px <= width <= 700px) queda intacta, porque <= no está en la lista de puntuación.

Dos minificadores en el mismo sitio, y el seguro pesa 2 bytes más

La página css-compressor usa otro motor. En vez de reconocer patrones, recorre el archivo carácter a carácter y marca cada uno como estructura o literal: todo lo que está dentro de una cadena, un comentario o un par de paréntesis es literal, y ninguna transformación puede tocarlo. Ese único indicador es lo que preserva un data URI, una expresión calc() y los decimales de un rgba().

Todo el sentido del enfoque ingenuo se suponía que era su menor tamaño. No lo es. Ambos se ejecutaron sobre las mismas tres hojas de estilo reales. En app-shell.module.css, 22 746 bytes de entrada, la versión con expresiones regulares produjo 19 278 bytes y el analizador 19 280: 2 bytes de diferencia, y con gzip el analizador fue incluso 1 byte más pequeño, 4 191 frente a 4 192. En admin.css la diferencia fue de 1 byte en crudo y 2 bytes con gzip. En globals.css, de 8 bytes en crudo. Ocho bytes, en un archivo donde la versión segura conserva el espacio de @media (min-width: 600px) y de rgba(0, 0, 0, 0.1). No hay ningún argumento de tamaño a favor de la versión con expresiones regulares; es sencillamente la que a veces destruye el archivo.

El SVG es la excepción, y tiene su propio fallo

Todo lo anterior dice que el argumento del peso a favor de minificar es débil. El SVG es donde es fuerte, porque el peso de un SVG exportado no son espacios. Un dibujo pequeño guardado desde un editor vectorial arrastra una declaración XML, un comentario del editor, un título, una descripción, un bloque de metadatos RDF, una vista con nombre y el último nivel de zoom, dos espacios de nombres del editor, una transformación de matriz identidad, un grosor de trazo y una opacidad fijados en sus propios valores por defecto, y coordenadas escritas con siete decimales. Pasa uno de esos archivos —1 071 bytes— por svg-optimizer y sale con 256 bytes, un recorte del 76,1%. Con gzip: de 603 a 207, un recorte del 65,7%. Ese ahorro es real porque lo eliminado es texto único, y el texto único es justo aquello con lo que un compresor no puede ayudar.

Esa misma ejecución sacó a la luz un defecto que conviene conocer antes de usarlo. Los colores pasan por dos etapas en el orden equivocado: primero se acortan y después se entregan a la pasada de redondeo de números, que lee los dígitos hexadecimales como números. stroke="#000000" se acorta a #000 y luego se redondea a #0. black pasa a #0. red pasa a #f0. Y como el patrón numérico acepta notación científica, un color hexadecimal cuyos dígitos rodean una e estalla: #e5e7eb sale como #e50000000eb, #1e293b como #1e+293b, #0e7490 como #0. La misma pasada reescribe url(#g-0010) como url(#g-10) mientras deja id="g-0010" intacto, así que el degradado al que apunta desaparece. Todo esto se reprodujo en un navegador real, con los ajustes por defecto. Desactivar la opción de redondear números evita todos los casos, a costa de unos pocos bytes de precisión.

Dos detalles más sobre la misma herramienta. Quita title y desc como metadatos del editor, y esos son los dos elementos que un lector de pantalla anuncia para un SVG, así que un icono que era accesible deja de serlo. Y su comprobación del marcado mal formado, en cambio, es de las cuidadosas: un navegador señala un error de XML injertando un elemento llamado parsererror, así que buscar solo ese nombre rechazaría cualquier dibujo válido que lleve uno propio. La herramienta pregunta al motor: una vez por sesión analiza algo deliberadamente roto, lee el espacio de nombres del marcador que vuelve y a partir de ahí solo mira ahí. Un dibujo que contiene un elemento parsererror se optimiza con normalidad; una etiqueta sin cerrar se sigue rechazando.

Las dos pasadas medidas por separado en cuatro archivos reales, bytes en crudo y gzip nivel 9
ArchivoOriginal, crudo / gzipSolo espacios, ahorro gzipSolo comentarios, ahorro gzip
Componente de tarjeta escrito a mano1 612 / 65948 bytes57 bytes
app-shell.module.css (denso, pocos comentarios)22 746 / 5 661103 bytes1 358 bytes
globals.css (muy comentado)7 148 / 3 140104 bytes2 420 bytes
admin.css4 767 / 1 855147 bytes1 042 bytes
SVG exportado de un editor, optimizador completo1 071 / 603Metadatos, no espacios396 bytes, 65,7%
Minificador CSSReduce CSS eliminando comentarios y espacios innecesarios.Probar la herramienta

Preguntas frecuentes

¿Sigue mereciendo la pena minificar CSS si el servidor lo comprime todo con gzip?
Sí, pero por los comentarios, no por los espacios. En los cuatro archivos medidos aquí, quitar todos los espacios y saltos de línea ahorró 48, 103, 104 y 147 bytes gzipados: un centenar de bytes cada uno, tanto si el archivo pesaba 1,6 kB como 22 kB, porque gzip codifica la sangría repetida casi gratis. Quitar los comentarios ahorró 57, 1 358, 2 420 y 1 042 bytes gzipados en los mismos archivos. Si tu hoja de estilos está documentada, los comentarios son todo el ahorro; si no lo está, minificarla te dará alrededor de una décima de kilobyte y el esfuerzo estaría mejor puesto en una pasada de CSS sin usar. Para lo que sirve de verdad minificar, en una cadena de compilación, es que viene acompañada de las pasadas que sí importan: quitar reglas que nada de la página usa, fusionar declaraciones duplicadas y acortar colores y unidades.
Mi maquetación se rompió tras minificar. ¿Por dónde empiezo a mirar?
Busca calc( en el archivo minificado y léelos todos. Si alguno contiene un signo más sin espacios alrededor —calc(100%+16px)—, esa declaración es inválida y el navegador la ignora. El CSS exige un espacio a ambos lados de + y - dentro de calc(), y un minificador con expresiones regulares que aprieta la puntuación lo borra. Después busca content: y cualquier selector de atributo con una coma o un punto y coma, porque un minificador ingenuo edita el interior de las cadenas. Luego mira los data URI: si alguno contenía los dos caracteres que abren un comentario CSS y más adelante los dos que lo cierran, todo lo que había entre medias se ha eliminado. Por último, compara el número de reglas antes y después; si bajó, se perdió algo estructural, no solo espacios.
¿Debo embellecer un archivo minificado que no escribí antes de editarlo?
Sí, y es el uso honesto de un embellecedor. Reformatear solo cambia los espacios, así que no puede alterar el comportamiento, y convierte un archivo de una sola línea en algo que un diff sabe describir. Dos advertencias. Primera: un archivo embellecido no es automáticamente un archivo fuente; si el original se generó desde Sass, TypeScript o una biblioteca de componentes, editar la salida significa que tu cambio desaparece en la siguiente compilación. Segunda: embellecer y volver a minificar no siempre es la identidad; en el motor HTML probado aquí, una ida y vuelta añade un espacio a cada lado del texto dentro de todo elemento no en línea, llevando una página de 133 bytes a 145 y quedándose ahí. Inofensivo en el navegador, pero no esperes recuperar un archivo idéntico byte a byte.
¿Por qué el optimizador de SVG ahorra mucho más que el minificador de CSS?
Porque elimina material distinto. Un minificador de CSS quita espacios y comentarios; un compresor ya se encarga de los espacios, así que solo cuentan los comentarios. Un optimizador de SVG quita metadatos del editor, atributos por defecto, grupos vacíos y decimales sobrantes: todo ello texto único que un compresor no puede plegar. En el archivo medido aquí, 1 071 bytes pasaron a 256 en crudo, y 603 bytes gzipados pasaron a 207, un recorte del 65,7% que sobrevivió casi intacto a la compresión. La lección se generaliza: cualquier minificador que solo reformatee te decepcionará después de gzip, y cualquiera que borre contenido no. Por eso mismo el borrado de contenido es la parte que hay que revisar.
¿Brotli se diferencia lo bastante de gzip como para cambiar la respuesta?
No, la refuerza ligeramente. La hoja de estilos de la tarjeta se comprimió a 527 bytes con Brotli frente a 659 con gzip, y minificada bajó a 451 frente a 555. El ahorro absoluto de minificar fue de 76 bytes con Brotli y de 104 con gzip: un compresor mejor deja menos por quitar al minificador, exactamente como cabría esperar, ya que ambos eliminan la misma redundancia. Así que si tu alojamiento sirve Brotli —la mayoría de las CDN lo hacen—, el argumento a favor de minificar espacios es aún más débil, y el de quitar comentarios no cambia, porque un comentario es texto único con cualquiera de los dos algoritmos.

Artículos que podrían interesarte

Todas las guías
GuíaQué puede quitar un minificador y qué no debe tocarLa minificación tiene que preservar el significado, y lo interesante son los espacios que llevan significado: el combinador descendiente, los espacios dentro de calc(), el hueco entre dos elementos en línea. Medido aquí sobre archivos reales, incluido lo que brotli te iba a ahorrar de todas formas.TutorialConstruir una tabla Markdown desde cero, sin contar guiones a manoLo más pequeño que sigue siendo una tabla son dos líneas: una fila de cabecera y una fila delimitadora. Aquí está por qué la segunda es obligatoria en GitHub Flavored Markdown, dónde las tablas de barras no existen en absoluto, y qué hace un generador que teclear a mano no puede.GuíaPegar una tabla en un pull request: qué se rompe y los dos caracteres que lo rompenUna tabla Markdown prohíbe exactamente dos caracteres dentro de una celda: la barra vertical y el salto de línea. Aquí está qué hace cada uno, cómo los trata un conversor, por qué el escape debe aplicarse en el orden correcto, y por qué el relleno nunca importa.GuíaTransponer una tabla cuyas filas deberían haber sido columnasQué le pasa a la fila de cabecera, a las filas de longitud desigual, a los tipos — y la única cosa con la que se confunde habitualmente transponer y que no puede hacer.ExplicaciónDe XML a JSON: atributos, repetición y la trampa del array de un solo elementoDos documentos que solo se diferencian en cuántos hijos existen producen dos formas JSON distintas, y ningún conversor puede distinguirlos sin un esquema. Además, lo que este hace de verdad con los atributos, el contenido mixto y los espacios, y lo único que sigue sin poder registrar.ExplicaciónDe CSV a JSON: los cinco casos que rompen cualquier conversorDelimitadores entrecomillados, saltos de línea incrustados, tipos ambiguos, cabeceras duplicadas y codificación. Cada caso se pasó por el conversor y aquí está la salida exacta, incluidos los dos que no salva.

Herramientas relacionadas

Estas cifras salen de ejecutar estas herramientas sobre archivos reales y comprimir el resultado, no de la promesa de un fabricante. El peso depende por completo del archivo: una hoja de estilos escrita con comentarios largos no se comprime igual que una sin ellos, y tus números no serán los nuestros. Los minificadores tampoco son equivalentes —dos de este sitio discrepan ante la misma entrada—, así que trata cualquier salida minificada como código nuevo que hay que revisar antes de publicarlo. Guarda el original legible en el control de versiones, minifica en la compilación y comprueba la página en un navegador antes de publicar.

Fuentes

¿Has detectado un error en este artículo?