Um sistema de design no WordPress é o conjunto de tokens, controlos permitidos no editor e layouts inseríveis que o Gutenberg consegue de facto impor. Os ficheiros do Figma não impõem nada no site publicado. Em 2026, esse contrato é o theme.json versão 3, a pasta /patterns e um número reduzido de blocos personalizados. Tudo o resto é um protótipo ou um objeto na base de dados que tem de ser tratado como tal.
Vemos sempre a mesma falha em sites editoriais grandes: o manual da marca está no Figma, o CSS está espalhado por cinco folhas de estilo e o editor continua a oferecer um seletor de cores livre. O marketing lança então um hex de campanha que existe numa única landing page. A campanha seguinte copia-o. Seis meses depois, já ninguém sabe dizer qual dos verdes é o verde da marca. O Gutenberg consegue evitar isto, mas só se desligar esses controlos e puser a paleta no theme.json.
Este artigo não pretende convencer ninguém a migrar de page builder. Se está a escolher entre o Gutenberg, o Elementor ou o Divi, leia a comparação de builders de 2026. Se está a decidir entre um block theme e um tema clássico em PHP, leia temas clássicos vs block themes. Aqui tratamos da camada que vem depois dessa escolha: como o sistema se mantém consistente quando os editores usam o inseridor todos os dias.
Como configurar o theme.json versão 3 para um sistema de design
A especificação viva é o theme.json versão 3. Foi introduzido no WordPress 6.6: o artigo do WordPress Developer Blog sobre estilos de secção indica que o esquema da versão 3 só é suportado no WordPress 6.6 ou posterior, ou com o plugin Gutenberg num core mais antigo. Os ficheiros antigos com version: 2 continuam a carregar. As novas definições chegam à versão 3. Essa especificação não tem versão 4, ao contrário do que afirmavam muitos resumos de 2025.
Aponte o ficheiro para o esquema que corresponde à versão mínima do WordPress que suporta, e não para trunk, a menos que o site corra sempre com o plugin Gutenberg:
{
"$schema": "https://schemas.wp.org/wp/6.6/theme.json",
"version": 3,
"settings": {},
"styles": {}
}settings define o que o editor pode fazer. styles define o aspeto por omissão quando ninguém altera um bloco. Misturar os dois é a forma como as equipas acabam por entregar, sem querer, um aspeto por omissão bonito que os editores conseguem estragar com um clique.
Num site que tem de respeitar a marca, o primeiro bloco settings que escrevemos é este. Fecha os seletores livres de cor, tamanho de letra e espaçamento, e dá ao editor escalas fixas em vez deles:
{
"$schema": "https://schemas.wp.org/wp/6.6/theme.json",
"version": 3,
"settings": {
"color": {
"custom": false,
"customDuotone": false,
"customGradient": false,
"defaultPalette": false,
"defaultGradients": false,
"defaultDuotone": false,
"palette": [
{ "slug": "base", "name": "Base", "color": "#ffffff" },
{ "slug": "contrast", "name": "Contraste", "color": "#111111" },
{ "slug": "primary", "name": "Primária", "color": "#0b3d91" },
{ "slug": "accent", "name": "Destaque", "color": "#c2410c" }
]
},
"typography": {
"customFontSize": false,
"dropCap": false,
"fontSizes": [
{ "slug": "small", "name": "Pequeno", "size": "0.875rem" },
{ "slug": "medium", "name": "Médio", "size": "1rem" },
{ "slug": "large", "name": "Grande", "size": "1.5rem" },
{ "slug": "x-large", "name": "Muito grande", "size": "2.25rem" }
]
},
"spacing": {
"customSpacingSize": false,
"defaultSpacingSizes": false,
"spacingSizes": [
{ "slug": "20", "name": "XS", "size": "0.5rem" },
{ "slug": "30", "name": "S", "size": "1rem" },
{ "slug": "40", "name": "M", "size": "1.5rem" },
{ "slug": "50", "name": "L", "size": "2.5rem" },
{ "slug": "60", "name": "XL", "size": "4rem" }
]
}
}
}color.custom: false é o antigo add_theme_support( 'disable-custom-colors' ). defaultPalette: false esconde as amostras cinzentas e azuis do core, para que o seletor mostre apenas os seus slugs. A correspondência está no manual Global Settings and Styles. Se estas duas opções ficarem nos valores por omissão (true), não tem um sistema de design. Tem uma sugestão.
customSpacingSize: false remove o campo livre de espaçamento, e defaultSpacingSizes: false impede o core de acrescentar a sua própria escala de espaçamento ao lado da sua. Ambas as chaves aparecem em settings.spacing na referência viva, junto de spacingSizes e spacingScale.
appearanceTools: true não serve para bloquear nada. A referência viva enumera o que ativa: imagem e tamanho de fundo, cor, raio, estilo e largura do contorno, cores de ligações, títulos, botões e legendas, proporção, altura, altura mínima, largura mínima e largura, posição fixa (sticky), espaço entre blocos, margem e preenchimento, e altura de linha. Use-o quando o trabalho de layout pertence ao editor. Deixe-o desligado, ou defina as chaves individualmente, quando quer que o espaçamento venha apenas dos presets.
Como o Gutenberg converte presets do theme.json em variáveis CSS
Cada slug da paleta passa a ser a propriedade personalizada --wp--preset--color--{slug} e classes utilitárias como .has-{slug}-color e .has-{slug}-background-color. Os tamanhos de letra e de espaçamento seguem --wp--preset--font-size--{slug} e --wp--preset--spacing--{slug}. Esta nomenclatura está no mesmo manual. O CSS próprio do tema deve usar estas variáveis, e não um segundo conjunto de tokens --brand-primary que acaba por divergir.
Os valores que não têm um tipo de preset, como profundidades de sombra ou raios de canto a que se quer dar nome, vão para settings.custom. O manual documenta que cada chave aí colocada se torna uma propriedade --wp--custom--{key}, com as chaves aninhadas unidas por um hífen duplo. Uma pequena folha de tokens para o exemplo acima fica assim no CSS gerado:
/* Presets de settings.color.palette e settings.typography.fontSizes */
--wp--preset--color--primary: #0b3d91;
--wp--preset--color--accent: #c2410c;
--wp--preset--font-size--large: 1.5rem;
/* Presets de settings.spacing.spacingSizes */
--wp--preset--spacing--30: 1rem;
--wp--preset--spacing--40: 1.5rem;
/* De settings.custom: { "radius": { "card": "8px" } } */
--wp--custom--radius--card: 8px;É tudo o que há a dizer sobre design tokens no Gutenberg. O WordPress não importa o Tokens Studio. Gera presets a partir do theme.json. Se a equipa de design já tem tokens em JSON, o pipeline honesto é um passo de build que escreve settings.color.palette (e as escalas de tipografia e espaçamento) no theme.json. O deploy entrega então um único ficheiro. Um webhook do Figma que “publica em produção” sem essa escrita é uma demonstração, não um sistema.
Como dividir o theme.json num site grande
Os temas filho fundem o seu theme.json por cima do tema pai. As variações de estilo vivem como ficheiros JSON adicionais em /styles. O PHP pode ainda alterar a árvore com o filtro wp_theme_json_data_theme quando um site de uma rede precisa de outra cor primária sem criar um fork do tema. Estas três divisões são o que o core oferece. Compilar doze fragmentos JSON numa tarefa Node não tem mal se a equipa já mantém essa tarefa. Não é obrigatório, nem está documentado como funcionalidade do WordPress.
Quando uma equipa escolhe o caminho da compilação, a estrutura costuma ser esta:
theme/
├── theme.json (gerado, versionado)
├── config/
│ ├── color.json
│ ├── typography.json
│ ├── spacing.json
│ └── custom.json
└── build-theme-json.js (funde config/ no theme.json)Design, desenvolvimento e marketing podem então editar os seus próprios ficheiros sem conflitos de merge num único documento JSON enorme. O custo é que o script de fusão passa a ser código que alguém tem de manter, testar e atualizar quando o esquema muda.
Como as variações de estilo trocam a paleta sem CSS novo
Uma paleta alternativa não precisa de uma segunda folha de estilo. O caminho do core é uma variação de estilo: um ficheiro JSON em /styles que redefine os mesmos slugs. O proprietário do site escolhe-a no Editor do site, em Estilos, e todos os blocos que já consomem as variáveis dos presets acompanham a mudança.
Variação de estilo em /styles/dark.json:
{
"$schema": "https://schemas.wp.org/wp/6.6/theme.json",
"version": 3,
"title": "Dark",
"settings": {
"color": {
"palette": [
{ "slug": "base", "name": "Base", "color": "#111111" },
{ "slug": "contrast", "name": "Contraste", "color": "#f5f5f5" }
]
}
},
"styles": {
"color": {
"background": "var(--wp--preset--color--base)",
"text": "var(--wp--preset--color--contrast)"
}
}
}A variação mantém os nomes dos slugs e altera apenas os seus valores. É essa a regra que faz tudo funcionar: os blocos guardam o slug, não o hex. Uma alternância automática entre modo claro e escuro com base em prefers-color-scheme não vem com o core. Continua a ser CSS escrito por si.
Desde o WordPress 6.6, a mesma pasta aceita também variações só de cor e só de tipografia, segundo o artigo do Developer Blog sobre variações de estilo de bloco. Para um grupo de marcas numa única base de código, isto dá uma separação limpa: espaçamento e layout partilhados no theme.json principal e um ficheiro de variação por cada paleta de marca.
Como funcionam os estilos de secção no theme.json desde o WordPress 6.6
Antes do 6.6, um estilo de bloco personalizado como “Boxed” num Pullquote implicava uma classe CSS e CSS escrito à mão. O WordPress 6.3 só tinha permitido ao theme.json editar os estilos de bloco registados pelo core. No artigo do Developer Blog de junho de 2024, Justin Tadlock explica que o WordPress 6.6 permite estilizar no theme.json qualquer variação de estilo de bloco registada, em styles.blocks.{block}.variations.{name}, incluindo os elementos e blocos aninhados dentro dela. O mesmo artigo descreve os “estilos de secção” como um conceito introduzido no 6.6: uma variação de estilo de bloco aplicada a uma secção, juntamente com os elementos e blocos aninhados que redefine.
Um estilo de secção pode ser registado a partir de um ficheiro JSON em /styles (o WordPress procura também em subpastas, por isso /styles/section/ funciona). A chave blockTypes enumera os blocos a que se aplica:
{
"$schema": "https://schemas.wp.org/wp/6.6/theme.json",
"version": 3,
"slug": "section-dark",
"title": "Dark section",
"blockTypes": [ "core/group", "core/columns" ],
"styles": {
"color": {
"background": "var:preset|color|contrast",
"text": "var:preset|color|base"
},
"elements": {
"link": {
"color": { "text": "var:preset|color|accent" }
}
}
}
}A mesma variação pode ser registada em PHP. No 6.6, register_block_style() aceita uma lista de nomes de blocos como primeiro argumento e uma chave style_data com a mesma estrutura do ficheiro JSON:
register_block_style(
array( 'core/group', 'core/columns' ),
array(
'name' => 'section-dark',
'label' => __( 'Dark section', 'themeslug' ),
'style_data' => array(
'color' => array(
'background' => 'var:preset|color|contrast',
'text' => 'var:preset|color|base',
),
),
)
);Num sistema de design, isto substitui a fonte de divergência mais comum: editores a escolher à mão as cores de fundo e de texto em cada Group. Com os estilos de secção, escolhem “Dark section” no painel Estilos, e o par de cores de fundo, texto e ligações vem de uma única definição. Uma variação de estilo global pode depois reajustar essa secção através da propriedade de topo styles.variations, para que uma variação de marca mude a secção escura juntamente com tudo o resto. O mesmo artigo assinala um limite a ter presente: os estilos de secção funcionam melhor em blocos contentores como Group, Columns e Cover.
Padrões do tema vs padrões sincronizados no WordPress
Esta é a distinção que mais estraga projetos.
O capítulo introdutório sobre padrões do Theme Handbook é direto: os padrões colocados em /patterns não são sincronizados. São modelos para a próxima inserção. O WordPress copia o markup dos blocos para o post. Se mais tarde editar o ficheiro PHP, as páginas existentes não mudam. O mesmo manual acrescenta que os padrões sincronizados só podem ser criados e geridos a partir da administração do WordPress.
Os padrões sincronizados (blocos reutilizáveis antes do WordPress 6.3) são posts wp_block na base de dados. São criados no editor. Todas as instâncias mudam em conjunto. Estes objetos não estão no Git. O staging e a produção precisam cada um do mesmo registo wp_block, ou terá de os recriar à mão.
Use esta divisão de propósito:
| Tipo | Onde vive | Atualiza páginas existentes | Passa entre ambientes |
|---|---|---|---|
Padrão do tema (/patterns) | no tema, no Git | não | sim, com o deploy |
| Padrão sincronizado | na base de dados | sim | só se copiar os dados wp_block |
| Parte de template (cabeçalho/rodapé) | ficheiro do tema até ser editado, depois base de dados | sim, enquanto parte | ficheiro até alguém o personalizar |
Heroes, layouts de casos de estudo e esqueletos de landing pages pertencem a /patterns. Um aviso legal, uma linha sobre cookies ou um banner que o departamento jurídico pode reescrever esta tarde pertencem a um padrão sincronizado, com uma exportação documentada para que o staging não traga surpresas.
Registe os padrões do tema colocando em /patterns um ficheiro PHP com cabeçalho, que é o caminho recomendado no capítulo sobre registo de padrões, ou chamando register_block_pattern() no init. Um padrão, um método. Não registe o mesmo slug duas vezes.
Na prática, uma biblioteca de padrões tem duas camadas. Os padrões de secção pequenos são as peças base: um hero com título, introdução, botão e imagem, um cartão de serviço com ícone, título, texto e ligação, um testemunho com fotografia, citação, nome e cargo, um banner de chamada para a ação. Os padrões de página inteira combinam-nos nos tipos de página que o marketing repete: uma landing page de serviço, um caso de estudo, uma página de equipa, uma página de contacto. Os editores escolhem um padrão de página inteira e substituem o texto de exemplo, pelo que uma página nova começa dentro das regras da marca e não num ecrã vazio.
Os padrões sincronizados justificam-se para conteúdo que tem de mudar em todo o lado no mesmo dia: avisos legais, linhas de consentimento, blocos com a morada e o telefone da empresa, a chamada para a ação da campanha em curso.
Como os overrides de padrões e a Block Bindings API ligam conteúdo
Um padrão sincronizado era antes tudo ou nada: ou todas as instâncias eram idênticas, ou o desanexava e perdia a sincronização. O WordPress 6.6 acrescentou os overrides em padrões sincronizados. No tutorial do Developer Blog assinado por Nick Diego, um cartão mantém o design partilhado enquanto cada instância altera o título, o texto e o botão. No editor, abre o padrão sincronizado com “Edit original”, seleciona um bloco, clica em “Enable overrides” no painel “Advanced” do inspetor de blocos e atribui-lhe um nome único. O markup do bloco passa então a ter uma ligação à fonte core/pattern-overrides.
Os overrides assentam em dois mecanismos mais antigos. A edição apenas de conteúdo, introduzida no WordPress 6.1, é templateLock: "contentOnly" num bloco contentor: só o texto e os media aninhados continuam editáveis, e os controlos do inspetor para definições e estilos ficam desativados. O segundo é a Block Bindings API, disponível desde o WordPress 6.5, que liga um atributo de bloco a uma fonte de dados em vez de a conteúdo estático.
O manual enumera os blocos core e atributos que aceitam bindings por omissão:
| Bloco | Atributos que aceitam binding |
|---|---|
| Image | id, url, title, alt, caption |
| Heading, Paragraph | content |
| Button | url, text, linkTarget, rel |
| Navigation Link, Navigation Submenu | url |
| Post Date | datetime |
As fontes incorporadas são core/post-meta (a meta key tem de estar registada com show_in_rest e não pode começar por sublinhado), core/pattern-overrides e, desde o WordPress 6.9, core/post-data (data, data de modificação e ligação) e core/term-data. Um plugin pode acrescentar a sua própria fonte com register_block_bindings_source() no init, passando um label, uma lista opcional uses_context e um get_value_callback. O binding propriamente dito fica no metadata do bloco:
<!-- wp:paragraph {"metadata":{"bindings":{"content":{"source":"core/post-meta","args":{"key":"product_sku"}}}}} -->
<p></p>
<!-- /wp:paragraph -->Num sistema de design, é assim que um padrão continua a ser um padrão enquanto os seus dados vêm de campos estruturados. Um padrão de cartão de produto pode ligar o parágrafo do SKU a post meta, para que os editores nunca o escrevam no layout. Há dois limites do manual que importam aqui. O registo do lado do editor com registerBlockBindingsSource() chegou no 6.7, e um valor ligado não é editável no editor a menos que a fonte forneça canUserEditValue. O artigo sobre overrides notava ainda, em junho de 2024, que os padrões sincronizados ficam guardados apenas na base de dados e não podem ser empacotados como ficheiros de padrões num tema, com as primeiras explorações acompanhadas numa issue do Gutenberg.
Como versionar padrões do tema com Git
O WordPress não versiona padrões: não há estados, nem aprovações, nem migração automática das instâncias já inseridas. O que existe é o Git na pasta /patterns, e é a equipa que define o ciclo:
- Rascunho: o novo padrão vive num branch.
- Revisão: a marca ou o jurídico aprovam-no no pull request.
- Publicado: é feito o deploy e aparece no inseridor.
- Retirado: sai do inseridor quando se apaga o ficheiro ou a chamada a
register_block_pattern(). As páginas que já o inseriram mantêm o seu markup, e é preciso tratá-las uma a uma.
O quarto passo é a razão para manter o conjunto de padrões curto. Cada padrão publicado deixa no conteúdo cópias a que o tema já não chega.
Como bloquear templates do Gutenberg com templateLock
Uma paleta com custom: false continua a falhar se o template da página for um Group vazio e o inseridor oferecer todos os blocos core. Para tipos de página que têm de seguir o modelo (produto, localização, documentação), bloqueie o template: allowedBlocks no grupo, templateLock: "insert" ou "all" onde o layout não pode ser reorganizado, e um padrão como conteúdo por omissão para que o editor nunca comece num ecrã em branco.
A referência de block templates define os valores. all impede inserir, mover e apagar blocos. insert impede inserir ou remover blocos, mas permite mover os existentes. contentOnly impede todas as operações, esconde da vista de lista os blocos sem conteúdo e não pode ser anulado por blocos filhos. O bloco Group declara templateLock como atributo no seu block.json, pelo que o bloqueio pode ficar diretamente no markup de um template ou de um padrão.
Há mais dois níveis. Um bloco individual pode ter um atributo lock com as opções move e remove, e a referência indica que o bloqueio ao nível do bloco tem prioridade sobre templateLock. Um custom post type pode registar a sua própria lista template e um template_lock em register_post_type(), para que cada novo produto comece com a mesma estrutura de blocos.
Dentro de um bloco personalizado, o mesmo bloqueio aplica-se aos blocos internos:
<InnerBlocks
template={ TEMPLATE }
templateLock="all"
allowedBlocks={ [ 'core/heading', 'core/paragraph', 'core/button' ] }
/>Os editores continuam a poder alterar texto e imagens, mas não conseguem reordenar, remover ou acrescentar blocos fora da estrutura definida.
Quando criar um bloco Gutenberg personalizado com block.json
É também aí que os blocos personalizados se justificam. Heading, Paragraph e Image do core cobrem a maior parte dos módulos de marketing. Uma tabela de comparação que tem de levar um SKU, uma moeda e uma data de “última verificação” precisa de atributos e de validação no block.json. Construímos esses blocos com @wordpress/scripts, mantemos o markup do save simples e recusamo-nos a recriar um page builder dentro do inspetor. Se o bloco é apenas uma capa à volta de blocos internos, prefira um padrão.
Uma pasta de bloco no repositório do sistema de design tem este aspeto:
blocks/
└── product-comparison/
├── block.json
├── edit.js (UI do editor)
├── save.js (markup do front-end)
├── style.scss (estilos do front-end e do editor)
└── editor.scss (estilos só do editor)A referência de metadados de blocos usa "apiVersion": 3 no seu exemplo. Convém saber onde termina a validação do block.json. A referência de atributos diz que cada definição de atributo contém pelo menos um type ou um enum, além do sítio de onde o valor é lido. enum restringe o valor guardado. Não há maxLength, minimum nem maximum que o Gutenberg imponha por si:
{
"apiVersion": 3,
"name": "wppoland/product-comparison",
"attributes": {
"heading": { "type": "string", "default": "" },
"price": { "type": "number", "default": 0 },
"variant": {
"type": "string",
"enum": [ "primary", "secondary", "accent" ],
"default": "primary"
}
}
}Os limites de intervalo e de comprimento aplicam-se no componente de edição ou na validação REST ao guardar:
<RichText
tagName="h3"
value={ attributes.heading }
onChange={ ( heading ) => setAttributes( { heading: heading.slice( 0, 120 ) } ) }
/>A referência do @wordpress/scripts cobre o resto da toolchain com uma única dependência. build produz um bundle de produção e start recompila a cada alteração. lint-js e lint-style aplicam as normas de código do WordPress a scripts e folhas de estilo. test-e2e corre testes end-to-end com Playwright, e plugin-zip empacota o plugin. O mesmo pacote deteta os ficheiros block.json na pasta de código-fonte e usa-os como pontos de entrada, pelo que uma nova pasta de bloco não exige nenhuma alteração ao webpack.
Como usar o Storybook para componentes de UI do Gutenberg
O próprio projeto Gutenberg documenta os seus componentes de UI no Storybook. O README da pasta storybook no repositório do Gutenberg afirma que o projeto “usa o Storybook para visualizar e trabalhar com os componentes de UI desenvolvidos nos pacotes do WordPress” (tradução própria), publica o resultado em wordpress.github.io/gutenberg e corre-o localmente com npm run storybook:dev a partir da raiz do repositório.
Há duas práticas desse README que funcionam bem num sistema de design para um cliente. Cada página de componente declara um estado (recommended, use-with-caution, not-recommended ou unaudited) que aparece na barra lateral, para que os programadores vejam em que componentes podem confiar. E o repositório guarda em commit um snapshot do manifesto de todos os componentes e das suas props: um pull request que remova a descrição de uma prop falha até alguém confirmar a alteração.
O Storybook não cobre a camada de conteúdo. Padrões, presets do theme.json e estilos de secção são renderizados dentro do editor de blocos, por isso a pré-visualização fiável para eles é uma página num site de staging que insere todos os padrões, editada com uma conta de editor. O Storybook serve para as partes React do sistema: os componentes edit dos blocos personalizados e quaisquer controlos partilhados da barra lateral construídos com @wordpress/components, que é a biblioteca que o Storybook público documenta.
Como passar tokens do Figma para o theme.json
Não existe sincronização oficial entre o Figma e o WordPress. O core não lê ficheiros do Figma, e nenhum plugin do Figma escreve sozinho num site em produção. O que se pode construir é um passo de build: os tokens saem da ferramenta de design em JSON e um script escreve-os no theme.json, que é o que o deploy entrega.
Os nomes quase nunca coincidem à partida, por isso esse mapeamento é código que alguém mantém. Um fluxo que aguenta o uso real:
- O designer altera uma cor no Figma.
- Um plugin de tokens exporta os tokens atualizados em JSON.
- O CI corre o script de build, que reescreve
settings.color.palettenotheme.json. - Os testes de regressão visual comparam capturas de ecrã antes e depois.
- Uma pessoa lê o diff do
theme.jsone aprova o pull request.
Pare a automação no quinto passo. Um webhook que faz deploy para produção sem que ninguém leia o diff é uma demonstração, não um sistema. Uma cor da marca é precisamente o tipo de alteração que merece revisão humana.
| Ferramenta | Função | O que ainda tem de escrever |
|---|---|---|
| Tokens Studio for Figma | Exporta tokens para JSON | O mapeamento desse JSON para as settings do theme.json |
| Style Dictionary | Transforma tokens entre plataformas | Um formato de saída próprio para o theme.json |
| GitHub Actions | Corre o build e abre o pull request | O passo de revisão antes do merge |
| Playwright | Comparação visual | As rotas e os estados que são capturados |
A documentação pode sair quase de graça a partir de material que já existe: uma página no site que insere todos os padrões da biblioteca, o histórico Git de /patterns e do theme.json como registo de alterações, e as capturas dos testes visuais como registo do antes e depois.
Como verificar a acessibilidade num sistema de design WordPress
Nada disto é feito pelo WordPress por si. São verificações que se constroem à volta do tema.
A paleta é uma lista curta de valores hex num ficheiro JSON, por isso o contraste pode ser verificado no build. Um teste percorre os pares permitidos de texto e fundo, calcula o rácio WCAG e faz falhar o build quando um par fica abaixo de 4.5:1 para texto normal. Identifica a combinação problemática pelo slug, não pelo hex, para que a correção seja feita no theme.json. O editor de blocos já avisa no inspetor quando uma combinação de cores escolhida tem pouco contraste, mas esse aviso não impede a publicação. Os estilos de secção ajudam aqui: quando o par de fundo e texto é definido uma vez num estilo de secção, é testado uma vez.
No CI, corra o axe-core sobre os templates principais e sobre cada variação de estilo publicada, e acrescente testes de navegação por teclado para os padrões que contêm elementos interativos. Tenha presente o limite: as ferramentas automáticas só apanham parte dos critérios WCAG. O resto continua a ser uma revisão manual com teclado e leitor de ecrã.
Como os assets de blocos carregam a pedido num block theme
Um sistema de design mal construído pode ser mais lento do que um site feito à mão, porque cada padrão arrasta consigo o seu CSS. O core ajuda, se o deixar. Em _add_default_theme_supports(), que corre para block themes, o WordPress acrescenta should_load_separate_core_block_assets e should_load_block_assets_on_demand como filtros __return_true (ver wp-includes/theme.php no wordpress-develop). O docblock em script-loader.php descreve o efeito: os assets de um bloco só carregam quando o bloco é renderizado. Um tema clássico ativa este comportamento com:
add_filter( 'should_load_separate_core_block_assets', '__return_true' );Uma página sem galeria deixa então de carregar o CSS da galeria. Para blocos personalizados, a regra prática decorre daqui: declare style, editorStyle, viewScript ou viewScriptModule no block.json em vez de carregar ficheiros globalmente a partir do functions.php, para que o WordPress os carregue apenas onde o bloco aparece. O que o WordPress não faz é gerar CSS crítico nem remover regras não usadas. Isso continua a ser tarefa do seu build ou de uma camada de cache.
Os orçamentos por componente são uma decisão da equipa, não uma medição do core, e só funcionam se alguém os verificar em cada pull request. A vitória mais barata é muitas vezes não precisar de script nenhum: um acordeão de FAQ construído sobre o bloco Details produz <details> e <summary>, que abrem e fecham sem JavaScript e funcionam com o teclado.
Checklist de um sistema de design WordPress escalável
Nos projetos de desenvolvimento WordPress, a sequência é sempre a mesma:
- Tokens no
theme.jsonversão 3, seletor bloqueado, paleta do core escondida. - Estilos de secção para os pares de fundo e texto, para que os editores deixem de colorir Groups à mão.
- Um conjunto curto de padrões em
/patternspara os layouts que o marketing realmente repete. - Um ou dois padrões sincronizados para o texto que pertence ao jurídico, exportados com a sincronização de conteúdo e nunca deixados como “logo recriamos isto em produção”.
- Blocos personalizados só depois de um padrão com blocos core ter falhado perante uma restrição real de atributos.
- Uma revisão no Editor do site com uma conta de editor, não de administrador, porque os administradores continuam a ver ferramentas que julgava ter escondido.
Se o front-end já usa CSS utilitário, mantenha o theme.json como fonte dos tokens e mapeie os slugs para esse CSS. Descrevemos essa divisão para o Tailwind em Tailwind CSS no desenvolvimento WordPress. O Gutenberg não quer saber que framework CSS consome --wp--preset--color--primary. Quer que o editor e o front-end usem o mesmo slug.
O sistema está a funcionar quando uma nova landing page é a inserção de um padrão, o seletor de cores tem oito amostras e um pedido de “só este laranja” é um pull request ao theme.json, não um hex num bloco Group.
Está a planear um sistema de design em WordPress? Escreva-nos.






