O que são design tokens e por que eles são a base do sistema visual
Design tokens são valores nomeados que representam decisões de design de forma reutilizável e consistente. Em vez de espalhar valores “soltos” como #1e90ff, 16px ou 0 8px 24px rgba(0,0,0,.12) pelo CSS, você centraliza essas escolhas em um conjunto de variáveis com significado. O token vira a “fonte da verdade” para cores, tipografia, espaçamentos, raios e sombras, permitindo que o sistema visual seja aplicado de forma uniforme em componentes diferentes.
O ponto principal não é “usar variáveis”, e sim transformar decisões visuais em um vocabulário estável. Isso reduz divergências (tons parecidos, espaçamentos quase iguais, sombras inconsistentes), facilita mudanças globais e melhora a comunicação entre design e desenvolvimento: em vez de “usa um cinza mais escuro”, você fala “usa --color-text”.
Tokens também ajudam a separar o que é decisão de design do que é implementação. Um componente não deveria “saber” que o azul é #2563eb; ele deveria pedir “cor de ação primária”. Assim, quando o tema muda, o componente continua correto.
Tipos de tokens: base, semânticos e de componente
Uma forma prática de pensar tokens é em três níveis:
- Tokens de base (primitivos): valores “brutos” do sistema, como paleta de cores (escala de cinzas e cores), escala tipográfica, escala de espaçamento, níveis de raio e elevação. Ex.:
--blue-600,--space-4,--radius-md. - Tokens semânticos: mapeiam intenção/uso para um valor de base. Ex.:
--color-bgaponta para um cinza claro no tema claro e para um cinza escuro no tema escuro. Componentes usam tokens semânticos sempre que possível. - Tokens de componente: ajustes específicos de um componente, ainda assim nomeados e centralizados. Ex.:
--button-padding-x,--card-shadow. Eles podem referenciar tokens semânticos/base.
Em projetos reais, a regra de ouro é: componentes consomem tokens semânticos; tokens semânticos apontam para tokens de base; tokens de componente existem quando a semântica geral não cobre o caso ou quando há necessidade de parametrização controlada.
Continue em nosso aplicativo
Você poderá ouvir o audiobook com a tela desligada, ganhar gratuitamente o certificado deste curso e ainda ter acesso a outros 5.000 cursos online gratuitos.
ou continue lendo abaixo...Baixar o aplicativo
Como estruturar tokens no CSS com variáveis (Custom Properties)
Uma abordagem prática é declarar tokens no :root (tema padrão) e sobrescrever em seletores de tema (por exemplo, [data-theme="dark"]). Isso permite troca de tema sem recompilar CSS e com baixo acoplamento.
:root { /* Base: cores (exemplo reduzido) */ --gray-0: #ffffff; --gray-50: #f8fafc; --gray-100: #f1f5f9; --gray-700: #334155; --gray-900: #0f172a; --blue-600: #2563eb; --red-600: #dc2626; /* Base: tipografia */ --font-sans: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; --text-sm: 0.875rem; --text-md: 1rem; --text-lg: 1.125rem; --line-md: 1.5; /* Base: espaçamento (escala) */ --space-1: 0.25rem; --space-2: 0.5rem; --space-3: 0.75rem; --space-4: 1rem; --space-6: 1.5rem; --space-8: 2rem; /* Base: raios */ --radius-sm: 0.375rem; --radius-md: 0.5rem; --radius-lg: 0.75rem; /* Base: sombras (elevação) */ --shadow-1: 0 1px 2px rgba(15, 23, 42, 0.08); --shadow-2: 0 4px 12px rgba(15, 23, 42, 0.12); --shadow-3: 0 12px 28px rgba(15, 23, 42, 0.16); /* Semânticos: superfícies e texto */ --color-bg: var(--gray-50); --color-surface: var(--gray-0); --color-border: var(--gray-100); --color-text: var(--gray-900); --color-text-muted: var(--gray-700); /* Semânticos: ações e estados */ --color-primary: var(--blue-600); --color-danger: var(--red-600); /* Semânticos: foco */ --color-focus: var(--blue-600);}Agora o tema escuro sobrescreve apenas tokens semânticos (e, se necessário, alguns de base). Isso evita duplicação e mantém o sistema previsível.
[data-theme="dark"] { --color-bg: var(--gray-900); --color-surface: #111c33; --color-border: rgba(255,255,255,0.08); --color-text: var(--gray-0); --color-text-muted: rgba(255,255,255,0.72); --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.35); --shadow-2: 0 6px 16px rgba(0, 0, 0, 0.45);}Boas práticas de nomenclatura para tokens
- Base: nomes neutros e escalas previsíveis (
--gray-100,--space-4,--shadow-2). - Semânticos: nomes orientados a intenção (
--color-text,--color-surface,--color-primary). - Evite tokens semânticos com nome de cor (
--primary-blue) porque isso dificulta rebranding e temas. - Evite granularidade excessiva no início. Comece com poucos tokens semânticos e expanda conforme surgirem necessidades reais.
Cores: paleta, contraste e tokens semânticos
Para cores, o erro comum é usar apenas tokens de base (ex.: --blue-600) diretamente nos componentes. Isso faz o componente depender da paleta e dificulta temas. Prefira tokens semânticos para usos recorrentes: fundo, superfície, texto, borda, ação primária, ação secundária, perigo, sucesso, aviso, informação.
Passo a passo: criar tokens de cor do zero
1) Defina uma escala de neutros (cinzas) e, se necessário, escalas de cores principais. A escala deve ter passos consistentes (ex.: 0, 50, 100… 900). Mesmo que você não use todos, a escala ajuda a manter coerência.
2) Defina tokens semânticos mínimos para layout e texto. Um conjunto inicial útil:
--color-bg,--color-surface,--color-surface-raised--color-text,--color-text-muted,--color-text-inverse--color-border,--color-divider--color-primary,--color-on-primary--color-danger,--color-on-danger
3) Mapeie tokens semânticos para base no tema padrão e sobrescreva no tema alternativo.
4) Use tokens semânticos nos componentes. Exemplo de botão e card consumindo tokens:
.c-card { background: var(--color-surface); color: var(--color-text); border: 1px solid var(--color-border); border-radius: var(--radius-lg); box-shadow: var(--shadow-1); padding: var(--space-6);} .c-button { font: 600 var(--text-md)/var(--line-md) var(--font-sans); border-radius: var(--radius-md); padding: var(--space-2) var(--space-4); border: 1px solid transparent; background: var(--color-primary); color: var(--color-on-primary);}5) Trate estados com tokens específicos quando necessário, em vez de “escurecer no olho”. Ex.: --color-primary-hover, --color-primary-active, --color-focus-ring. Se o projeto tiver muitos estados, vale criar uma pequena família semântica por intenção.
Tokens para foco e acessibilidade
Um token de foco consistente evita cada componente inventar um outline diferente. Exemplo:
:root { --focus-ring: 0 0 0 3px color-mix(in srgb, var(--color-focus) 35%, transparent);} .u-focus-ring:focus-visible { outline: none; box-shadow: var(--focus-ring);}Se preferir não depender de color-mix, defina um token pronto como --color-focus-alpha (um rgba) e use diretamente.
Tipografia: famílias, tamanhos, pesos e alturas de linha
Tokens de tipografia devem cobrir: família (sans/serif/mono), tamanhos (escala), pesos e alturas de linha. Em vez de definir font-size arbitrário por componente, use uma escala (ex.: 12, 14, 16, 18, 20, 24, 32) em rem. Isso melhora consistência e facilita ajustes globais.
Passo a passo: montar uma escala tipográfica simples
1) Defina o tamanho base do documento (geralmente 16px). Use rem nos tokens para respeitar preferências do usuário.
2) Crie tokens de tamanho com nomes por intenção (opcional) ou por escala. Um padrão comum é --text-sm, --text-md, --text-lg, --text-xl.
3) Defina alturas de linha como tokens. Isso evita variações sutis que quebram ritmo vertical.
4) Defina pesos como tokens para padronizar (400, 500, 600, 700).
:root { --font-sans: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; --weight-regular: 400; --weight-medium: 500; --weight-semibold: 600; --weight-bold: 700; --text-xs: 0.75rem; --text-sm: 0.875rem; --text-md: 1rem; --text-lg: 1.125rem; --text-xl: 1.25rem; --text-2xl: 1.5rem; --line-tight: 1.25; --line-md: 1.5; --line-loose: 1.75;}Aplicação em componentes:
.c-input { font-family: var(--font-sans); font-size: var(--text-md); line-height: var(--line-md); font-weight: var(--weight-regular);} .c-card__title { font-size: var(--text-xl); line-height: var(--line-tight); font-weight: var(--weight-semibold);}Se o projeto tiver muitos estilos de texto (títulos, subtítulos, corpo, legenda), você pode criar tokens semânticos de tipografia, como --type-body, --type-heading, mas no CSS puro isso costuma virar combinações de múltiplas propriedades. Uma alternativa é criar utilitários ou classes de objeto para “text styles”, mantendo os valores ainda baseados em tokens.
Espaçamentos: escala, ritmo e consistência entre componentes
Tokens de espaçamento resolvem um problema clássico: cada componente inventa margens e paddings diferentes, e o layout fica “quase alinhado”. Uma escala (ex.: 4px, 8px, 12px, 16px, 24px, 32px) cria ritmo e reduz decisões repetitivas.
Passo a passo: definir e aplicar uma escala de espaçamento
1) Escolha uma unidade base (muito comum: 4px). Em rem, 4px vira 0.25rem se a base for 16px.
2) Crie tokens de escala com incrementos coerentes. Evite criar --space-5 se ele não for usado; prefira uma escala que faça sentido para o produto.
3) Use tokens para padding, gap e margin. Exemplo de um header de card e uma lista com espaçamento consistente:
.c-card__header { padding: var(--space-6); border-bottom: 1px solid var(--color-border);} .c-stack { display: flex; flex-direction: column; gap: var(--space-3);} .c-stack--lg { gap: var(--space-6);}4) Evite “ajustes finos” fora da escala. Se surgir necessidade recorrente de um valor intermediário, adicione um token novo de forma deliberada (e não como exceção isolada).
Uma dica prática é tratar gap como cidadão de primeira classe: muitos espaçamentos internos de componentes ficam mais simples com gap do que com margens em elementos filhos.
Raios (border-radius): consistência de cantos e hierarquia visual
Raios são um detalhe que rapidamente vira bagunça: botões com 6px, cards com 10px, inputs com 4px. Tokens de raio padronizam a “assinatura” visual. Além disso, raios podem expressar hierarquia: elementos menores com raio menor, superfícies maiores com raio maior.
Passo a passo: criar tokens de raio e aplicar
1) Defina poucos níveis: por exemplo, sm, md, lg e um pill (totalmente arredondado).
:root { --radius-sm: 0.375rem; --radius-md: 0.5rem; --radius-lg: 0.75rem; --radius-pill: 9999px;}2) Aplique por intenção:
- Inputs e botões:
--radius-md - Cards e modais:
--radius-lg - Chips/badges:
--radius-pill
.c-badge { border-radius: var(--radius-pill); padding: var(--space-1) var(--space-2);} .c-modal { border-radius: var(--radius-lg); box-shadow: var(--shadow-3);}3) Se houver variações por tema (ex.: tema “mais quadrado”), você pode sobrescrever tokens de raio no seletor do tema, sem tocar nos componentes.
Sombras: elevação, camadas e coerência entre superfícies
Sombras comunicam elevação e separação entre camadas (card sobre fundo, dropdown sobre card, modal sobre tudo). Sem tokens, cada componente cria uma sombra diferente, e o resultado parece inconsistente. Com tokens, você define níveis de elevação e aplica conforme a função do elemento.
Passo a passo: definir níveis de elevação
1) Defina 3 a 5 níveis de sombra. Exemplo:
--shadow-1: leve (cards, inputs em foco leve)--shadow-2: médio (dropdown, popover)--shadow-3: forte (modal)
2) Crie tokens semânticos para casos recorrentes se necessário, como --shadow-surface, --shadow-overlay, apontando para os níveis base. Isso facilita mudar a estratégia sem alterar componentes.
:root { --shadow-1: 0 1px 2px rgba(15, 23, 42, 0.08); --shadow-2: 0 4px 12px rgba(15, 23, 42, 0.12); --shadow-3: 0 12px 28px rgba(15, 23, 42, 0.16); --shadow-surface: var(--shadow-1); --shadow-floating: var(--shadow-2); --shadow-overlay: var(--shadow-3);}3) Aplique por função:
.c-card { box-shadow: var(--shadow-surface);} .c-dropdown { box-shadow: var(--shadow-floating);} .c-modal { box-shadow: var(--shadow-overlay);}4) Ajuste por tema. Em tema escuro, sombras muitas vezes precisam de mais opacidade e/ou combinação com bordas. Você pode sobrescrever --shadow-* e --color-border no tema escuro para manter percepção de profundidade.
Integração prática: tokens semânticos por superfície e componentes parametrizáveis
Um sistema visual consistente costuma girar em torno de “superfícies” (backgrounds) e seus conteúdos. Uma forma prática de escalar é criar tokens semânticos por tipo de superfície e usar tokens de componente para ajustes locais.
Exemplo: superfícies e conteúdo
:root { --surface-0: var(--color-bg); --surface-1: var(--color-surface); --surface-2: var(--color-surface); --on-surface: var(--color-text); --on-surface-muted: var(--color-text-muted);} .c-page { background: var(--surface-0); color: var(--on-surface);} .c-panel { background: var(--surface-1); color: var(--on-surface); border: 1px solid var(--color-border); border-radius: var(--radius-lg);}Se um componente precisar de ajustes sem quebrar o sistema, use tokens de componente com fallback para tokens globais:
.c-button { --button-radius: var(--radius-md); --button-padding-y: var(--space-2); --button-padding-x: var(--space-4); --button-bg: var(--color-primary); --button-fg: var(--color-on-primary); border-radius: var(--button-radius); padding: var(--button-padding-y) var(--button-padding-x); background: var(--button-bg); color: var(--button-fg);} .c-button--sm { --button-padding-y: var(--space-1); --button-padding-x: var(--space-3); font-size: var(--text-sm);} .c-button--danger { --button-bg: var(--color-danger); --button-fg: var(--color-on-danger);}Esse padrão permite variações controladas sem “furar” a base do sistema visual. O componente continua consumindo tokens e expondo pontos de ajuste claros.
Checklist prático para implementar tokens em um projeto existente
1) Inventário de valores repetidos
Liste valores que aparecem muitas vezes: cores hex, tamanhos de fonte, paddings, raios e sombras. Agrupe por similaridade e escolha quais viram tokens de base. O objetivo é reduzir variações quase iguais.
2) Definição das escalas mínimas
Crie escalas pequenas e úteis: uma escala de espaçamento, uma escala tipográfica, 3 níveis de raio e 3 níveis de sombra. Evite criar dezenas de tokens antes de validar o uso real.
3) Criação de tokens semânticos
Defina tokens semânticos para os usos mais frequentes (texto, fundo, superfície, borda, primário, perigo, foco). Mapeie para tokens de base no tema padrão.
4) Migração incremental por componente
Escolha um componente por vez e substitua valores diretos por tokens. Exemplo de migração típica:
- Trocar
background: #fffporbackground: var(--color-surface) - Trocar
border-radius: 8pxporborder-radius: var(--radius-lg) - Trocar
padding: 12px 16pxporpadding: var(--space-3) var(--space-4) - Trocar
box-shadowporvar(--shadow-1)
5) Temas e modos (claro/escuro) com sobrescrita semântica
Implemente o tema alternativo sobrescrevendo tokens semânticos e, quando necessário, tokens de sombra. Evite duplicar regras de componentes para cada tema.
6) Regras de uso para o time
Defina regras simples e objetivas:
- Componentes não usam valores hex diretamente; usam tokens semânticos.
- Espaçamentos devem vir da escala; exceções viram tokens novos após revisão.
- Sombras só podem ser uma das elevações definidas.
- Raios só podem ser os níveis definidos (sm/md/lg/pill).
Essas regras reduzem divergências e tornam revisões de CSS mais rápidas, porque o revisor procura “uso de token” em vez de avaliar cada valor individual.