
🔘 Shortcode de botão no WordPress: código PHP pronto a usar e CSS moderno 2026
Precisa de um botão «Download» no meio de um artigo, mas o seu tema só mostra uma ligação azul sublinhada. Parece-lhe familiar? No Editor de Blocos, um botão é adicionado com um clique, mas no editor clássico, nos widgets e nos temas personalizados tem de escrever HTML com classes manualmente de cada vez.
Copiar marcação de artigo para artigo acaba de forma previsível: esquece-se de uma classe num sítio, perde rel="noopener" noutro, e o botão aparece de repente com um tom diferente num terceiro. Quanto mais conteúdo o seu site tiver, mais cara se torna cada alteração de estilo.
A solução demora cerca de dez minutos. Abaixo encontra um shortcode PHP [button] pronto a usar, uma paleta OKLCH, suporte para tema escuro via light-dark() e acessibilidade WCAG 2.2. Tudo foi testado nos navegadores atuais de 2026.
Como adicionar um botão via shortcode: plano de ação
💡 Visão geral rápida:
- Passo 1: Adicione a função PHP do botão ao
functions.phpdo seu tema filho - Passo 2: Registe a tag
[button]comadd_shortcode()no hookinit - Passo 3: Inclua CSS com todos os estados: normal, hover, active, focus
- Passo 4: Defina esquemas de cor com uma única linha OKLCH por cor
- Passo 5: Insira
[button url="..." color="blue"]Text[/button]num artigo e teste o foco de teclado
Cada passo abaixo inclui código pronto a copiar. Coloque o código num tema filho para que a atualização do tema principal não apague as suas alterações. Se ainda não tem um tema filho, crie um primeiro usando o guia oficial do WordPress para temas filho; demora apenas alguns minutos.
Mas antes de copiar, veja o que mudou no estilo dos botões em si. Nos últimos anos, o CSS para botões foi quase completamente reescrito.
O que mudou no CSS dos botões até 2026
Em resumo: já não se constroem botões com prefixos de fabricante e três conjuntos de tons de hover escolhidos manualmente. As propriedades personalizadas, o aninhamento nativo, o modelo de cor OKLCH e a função light-dark() reduzem um bloco de estilo típico praticamente a metade e eliminam a duplicação.
Estas técnicas aplicam-se a uma escala enorme. De acordo com os dados do W3Techs de julho de 2026, o WordPress alimenta 41,5% de todos os websites e detém 59,2% do mercado de CMS. Qualquer padrão deste artigo pode ser transportado de projeto para projeto durante anos.
Técnica | Como se fazia antes | Como se faz em 2026 |
|---|---|---|
Cor | HEX mais tons manuais para hover e active |
|
Paleta | Nove regras CSS por cor | Uma linha a sobrescrever |
Prefixos |
| Não são necessários: as propriedades estão padronizadas há muito |
Aninhamento | Apenas via Sass ou Less | Aninhamento nativo de CSS |
Foco |
|
|
Tema escuro | Folha de estilos separada |
|
Vamos começar pelo lado do servidor: enquanto não tivermos uma função PHP, não há nada para estilizar.
Função PHP do botão
A função aceita atributos do editor e devolve uma tag <a> pronta a usar, com classes, uma ligação e texto. Os shortcodes surgiram no WordPress 2.5 e continuam a ser a forma mais rápida de inserir marcação arbitrária no conteúdo: o add_shortcode() da referência oficial regista a tag, e uma função de callback monta o HTML.
1 /** 2 * Generates button HTML via the [button] shortcode. 3 * 4 * @param array|string $atts Shortcode attributes. 5 * @param string|null $content Text inside the paired [button]...[/button] tag. 6 * @return string Button HTML markup. 7 */ 8 function myprefix_button_shortcode( $atts, $content = null ) { 9 $atts = shortcode_atts( 10 array( 11 'url' => '', 12 'title' => '', 13 'target' => '', 14 'text' => '', 15 'color' => 'green', 16 ), 17 $atts, 18 'button' 19 ); 20 21 // Button text: text attribute takes priority, then tag content 22 $label = $atts['text'] ? $atts['text'] : $content; 23 24 // URL provided: build <a> 25 if ( $atts['url'] ) { 26 $target_attr = ( 'blank' === $atts['target'] ) ? ' target="_blank" rel="noopener noreferrer"' : ''; 27 $title_attr = $atts['title'] ? ' title="' . esc_attr( $atts['title'] ) . '"' : ''; 28 29 return sprintf( 30 '<a href="%s" class="myprefix-button color-%s"%s%s>%s</a>', 31 esc_url( $atts['url'] ), 32 esc_attr( $atts['color'] ), 33 $target_attr, 34 $title_attr, 35 do_shortcode( $label ) 36 ); 37 } 38 39 // No URL: wrap in <span> 40 return sprintf( 41 '<span class="myprefix-button color-%s">%s</span>', 42 esc_attr( $atts['color'] ), 43 do_shortcode( $label ) 44 ); 45 }
Note três detalhes. O shortcode_atts() combina os atributos fornecidos com os valores predefinidos, pelo que não há extract() nem variáveis não declaradas no escopo. Todos os valores dinâmicos passam por esc_url() e esc_attr(): o WordPress não escapa a saída do shortcode por si. E o do_shortcode() dentro do rótulo permite aninhar um shortcode dentro de outro (por exemplo, um ícone dentro do botão).
Registar o shortcode e usá-lo no editor
O registo é feito no hook init: nessa altura o núcleo está totalmente carregado e outros plugins podem sobrescrever a tag via remove_shortcode(), se necessário.
1 add_action( 'init', 'myprefix_register_button_shortcode' ); 2 3 function myprefix_register_button_shortcode() { 4 add_shortcode( 'button', 'myprefix_button_shortcode' ); 5 }
Agora abra um artigo e insira a tag. No editor clássico, coloque-a diretamente no texto; no Editor de Blocos, use o bloco «Shortcode»:
1 [button url="https://example.com/download" target="blank" text="Download free"] 2 3 [button url="https://example.com" color="blue"]Learn more[/button]
A primeira variante é de fecho automático, com o texto num atributo. A segunda é emparelhada: o rótulo fica entre as tags de abertura e fecho. O resultado é idêntico; escolha a sintaxe que for mais conveniente para os seus autores.
Sem estilos, o botão continua a parecer uma ligação comum. No entanto, a mecânica já funciona: a classe myprefix-button color-green está na marcação, e só falta estilizá-la.
Estilos base: propriedades personalizadas e aninhamento
Toda a aparência assenta numa única variável, --btn-bg. O color-mix() calcula os tons para hover e active a partir dela, pelo que já não precisa de escolher variantes mais escuras manualmente. As regras aninhadas funcionam de forma nativa, sem Sass.
1 .myprefix-button { 2 --btn-bg: oklch(58% 0.15 145); 3 --btn-fg: #fff; 4 5 display: inline-block; 6 padding: 12px 24px; 7 background: var(--btn-bg); 8 color: var(--btn-fg); 9 font-weight: 600; 10 text-decoration: none; 11 border-radius: 8px; 12 cursor: pointer; 13 transition: background 0.2s ease, translate 0.15s ease; 14 15 &:hover { 16 background: color-mix(in oklch, var(--btn-bg), black 12%); 17 color: var(--btn-fg); 18 text-decoration: none; 19 } 20 21 &:active { 22 background: color-mix(in oklch, var(--btn-bg), black 20%); 23 translate: 0 1px; 24 } 25 26 &:focus-visible { 27 outline: 3px solid color-mix(in oklch, var(--btn-bg), white 30%); 28 outline-offset: 2px; 29 } 30 }
O deslocamento translate: 0 1px no estado ativo simula o pressionar de um botão físico de forma mais subtil do que a antiga técnica de sombra interior. A transition define a suavidade, e a cor do texto é repetida explicitamente no :hover para que os estilos do tema não a substituam.
Copie o bloco para o style.css do seu tema filho ou para a secção "CSS adicional" do Personalizador. Agora a parte divertida: os esquemas de cores.
Paleta OKLCH: uma nova cor numa linha
Cada esquema ocupa agora exatamente uma linha: apenas a variável muda, e todos os estados são recalculados automaticamente.
1 .myprefix-button.color-blue { --btn-bg: oklch(55% 0.17 255); } 2 .myprefix-button.color-red { --btn-bg: oklch(55% 0.19 25); } 3 .myprefix-button.color-orange { --btn-bg: oklch(68% 0.16 60); }
Porquê OKLCH em vez do familiar HEX? Na descrição de oklch() na MDN, o primeiro parâmetro é a luminosidade percebida: duas cores com o mesmo primeiro número parecem igualmente brilhantes. Os botões azul e vermelho acima são visualmente equivalentes; o HEX não oferece essa garantia. Criar novos esquemas é fácil alterando apenas o terceiro parâmetro (matiz).
A utilização no editor permanece igual: color="red" ativa o esquema vermelho, color="orange" o laranja. O atributo predefinido continua a ser verde, como na função original.

Acessibilidade: o que falha com mais frequência
A resposta direta: um botão precisa de um anel de foco visível, um tamanho de alvo suficiente e respeito pelas preferências de animação. Estes não são requisitos de checklist. Uma auditoria a 17,2 milhões de sites no Web Almanac 2025 mostrou que 67% dos sites removem o contorno de foco e apenas 30% cumprem os padrões de contraste das WCAG.
O quadro legal também se tornou mais rigoroso: a partir de 28 de junho de 2025, aplica-se o European Accessibility Act, e os requisitos de acessibilidade para produtos digitais na UE são agora uma norma legal e não uma recomendação.
O critério 2.5.8 Tamanho do Alvo (Mínimo) de nível AA das WCAG 2.2 exige que um alvo interativo meça pelo menos 24 por 24 píxeis CSS ou tenha um espaço livre equivalente à sua volta.
O nosso botão com padding: 12px 24px cumpre o mínimo com folga, mas vale a pena adicionar duas regras em separado:
1 .myprefix-button { 2 min-block-size: 44px; 3 align-content: center; 4 } 5 6 @media (prefers-reduced-motion: reduce) { 7 .myprefix-button { 8 transition: none; 9 } 10 }
A primeira regra eleva a altura para uma zona de toque confortável em dispositivos móveis, onde toques falhados em alvos pequenos são especialmente frustrantes. A segunda desativa as animações para pessoas que o solicitaram nas definições do sistema. Já definimos o anel de foco através de :focus-visible: ele aparece durante a navegação por teclado e não incomoda os utilizadores de rato.

Tema escuro via light-dark()
Uma única função substitui toda a media query prefers-color-scheme. Especifica dois valores (claro e escuro), e o navegador escolhe o correto com base no esquema ativo. De acordo com a MDN, a função light-dark() tem o estado Baseline Recently available desde maio de 2024, o que significa que funciona em todos os navegadores atuais.
1 :root { 2 color-scheme: light dark; 3 } 4 5 .myprefix-button { 6 --btn-bg: light-dark(oklch(58% 0.15 145), oklch(70% 0.13 145)); 7 --btn-fg: light-dark(#fff, oklch(22% 0.02 145)); 8 }
A linha color-scheme: light dark é obrigatória: sem ela, a função não será ativada. Para o esquema escuro, o fundo é tornado mais claro e o texto mais escuro: numa tela escura, botões escuros saturados afundam-se, um erro comum. Uma análise detalhada da tematização com todas as armadilhas está disponível no artigo do web.dev sobre temas de cor.
Se o seu público usar navegadores corporativos antigos, envolva as novas funcionalidades em @supports e mantenha HEX simples como fallback: o botão degrada-se com elegância, perdendo apenas a precisão da tonalidade.
Segurança: três linhas que as pessoas esquecem
Antes de mais: target="_blank" sem rel="noopener noreferrer" abre uma vulnerabilidade de tabnabbing. A página para a qual o botão aponta ganha acesso a window.opener e pode substituir o separador que contém o seu site. Na nossa função, o atributo é adicionado automaticamente, mas é fácil perdê-lo durante modificações.
O escape é igualmente importante. esc_url() bloqueia protocolos perigosos como javascript:, e esc_attr() impede a quebra de um atributo. Estas chamadas nunca devem ser removidas por brevidade em qualquer shortcode que aceite dados do editor.
Um último ponto: $content não é passado intencionalmente por wp_kses_post() para que shortcodes aninhados funcionem. No entanto, se permitir que botões sejam inseridos através de formulários de front-end, envolva $label em wp_kses_post() antes da saída.
Como testar um botão antes de publicar
Um teste rápido demora alguns minutos e deteta quase todos os problemas que os utilizadores reportam mais tarde. Percorra esta lista antes de colocar o botão em artigos de produção:
- Clique no botão com um rato e verifique se o link abre no separador correto.
- Navegue pela página com a tecla Tab: o anel de foco deve ser óbvio à primeira vista.
- Ative a emulação de esquema escuro nas DevTools (painel Rendering, opção prefers-color-scheme) e verifique ambas as variantes de fundo.
- Ative a emulação de prefers-reduced-motion no mesmo painel e confirme que o botão para de animar.
- Abra a página em modo móvel e tente tocar no botão com o polegar.
Se tudo passar, o shortcode está pronto para uso em massa. Crie o hábito de percorrer esta lista após cada alteração de estilo: regressões nos estados de foco e no tema escuro são invisíveis até que as procure especificamente. As perguntas mais comuns sobre o comportamento do shortcode estão reunidas abaixo.
⁉️🤔 Perguntas frequentes
Este shortcode funciona no Editor de Blocos?
Sim, totalmente. Insira um bloco «Shortcode» e escreva
[button ...]dentro dele. O markup é montado no servidor quando o artigo é renderizado, por isso o editor não se importa como a tag chegou ao conteúdo. Para elementos usados com frequência, acaba por fazer sentido registar um bloco nativo viaregister_block_type(), mas isso é um projeto separado.
E se o navegador de um visitante não entender oklch() ou light-dark()?
Envolva os valores modernos numa diretiva
@supportse mantenha HEX simples como valor padrão. Um navegador antigo aplicará a cor de fallback; um novo usará OKLCH. O botão permanece funcional em ambos os casos: a degradação graciosa afeta apenas a precisão da tonalidade e a automatização do tema escuro, não a funcionalidade.
Porque é que o shortcode aparece na página como texto entre parênteses retos?
Na maioria das vezes, a função não está registada: verifique se o
functions.phpfoi guardado sem erros de sintaxe e se o hookinitfoi executado. Uma segunda possibilidade: inseriu a tag num ficheiro de template, onde precisa de uma chamada explícitaecho do_shortcode( '[button ...]' ). Ative oWP_DEBUGe verifique o registo de erros.
Como adiciono um ícone dentro do botão?
A via mais rápida: um emoji diretamente no texto, por exemplo
text="📥 Download". Para SVG, passe o URL do ficheiro como um atributo separado e produza uma tag<img>dentro do link através do mesmosprintf. A abordagem Dashicons também funciona: um pseudo-elemento::beforemaisfont-family: dashiconsnuma classe dedicada.
Os prefixos de vendor para border-radius e transition ainda são necessários em 2026?
Não. Estas propriedades estão padronizadas há muito e funcionam em todos os navegadores atuais sem prefixos. Verifique o suporte para uma funcionalidade específica nas tabelas da MDN ou no caniuse.com, que também mostram o estado Baseline indicando quando uma funcionalidade pode ser usada sem fallbacks.
💎 Resumo e conclusões
Para um site que precisa apenas de alguns botões padrão, um shortcode personalizado supera qualquer plugin: controlo total sobre o markup, zero scripts extra na fila de carregamento e nenhuma dependência para manter atualizada. Um construtor visual com dezenas de estilos prontos é necessário com menos frequência do que parece, mas se realmente precisar de um, veja o MaxButtons no diretório wordpress.org.
Dica prática: comece a implementação com a linha color-scheme: light dark em :root e variáveis via light-dark(). Esta é a forma mais barata de obter um tema escuro adequado, e compensa para cada elemento de IU subsequente. E uma armadilha para terminar: não teste o botão apenas com um rato. Navegue pela página com a tecla Tab e verifique se o anel de foco está visível; caso contrário, alguns visitantes simplesmente não encontrarão o seu botão.
Pegue no código, cole-o no seu tema filho e teste o botão no seu site hoje. Funcionou ou encontrou um conflito com o seu tema? Partilhe nos comentários, e resolveremos juntos. E subscreva para atualizações do blog: estão a caminho mais análises úteis de shortcodes.



