Por que a sua loja online parece uma colcha de retalhos
Este guia é para quem paga por um site, um aplicativo e um painel e vê cada um com uma cara. Você vai entender por que isso acontece, o que pedir a quem constrói e como cobrar o resultado. Serve para conversar de igual para igual com o time de tecnologia.
Alexandre Caramaschi
Founder da Brasil GEO, ex-CMO da Semantix (Nasdaq), cofundador da AI Brasil
Cenário: uma loja de autopeças tem site, aplicativo e painel de gestão. Cada um usa um azul diferente, e o botão de comprar muda de forma em cada tela. O cliente sente que trocou de empresa no meio do caminho.
A causa raramente é falta de capricho. Cada pedaço foi construído em época diferente, por gente diferente, com a cor escrita direto dentro do código. Quando a marca mudou de tom, ninguém achou todos os lugares.
Este guia mostra o que segura a aparência unida quando as peças são diferentes. São decisões com nome, mais os recursos que o navegador já traz de fábrica hoje. Ele fecha a trilha aberta em como escolher a tecnologia do seu site.
A camada que veste as três stacks
- 1Páginas em Astro, Svelte e ReactConteúdo, storefront e painel consomem a mesma variável, então o botão tem a mesma cara nas três.
- 2Componentes reutilizáveisCard, banner e botão estilizados com as utilitárias do tema; comportamento acessível vem de primitiva headless ou de elemento nativo.
- 3Tailwind v4 CSS-firstCada token declarado em @theme vira variável CSS e classe utilitária de uma vez.
- 4Tokens nomeados em OKLCHEscala de 50 a 950 com contraste previsível e semântica (--color-surface, --color-text, --color-danger) por cima.
Por que a cor da marca precisa de um apelido no sistema?
Porque apelido é o nome de uma decisão, e nome você troca num lugar só. Quem constrói escreve --color-primary uma vez e usa esse apelido nos botões. Quando a marca muda de tom, muda a definição do apelido. O nome técnico desse apelido é token.
Sem apelido, o código da cor vira um número solto repetido em trinta arquivos. Na loja de autopeças, o azul do botão de comprar apareceu em quatro tons porque cada tela recebeu um número copiado à mão em uma data diferente.
Hex solto × token nomeado
Hex solto
- #6366f1 espalhado por trinta arquivos
- color: #1a1a1a cravado vira preto-sobre-preto quando o tema escurece
- Trocar o tom da marca exige editar trinta ocorrências
- O agente adivinha um hex a cada botão
Token nomeado
- --color-primary definido em um lugar só
- O componente referencia var(--color-primary)
- O token adapta por tema e o texto continua visível
- O agente compõe com o token primário que você pediu
A regra não tem exceção: texto e fundo bem diferentes um do outro, sempre. No tema claro e no escuro, a cor precisa vir de um apelido que se adapta, jamais de um tom escuro cravado que some quando o fundo escurece.
Esse hábito evita o defeito de leitura mais comum: o tom cravado no tema escuro. Um cinza quase preto escrito dentro do componente vira preto sobre preto quando o site escurece, e o texto some. O apelido se adapta ao tema; o número cravado fica onde está.
Como montar uma escala de tons que sempre dá para ler?
Você monta a escala pelo brilho, do tom mais claro ao mais escuro. Para isso existe um jeito de escrever cor em que o brilho se comporta como o olho espera, chamado OKLCH. Assim o contraste cresce de forma parelha, sem dar salto.
Contraste é a diferença entre a tinta do texto e o fundo. Ele é requisito do projeto, na mesma altura do prazo de entrega. O piso aceito é de 4,5 vezes para texto comum e de 3 vezes para texto grande. Quem constrói o seu site precisa entregar isso medido.
Quatro termos da escala de cor
@theme {
/* Escala primária em OKLCH: só a luminosidade muda de forma previsível. */
--color-primary-50: oklch(0.97 0.02 277);
--color-primary-500: oklch(0.62 0.19 277);
--color-primary-700: oklch(0.50 0.19 277);
--color-primary-950: oklch(0.28 0.10 277);
/* Tokens semânticos: o componente consome estes, não a escala crua. */
--color-surface: var(--color-primary-950);
--color-text: oklch(0.98 0.01 277); /* claro sobre superfície escura: AA folgado */
--color-danger: oklch(0.58 0.20 25);
}
Repare na separação entre a escala, que são os números, e os apelidos de uso, como superfície, texto e alerta. O componente nunca pega o número cru. Ele pede o apelido. Trocar a paleta inteira vira uma edição pequena, e a legibilidade já foi decidida antes.
Como a ferramenta de estilo aproveita esses apelidos?
Ela lê os apelidos direto do seu arquivo de cores. A versão nova do Tailwind, a ferramenta de estilo mais usada no mercado, deixou de guardar o tema num arquivo de configuração à parte. Agora o tema mora no próprio arquivo de estilos, num bloco chamado @theme.
Cada apelido declarado ali vira duas coisas de uma vez: a variável de cor e o atalho que quem constrói usa nos componentes. Os apelidos da sua marca e a ferramenta deixam de viver em mundos separados.
@import "tailwindcss";
@theme {
--color-primary: oklch(0.62 0.19 277);
--color-on-primary: oklch(0.99 0 0);
--radius-lg: 0.625rem;
}
/* Isto gera, de uma vez: a variável var(--color-primary) E as utilitárias
bg-primary, text-primary, border-primary, rounded-lg... */
Isso muda até o jeito de pedir alteração. Em vez de escrever no chamado "deixe esse botão azul com canto arredondado", quem pede escreve "use os atalhos do nosso tema". Aí quem constrói, ou a IA que ajuda a construir, monta a tela a partir do seu sistema em vez de inventar valor avulso.
Do token ao prompt no Tailwind v4
- Declare o token no bloco @themeA configuração de tema mora dentro do próprio CSS; o tailwind.config.js ficou para trás.
- O motor gera variável e utilitáriaCada token vira, automaticamente, uma variável CSS e uma classe utilitária.
- O componente usa as utilitárias do temabg-primary text-on-primary rounded-lg px-4 py-2, sem valor avulso.
- O prompt fala a língua do sistemaPeça ao agente as utilitárias do seu tema e ele compõe a partir dos seus tokens.
O que o navegador já faz hoje sem programação extra?
Boa parte do que antes exigia biblioteca. Cartão que se adapta ao espaço, estilo que reage ao conteúdo, balão de ajuda, janela de confirmação e transição entre telas já vêm de fábrica. Isso deixa a sua loja mais leve e mais barata de manter.
Os cartões abaixo funcionam de verdade e usam quase todos esses recursos ao mesmo tempo. Os valores são de exemplo. Eles mostram receita, ticket médio (quanto cada cliente gasta, em média, por compra) e conversão (quando o visitante vira cliente pagante). Vale abrir esta página no celular e no computador.
Receita últimos 30 dias
R$ 1,24 mi
▲ 8,2%Ticket médio
R$ 312
▲ 3,1%Ruptura de estoque
6,4%
▼ 1,9 p.p. Fora da metaConversão mobile
1,8%
▲ 0,4 p.p.O primeiro cartão está numa coluna larga e se organiza deitado. Os três de baixo estão numa grade estreita e ficam empilhados. É o mesmo componente, sem nenhuma variação escrita à mão. Quem decide o formato é a regra que mede o espaço disponível.
O cartão que se adapta ao espaço onde foi colocado
A regra antiga media a largura da tela inteira. A regra nova mede o espaço do próprio cartão. Parece detalhe e muda tudo em componente reaproveitado.
.metric-card { container-type: inline-size; container-name: metric; }
/* Quando o espaço do PRÓPRIO card passa de 360px, vira linha. */
@container metric (min-width: 360px) {
.metric-card__box { flex-direction: row; align-items: center; }
}
Na prática, o mesmo cartão fica deitado numa coluna larga e empilhado numa faixa estreita. Ninguém reescreve nada, e quem constrói nem precisa saber em que página o cartão vai parar.
Media query × container query
Media query
- Mede a largura da janela
- Precisa saber em que página o componente está
- Cada contexto pede uma variante ou uma reescrita
Container query
- Mede o espaço onde o card foi colocado
- O mesmo componente, sem nenhuma variante
- Horizontal na coluna larga, empilhado na sidebar estreita
O aviso que pinta o cartão inteiro sozinho
O cartão de ruptura acima está com a borda vermelha. Ninguém mandou pintar. Ele contém um selo de alerta dentro, e a regra de estilo reage a essa presença pintando a moldura toda com o apelido de perigo.
.metric-card__box:has([data-state="alert"]) {
border-color: var(--danger);
box-shadow: 0 0 0 1px var(--danger), 0 8px 28px -12px var(--danger-surface);
}
O texto do alerta usa um vermelho de brilho mais alto sobre uma tinta suave. Essa escolha existe para o aviso continuar legível em fundo escuro, em vez de virar vermelho escuro sobre escuro.
O balão de ajuda e a janela de confirmação
O botão de interrogação de cada cartão abre um detalhe com o recurso de balão nativo do navegador. Fechar com a tecla Esc, fechar clicando fora e aparecer por cima de tudo já vêm prontos, sem uma linha de programação.
.metric-card__info { anchor-name: var(--anchor-name); }
@supports (anchor-name: --a) {
.metric-card__detalhe {
position-anchor: var(--anchor-name);
position-area: block-end span-inline-start;
position-try-fallbacks: flip-block, flip-inline;
}
}
Para o que precisa de resposta antes de seguir, como confirmar a exclusão de um pedido, existe a janela de confirmação nativa. A regra prática é simples: balão para aviso leve, janela quando a pessoa precisa resolver aquilo primeiro.
Qual recurso nativo resolve o caso
- Sea sobreposição é leve e não-modal (detalhe de um card)entãoatributo popover, com fechamento por Esc, dismiss ao clicar fora e camada superior de graça
- Seo usuário precisa resolver aquilo antes de seguir (carrinho, confirmação de exclusão)entãoelemento <dialog>, com foco preso e backdrop nativos
- Seo popover precisa grudar no botão que o abriuentãoanchor positioning
- Seo estilo depende da presença de um filho (selo [data-state="alert"])então:has() pinta o card inteiro com o token --danger
Que acabamentos custam quase nada e melhoram a leitura?
Três, e todos vêm do navegador. O primeiro equilibra a quebra dos títulos, para o título não ficar com uma palavra sozinha na segunda linha. O segundo evita a palavra órfã no fim de um parágrafo.
O terceiro anima a entrada dos blocos conforme a pessoa rola a página, e a troca entre uma tela e outra. Antes isso pedia programação. Hoje sai de duas linhas de estilo.
.metric-card__rotulo { text-wrap: pretty; }
.metric-card__valor { text-wrap: balance; }
[data-reveal] { animation: reveal linear both; animation-timeline: view(); }
.metric-card__box { view-transition-name: var(--vt-name, none); }
Cada um desses recursos falha em silêncio. Navegador antigo simplesmente ignora a regra e mostra o conteúdo legível do mesmo jeito. Por isso dá para usar hoje sem medo de quebrar a loja para alguém.
Como desenhar um painel de números que ajuda a decidir?
Um bom painel responde em segundos a três perguntas: como estamos, em relação a quê e o que mudou. Cada número desse painel é um KPI, ou seja, o número que você olha toda semana para saber se está indo bem.
O inimigo é o enfeite. Gráfico de pizza, medidor redondo e efeito de três dimensões ocupam espaço e dizem pouco. Os cartões acima fazem o contrário e respondem às três perguntas de uma vez.
Olhe o que cada cartão mostra. O valor responde como estamos. A seta com o número responde o que mudou. E a barrinha responde em relação a quê, comparando o realizado com a meta numa linha só. O cartão de receita bateu a meta e o de conversão ficou abaixo.
As três perguntas que o card responde
Prefira a barrinha ao medidor redondo. Ela ocupa menos espaço, compara o realizado com a meta numa linha só e é bem mais fácil de ler. Pizza, medidor redondo e efeito de três dimensões atrapalham num painel de decisão.
Também há uma regra para quando desenhar à mão e quando chamar uma biblioteca. Desenho simples, como barrinha de meta, mini-gráfico de linha e barra de progresso, sai à mão em poucas linhas. Biblioteca só entra no que é denso mesmo: série longa de datas, zoom e filtro no gráfico.
SVG à mão ou biblioteca
- Seo elemento é simples e desenhável à mão (KPI card, bullet chart, sparkline, barra de progresso, waterfall simples, tabela de variância)entãoSVG inline puro, sem dependência
- Seo gráfico é denso ou interativo (séries temporais com muitos pontos, tooltip, zoom, brush, tipos complexos)entãobiblioteca, como ECharts
<svg class="metric-card__bullet" viewBox="0 0 100 12" preserveAspectRatio="none" role="img"
aria-label="Realizado em 124% da meta">
<rect class="bullet-track" x="0" y="4" width="100" height="4" rx="2" />
<rect class="bullet-measure" data-ok="true" x="0" y="4" width="62" height="4" rx="2" />
<rect class="bullet-target" x="49.3" y="1" width="1.4" height="10" />
</svg>
Quando vale usar um componente pronto de terceiro?
Vale quando o comportamento é difícil de acertar. Menu que anda com as setas do teclado, campo de busca com sugestão, abas e lista suspensa com foco controlado entram nessa lista. Errar isso deixa a loja inutilizável para quem navega pelo teclado ou usa leitor de tela.
Para o que é simples, como cartão, selo e botão, o básico do navegador resolve. Para balões e janelas, os recursos nativos que você viu acima chegam antes de qualquer biblioteca.
É aqui que entra o padrão mais usado hoje no mercado, o shadcn. Em vez de instalar uma caixa-preta, você copia o código do componente para dentro do seu projeto. O botão vira um arquivo seu, editável, vestido com os apelidos da sua marca. A parte difícil do comportamento fica delegada a quem já resolveu.
Biblioteca fechada × padrão shadcn
Dependência fechada do npm
- O código do componente mora fora do seu repo
- Você briga com os estilos da biblioteca
- Importa megabytes para desenhar um cartão
Padrão shadcn
- Catálogo copiado para src/components/ui/button.tsx, seu e editável
- Estilizado com as utilitárias do tema, os mesmos tokens
- Só o comportamento acessível fica delegado a uma primitiva headless
A vantagem de copiar o componente para dentro do projeto é ter o código na mão, sem brigar com o estilo de uma biblioteca fechada. Você terceiriza só a parte difícil, o comportamento que alguém já resolveu direito.
O cartão de números deste guia mostra o outro lado. O comportamento dele é simples, então ele dispensa qualquer biblioteca. Saber separar os dois casos é o que segura o peso da sua loja e o tempo de carregamento junto.
Por onde começar na sua loja esta semana?
Comece pelo inventário de cores. Peça a quem constrói a lista dos tons cravados dentro dos componentes e transforme cada um num apelido do tema. Depois disso, escolha um componente que se repete, como um cartão ou uma faixa, e troque a regra de tela pela regra de espaço.
A loja de autopeças do começo fez esses dois passos em duas semanas. O azul virou um apelido só e o botão de comprar ficou igual nas três telas. O cliente parou de sentir que mudou de empresa no meio do caminho.
Para amarrar a escolha de tecnologia a essa camada visual, volte aos guias de Astro, Next 16 e Svelte 5. O mesmo conjunto de apelidos veste as três com a mesma cara.
Próximo passo em três movimentos
- Inventário de coresExtraia para tokens as cores cravadas nos componentes, defina-as em OKLCH no bloco @theme e rode um grep por hex em propriedades de cor.
- Um componente reutilizávelEscolha um card ou um banner e troque a media query por container query.
- Amarrar à stackVolte aos guias de Astro, Next 16 e Svelte 5: o mesmo conjunto de tokens veste as três.
Perguntas frequentes
O que é um token de design, em palavras simples?
É o apelido de uma decisão visual guardado num lugar só. Em vez de escrever o código da cor azul dentro de cada componente, quem constrói escreve o apelido da cor primária. Quando a marca muda de tom, muda a definição do apelido e a loja inteira acompanha. O mesmo vale para arredondamento de canto, espaçamento e tamanho de letra.
Por que a cor da minha loja fica diferente em cada tela?
Porque o código da cor foi escrito à mão dentro de cada pedaço, em épocas diferentes. Quando a marca mudou de tom, ninguém achou todos os lugares. A correção é transformar cada cor num apelido do tema e proibir número de cor solto dentro dos componentes. Uma busca por códigos de cor no projeto mostra o tamanho do problema em minutos.
Preciso mesmo me preocupar com contraste de texto?
Sim, porque contraste baixo faz o cliente desistir de ler e derruba a venda. O piso aceito é de 4,5 vezes de diferença entre tinta e fundo no texto comum, e de 3 vezes no texto grande. Peça essa medição a quem constrói, no tema claro e no escuro. É uma conferência rápida e evita texto que some quando o site escurece.
Em quais telas eu deveria contratar um componente pronto?
Naquelas em que o comportamento é difícil de acertar: menu que anda pelo teclado, campo de busca com sugestão, abas e lista suspensa. Para cartão, selo e botão, o básico do navegador basta. Para balão de ajuda e janela de confirmação, os recursos nativos do navegador chegam antes de qualquer biblioteca e deixam a loja mais leve.
O que o navegador já resolve sozinho em 2026?
Ele resolve o cartão que muda de formato conforme o espaço e o estilo que reage ao conteúdo de dentro. Também o balão de ajuda que fecha com Esc, a janela de confirmação com foco preso e a transição animada entre telas. Todos falham em silêncio em navegador antigo, que mostra o conteúdo legível do mesmo jeito. Isso deixa a loja mais leve e mais barata de manter.
Para levar deste guia
-
Cor de marca precisa de apelido no sistema, definido num lugar só. Assim você troca o tom da marca numa linha em vez de caçar o código em trinta arquivos.
-
Uma escala de tons montada por brilho garante texto legível no tema claro e no escuro. O piso é 4,5 vezes de contraste no texto comum.
-
A ferramenta de estilo mais usada lê esses apelidos direto do seu arquivo de cores, então quem constrói compõe com a sua marca.
-
O navegador já entrega sozinho cartão que se adapta ao espaço, aviso que reage ao conteúdo, balão de ajuda e transição de tela.
-
Componente pronto de terceiro vale onde o comportamento é difícil de acertar. Para cartão e botão simples, o básico do navegador resolve.
De onde vêm os números deste guia?
Cada link abre a publicação de origem, com o nome de quem assina o dado e a data em que ele saiu.
- W3C, Web Content Accessibility Guidelines 2.2, critério de contraste mínimo, 12 de dezembro de 2024.
- Curadoria Brasil GEO, Alexandre Caramaschi, 2026.
Cursos para aprofundar
Formações gratuitas do portal de educação de Alexandre Caramaschi, fundador da Brasil GEO.
SEO Técnico para E-commerce
Core Web Vitals, renderização e crawl budget: o que a stack do storefront precisa entregar para ranquear e ser citada.
Curso gratuitoCRO e Experimentação
Governança de experimentos e testes A/B para evoluir a interface sem quebrar a conversão a cada release da stack.
Leve a decisão para o seu contexto
Este guia mostra o que pedir a quem constrói; os números da sua loja mostram a prioridade. As calculadoras do portal fazem essa conta com os seus dados, e a Onclick mostra como um sistema de retaguarda integrado, o sistema por trás do caixa, sustenta essa rotina.