Ir para o conteúdo
Allin

Embelezar ou minificar: para que serve cada um e o que faz ao peso

Publicado a 10/08/2026 · 15 min de leitura · Ferramentas para programadores

Daniel Okonkwo

Daniel OkonkwoProgramador front-end e redator de Tecnologia na Allin

Desempenho web · Formatos de ficheiro

Verificado a partir de 4 fontes

Ver perfil
Em resumo

Embelezar serve para ler; minificar serve para publicar. O argumento do peso é bem mais fraco do que a contagem de bytes em bruto sugere, porque tudo o que publica vai comprimido com gzip e o gzip já trata da repetição — e a indentação é o texto mais repetitivo que existe. Quatro folhas de estilo passaram por este minificador, com os dois tamanhos anotados. Um componente de cartão escrito à mão passou de 1 612 para 1 118 bytes, um corte de 30,6%; com gzip, de 659 para 555, uma poupança de 104 bytes. Separar as duas passagens é a lição verdadeira. Nos mesmos quatro ficheiros, retirar só os espaços poupou 48, 103, 104 e 147 bytes comprimidos — uma centena, seja qual for o tamanho, de 1,6 kB a 22 kB. Retirar só os comentários poupou 57, 1 358, 2 420 e 1 042. Num ficheiro muito comentado os comentários são 96% da poupança real; os espaços, um erro de arredondamento. Minifique pelos comentários e pelo código morto, não pelas quebras de linha, e nunca à custa da correção. Este minificador são cinco expressões regulares e parte cinco coisas: apaga o espaço que o CSS exige dos dois lados do + dentro de calc(), pelo que calc(100% + 16px) fica uma declaração inválida que o navegador deita fora; edita o interior das strings e transforma content: "a; b" em "a;b"; apaga uma string que apenas parece um comentário; engole uma sequência de comentário dentro de um data URI; e reescreve a[title="hello, world"]. O mesmo site tem o css-compressor, um analisador que não parte nenhuma delas e pesa 2 bytes a mais num ficheiro de 22 746 bytes.

Quatro folhas de estilo reais passadas pelo minificador, medidas em bruto e depois de gzip. Retirar todos os espaços poupou 48, 103, 104 e 147 bytes comprimidos; retirar os comentários, 57, 1 358, 2 420 e 1 042. E as cinco entradas que este minificador parte.

A medida que quase todos os artigos saltam: depois do gzip

Um minificador anuncia a contagem de bytes em bruto porque é a única que sabe calcular. Não é a que viaja. Qualquer folha de estilos servida por HTTP chega comprimida, e as duas operações sobrepõem-se: o gzip codifica uma sequência de bytes repetidos como uma referência curta para trás, e quatro espaços de indentação repetidos trezentas vezes são a coisa mais barata que alguma vez encontrará. Retirar essa indentação antes de comprimir elimina trabalho que o gzip fazia de graça.

Separaram-se então as duas passagens e mediu-se cada uma por si. Retirar só os comentários, depois só os espaços, depois ambos, em quatro ficheiros: um componente de cartão escrito à mão de 1 612 bytes e três folhas de estilo tiradas tal e qual do repositório deste site. Comprimida com gzip nível 9, a passagem dos espaços poupou 48, 103, 104 e 147 bytes. Não percentagens: bytes, e mais ou menos a mesma centena quer o ficheiro tivesse 1,6 kB quer 22 kB, porque numa folha de estilos há apenas um número limitado de indentações distintas por mais longa que seja. A passagem dos comentários, nos mesmos quatro ficheiros, poupou 57, 1 358, 2 420 e 1 042 bytes comprimidos.

Um ficheiro chega para demonstrar. O globals.css deste site pesa 7 148 bytes, boa parte deles prosa a explicar porque cada cor foi escolhida. Retirar os espaços levou-o de 3 140 bytes gzipados para 3 036: 104 bytes, 3,3%. Retirar os comentários deixou-o em 720, uma poupança de 2 420 bytes, 77%. Noventa e seis por cento do ganho real vinha dos comentários, e nada das quebras de linha. Está aí todo o argumento num só ficheiro: minifique para tirar o que o navegador não pode usar, não para tirar aquilo de que o compressor já trata.

Embelezar não custa quase nada depois de comprimido

A simetria vale no outro sentido, e é essa a parte útil. O exemplo que vem com o embelezador de HTML é uma página minificada de 485 bytes. Embelezada com indentação de dois espaços fica em 627 bytes: mais 142, um aumento de 29,3%, o número que deixa toda a gente nervosa. Com gzip, passa de 343 para 369 bytes: 26 bytes, 7,6%. Vinte e seis bytes não são nada. Se publica uma página legível por alguma razão — um exemplo de documentação, um modelo de e-mail que alguém tem de editar, uma página cujo código-fonte quer que se possa ver —, o custo comprimido de a deixar legível é menor do que um pedido de favicon.

O embelezador de HTML também merece que se perceba o que recusa fazer. Copia o conteúdo de pre e textarea byte a byte, porque os seus espaços são renderizados. Mantém um espaço único entre dois elementos em linha, porque retirá-lo colaria duas palavras no ecrã. E não toca num atributo entre aspas, pelo que title="a > b" sobrevive intacto em vez de ser cortado no sinal de maior. Os três comportamentos foram verificados diretamente e todos os três se confirmam.

Tem, isso sim, um ponto cego, e é precisamente o que o seu próprio comentário diz ter fechado. Dois botões separados por um espaço — <div><button>A</button> <button>B</button></div> — saem do minificador como <button>A</button><button>B</button>. Os botões são inline-block, portanto esse espaço é desenhado, e o intervalo entre os dois botões desaparece. A regra aplicada é que o espaço entre duas etiquetas de bloco é invisível, e a sua lista de elementos em linha tem a, b, span, code e mais uma vintena, mas não button, nem select, nem uma imagem dentro de uma ligação. Confira qualquer fila de botões depois de minificar.

Cinco entradas que este minificador de CSS trata mal

A página css-minifier são cinco expressões regulares: retirar comentários, reduzir as sequências de espaços a um só, eliminar os espaços à volta de um conjunto de sinais de pontuação, retirar um ponto e vírgula antes de uma chaveta de fecho e aparar. Chega para uma folha de estilos que escreveu há uma hora e não chega para mais nada, porque uma expressão regular não distingue a estrutura do conteúdo.

A primeira falha é a grave. O CSS Values and Units Level 3 diz, na sintaxe de calc(), que é obrigatório um espaço dos dois lados dos operadores + e -. A lista de pontuação aqui inclui o +, portanto calc(100% + 16px) sai como calc(100%+16px) e a declaração inteira fica inválida: o navegador deita-a fora e volta ao que estivesse antes. Como o - não está na lista, calc(100% - 16px) sobrevive intacto, o que é pior — metade das suas expressões calc funcionam e a outra metade desaparece em silêncio. Não é um caso inventado. O ficheiro apps/web/components/app/app-shell.module.css deste repositório contém calc(74px + env(safe-area-inset-bottom)), o espaçamento que mantém a barra de separadores móvel afastada do indicador de início. Passe-o por esta ferramenta e esse espaçamento desapareceu.

As outras quatro vêm da mesma raiz: as strings e os data URI são conteúdo, e as passagens tratam-nos como estrutura. content: "a; b" torna-se content:"a;b", porque o ponto e vírgula está na lista de pontuação. content: "{ }" torna-se content:"{}". a[title="hello, world"] torna-se a[title="hello,world"] e o seletor deixa de corresponder. Uma folha de estilos cuja string content contém os carateres que abrem e fecham um comentário CSS — content: "/* not a comment */" — sai como content:"", com a string esvaziada. E uma imagem de fundo escrita como data URI que por acaso contenha essa mesma sequência de dois carateres perde tudo o que está entre eles: url("data:image/svg+xml,...%3E/*x*/%3C...") chega com o meio apagado e a imagem morta.

Duas coisas que não parte, para equilibrar. As propriedades personalizadas sobrevivem: --shadow: 0 2px 8px rgba(0, 0, 0, 0.1) sai como --shadow:0 2px 8px rgba(0,0,0,0.1), que é o mesmo valor. As consultas de media também sobrevivem: @media screen and (min-width: 600px) fica @media screen and (min-width:600px), continua válida, e a sintaxe de intervalo moderna @media (400px <= width <= 700px) fica intacta, porque <= não está na lista de pontuação.

Dois minificadores no mesmo site, e o seguro pesa 2 bytes a mais

A página css-compressor usa outro motor. Em vez de reconhecer padrões, percorre o ficheiro carácter a carácter e marca cada um como estrutura ou literal: tudo o que está dentro de uma string, de um comentário ou de um par de parênteses é literal, e nenhuma transformação lhe pode tocar. É esse único sinalizador que preserva um data URI, uma expressão calc() e as casas decimais de um rgba().

Todo o interesse da abordagem ingénua devia ser ser mais pequena. Não é. Ambos correram sobre as mesmas três folhas de estilo reais. Em app-shell.module.css, 22 746 bytes à entrada, a versão com expressões regulares produziu 19 278 bytes e o analisador 19 280 — 2 bytes de diferença, e com gzip o analisador foi até 1 byte mais pequeno, 4 191 contra 4 192. Em admin.css a diferença foi de 1 byte em bruto e 2 bytes com gzip. Em globals.css, de 8 bytes em bruto. Oito bytes, num ficheiro onde a versão segura mantém o espaço em @media (min-width: 600px) e em rgba(0, 0, 0, 0.1). Não há nenhum argumento de tamanho a favor da versão com expressões regulares; é simplesmente a que às vezes destrói o ficheiro.

O SVG é a exceção, e tem o seu próprio erro

Tudo o que vem acima diz que o argumento do peso a favor da minificação é fraco. O SVG é onde é forte, porque o peso de um SVG exportado não são espaços. Um desenho pequeno guardado a partir de um editor vetorial transporta uma declaração XML, um comentário do editor, um título, uma descrição, um bloco de metadados RDF, uma vista nomeada com o último nível de zoom, dois espaços de nomes do editor, uma transformação de matriz identidade, uma espessura de traço e uma opacidade fixadas nos seus próprios valores por omissão, e coordenadas escritas com sete casas decimais. Passe um ficheiro desses — 1 071 bytes — pelo svg-optimizer e sai com 256 bytes, um corte de 76,1%. Com gzip: de 603 para 207, um corte de 65,7%. Essa poupança é real porque o material removido é texto único, e texto único é precisamente aquilo em que um compressor não pode ajudar.

Essa mesma execução trouxe à luz um defeito que convém conhecer antes de o usar. As cores passam por duas etapas na ordem errada: primeiro são encurtadas e depois entregues à passagem de arredondamento de números, que lê os algarismos hexadecimais como números. stroke="#000000" é encurtado para #000 e depois arredondado para #0. black passa a #0. red passa a #f0. E como o padrão numérico aceita notação científica, uma cor hexadecimal cujos algarismos rodeiam um e explode: #e5e7eb sai como #e50000000eb, #1e293b como #1e+293b, #0e7490 como #0. A mesma passagem reescreve url(#g-0010) como url(#g-10) enquanto deixa id="g-0010" intacto, pelo que o gradiente para onde aponta desaparece. Tudo isto foi reproduzido num navegador real, com as definições por omissão. Desligar a opção de arredondar números evita todos os casos, ao custo de alguns bytes de precisão.

Mais dois pormenores sobre a mesma ferramenta. Remove title e desc como metadados do editor — e esses são os dois elementos que um leitor de ecrã anuncia para um SVG, pelo que um ícone que era acessível deixa de o ser. E a sua verificação de marcação mal formada, essa, é das cuidadosas: um navegador assinala um erro de XML enxertando um elemento chamado parsererror, pelo que procurar só esse nome recusaria qualquer desenho válido que traga um seu. A ferramenta pergunta antes ao motor: uma vez por sessão analisa algo deliberadamente partido, lê o espaço de nomes do marcador que volta e a partir daí olha só para ali. Um desenho que contém um elemento parsererror otimiza-se normalmente; uma etiqueta por fechar continua a ser recusada.

As duas passagens medidas em separado em quatro ficheiros reais, bytes em bruto e gzip nível 9
FicheiroOriginal, bruto / gzipSó espaços, poupança gzipSó comentários, poupança gzip
Componente de cartão escrito à mão1 612 / 65948 bytes57 bytes
app-shell.module.css (denso, poucos comentários)22 746 / 5 661103 bytes1 358 bytes
globals.css (muito comentado)7 148 / 3 140104 bytes2 420 bytes
admin.css4 767 / 1 855147 bytes1 042 bytes
SVG exportado de um editor, otimizador completo1 071 / 603Metadados, não espaços396 bytes, 65,7%
Minificador CSSReduza CSS removendo comentários e espaços desnecessários.Experimentar a ferramenta

Perguntas frequentes

Ainda vale a pena minificar CSS se o servidor comprime tudo com gzip?
Sim, mas pelos comentários, não pelos espaços. Nos quatro ficheiros medidos aqui, retirar todos os espaços e quebras de linha poupou 48, 103, 104 e 147 bytes gzipados — uma centena de bytes cada um, quer o ficheiro tivesse 1,6 kB quer 22 kB, porque o gzip codifica a indentação repetida quase de graça. Retirar os comentários poupou 57, 1 358, 2 420 e 1 042 bytes gzipados nos mesmos ficheiros. Se a sua folha de estilos está documentada, os comentários são toda a poupança; se não está, minificá-la vai render cerca de um décimo de quilobyte e o esforço estaria melhor aplicado numa passagem de CSS não utilizado. Aquilo para que a minificação serve de facto, numa cadeia de compilação, é vir acompanhada das passagens que contam: retirar regras que nada na página usa, fundir declarações duplicadas e encurtar cores e unidades.
O meu layout partiu-se depois de minificar. Por onde começo a olhar?
Procure calc( no ficheiro minificado e leia todos. Se algum contiver um sinal de mais sem espaços à volta — calc(100%+16px) —, essa declaração é inválida e o navegador ignora-a. O CSS exige um espaço dos dois lados de + e - dentro de calc(), e um minificador com expressões regulares que aperta a pontuação apaga-o. A seguir procure content: e qualquer seletor de atributo com uma vírgula ou um ponto e vírgula, porque um minificador ingénuo edita o interior das strings. Depois olhe para os data URI: se algum continha os dois carateres que abrem um comentário CSS e mais à frente os dois que o fecham, tudo o que estava pelo meio foi removido. Por fim, compare o número de regras antes e depois; se baixou, perdeu-se algo estrutural, não apenas espaços.
Devo embelezar um ficheiro minificado que não escrevi, antes de o editar?
Sim, e é o uso honesto de um embelezador. Reformatar só muda os espaços, portanto não pode alterar o comportamento, e transforma um ficheiro de uma só linha em algo que um diff sabe descrever. Duas ressalvas. Primeira: um ficheiro embelezado não é automaticamente um ficheiro fonte — se o original foi gerado a partir de Sass, TypeScript ou uma biblioteca de componentes, editar a saída significa que a sua alteração desaparece na compilação seguinte. Segunda: embelezar e voltar a minificar nem sempre é a identidade; no motor HTML testado aqui, uma ida e volta acrescenta um espaço de cada lado do texto dentro de cada elemento não em linha, levando uma página de 133 bytes a 145 e ficando por aí. Inofensivo no navegador, mas não espere recuperar um ficheiro idêntico byte a byte.
Porque é que o otimizador de SVG poupa muito mais do que o minificador de CSS?
Porque remove material diferente. Um minificador de CSS retira espaços e comentários; um compressor já trata dos espaços, portanto só os comentários contam. Um otimizador de SVG retira metadados do editor, atributos por omissão, grupos vazios e casas decimais supérfluas — tudo texto único que um compressor não consegue dobrar. No ficheiro medido aqui, 1 071 bytes passaram a 256 em bruto, e 603 bytes gzipados passaram a 207, um corte de 65,7% que sobreviveu quase intacto à compressão. A lição generaliza-se: qualquer minificador que apenas reformate vai desiludi-lo depois do gzip, e qualquer um que apague conteúdo não. É também por isso que apagar conteúdo é a parte a verificar.
O Brotli é suficientemente diferente do gzip para mudar a resposta?
Não, torna-a ligeiramente mais forte. A folha de estilos do cartão comprimiu para 527 bytes com Brotli contra 659 com gzip, e minificada desceu para 451 contra 555. A poupança absoluta da minificação foi de 76 bytes com Brotli e de 104 com gzip: um compressor melhor deixa menos para o minificador retirar, exatamente como seria de esperar, já que ambos removem a mesma redundância. Portanto se o seu alojamento serve Brotli — a maioria das CDN serve — o argumento a favor de minificar espaços é ainda mais fraco, e o de retirar comentários não muda, porque um comentário é texto único com qualquer dos algoritmos.

Artigos que podem interessar-lhe

Todos os guias
GuiaO que um minificador pode remover e o que não pode tocarA minificação tem de preservar o significado, e o interessante são os espaços que carregam significado: o combinador descendente, os espaços dentro de calc(), o intervalo entre dois elementos em linha. Medido aqui em ficheiros reais, incluindo o que o brotli já lhe ia poupar.TutorialConstruir uma tabela Markdown de raiz, sem contar travessões à mãoA coisa mais pequena que ainda é uma tabela são duas linhas: uma linha de cabeçalho e uma linha delimitadora. Aqui está porque é que a segunda é obrigatória em GitHub Flavored Markdown, onde as tabelas de barras não existem de todo, e o que um gerador faz que escrever à mão não consegue.GuiaColar uma tabela num pull request: o que parte, e os dois carateres que partem tudoUma tabela Markdown proíbe exatamente dois carateres dentro de uma célula: a barra vertical e a quebra de linha. Aqui está o que cada um faz, como um conversor os trata, porque é que o escape tem de ser aplicado na ordem certa, e porque é que o alinhamento da fonte nunca conta.GuiaTranspor uma tabela cujas linhas deviam ter sido colunasO que acontece à linha de cabeçalho, às linhas de comprimento desigual, aos tipos — e a única coisa com que transpor é regularmente confundido e que não consegue fazer.ExplicaçãoDe XML para JSON: atributos, repetição e a armadilha do array de um só elementoDois documentos que só diferem no número de filhos produzem duas formas JSON diferentes, e nenhum conversor os distingue sem um esquema. Além do que este faz mesmo com os atributos, o conteúdo misto e os espaços — e a única coisa que continua a não conseguir registar.ExplicaçãoDe CSV para JSON: os cinco casos que partem qualquer conversorDelimitadores entre aspas, quebras de linha embutidas, tipos ambíguos, cabeçalhos repetidos e codificação. Cada caso passou pelo conversor e a saída exata está aqui — incluindo os dois que ele não salva.

Ferramentas relacionadas

Estes números vêm de executar estas ferramentas sobre ficheiros reais e comprimir o resultado, não de uma promessa de fabricante. O peso depende inteiramente do ficheiro: uma folha de estilos escrita com comentários longos não comprime como uma sem eles, e os seus números não serão os nossos. Os minificadores também não são equivalentes — dois deste site divergem perante a mesma entrada — portanto trate qualquer saída minificada como código novo, a rever antes de publicar. Guarde o original legível no controlo de versões, minifique na compilação e confirme a página num navegador antes de publicar.

Fontes

Detetaste um erro neste artigo?