WebP no WordPress: como trocar JPG e PNG sem quebrar o site
Passo a passo para usar WebP no WordPress: plugin, linha de comando, regras de servidor e WP-CLI, com testes, plano de volta e correção dos erros mais comuns.
Você sabe HTML, CSS e um pouco de JavaScript. Já fez sites bonitos e sabe que, na hora de entregar para um cliente, existe um problema: ele quer editar textos, trocar fotos e publicar novidades sem mexer em código. É aí que o WordPress entra, e é aí que muita gente trava, porque a maioria dos tutoriais ensina a instalar um tema pronto e parar por ali.
A boa notícia: criar um tema WordPress do zero é bem menos assustador do que parece. Um tema nada mais é do que uma pasta com arquivos PHP, um CSS e algumas funções que o WordPress já oferece prontas. Se você domina HTML e CSS, já tem mais da metade do caminho andado.
Neste guia, você vai sair de um site estático e chegar a um tema funcional, com cabeçalho, rodapé, lista de posts, página única, menu editável pelo painel e sidebar. Além de ensinar o passo a passo, explico o motivo de cada decisão, porque é isso que separa quem copia código de quem consegue resolver os problemas que aparecem depois.
Não é preciso saber PHP. Todo o PHP deste artigo é copiável e vem explicado linha a linha. O que você precisa ter é:
Se você nunca configurou um servidor local, não se preocupe: a próxima seção cobre isso.
Antes de abrir o editor, vale entender quando essa escolha faz sentido. Nem todo projeto precisa de um tema próprio, e saber a diferença economiza tempo e dinheiro.
| Situação | Melhor caminho |
|---|---|
| Blog pessoal simples, sem identidade visual definida | Tema pronto, ajustado com o personalizador |
| Site institucional com design já aprovado | Tema do zero, seguindo o layout |
| Site que precisa de alta performance e SEO técnico | Tema do zero, enxuto e sem código sobrando |
| Projeto com regras de negócio específicas | Tema do zero, com plugin próprio quando necessário |
| Prazo curto e orçamento mínimo | Tema pronto e bem configurado |
O problema dos temas prontos multiuso é que eles carregam dezenas de recursos que você nunca vai usar: scripts, estilos, fontes e módulos que pesam na página. Um tema sob medida carrega só o que o projeto precisa, o que ajuda diretamente na performance web e nas métricas de velocidade. Se o seu site já está lento, vale conferir também as causas mais comuns de um WordPress lento.
Pense no WordPress em duas camadas. A primeira é o núcleo: o código que gerencia banco de dados, usuários, permissões e conteúdo. A segunda é o tema: a camada que decide como esse conteúdo aparece na tela.
O núcleo você nunca edita. Tudo o que você personaliza fica dentro da pasta wp-content, e o tema mora em wp-content/themes/. O WordPress lê essa pasta, encontra o seu tema e passa a usar os arquivos dele para montar cada página.
Um tema clássico precisa de apenas dois arquivos para existir:
style.css: traz as informações do tema no topo e também pode guardar o CSS.index.php: o modelo padrão, usado quando nenhum outro modelo mais específico existe.Todo o resto é organização e recurso extra. Isso vale para temas clássicos. Existe também o modelo de tema em blocos (com theme.json e edição completa do site), disponível desde o WordPress 5.9. Neste guia, o foco é o tema clássico em PHP, que continua amplamente usado e é a melhor forma de entender como o WordPress funciona por baixo.
Desenvolver direto em um site no ar é pedir problema. Qualquer erro de PHP pode derrubar a página para os visitantes. Por isso, o primeiro passo é montar um ambiente local.
Você tem algumas opções:
Se escolher o caminho manual (XAMPP ou MAMP), o processo é este:
wp_tema.wp-config-sample.php e renomeie a cópia para wp-config.php.https://api.wordpress.org/secret-key/1.1/salt/.Enquanto desenvolve, ative o modo de depuração para ver os erros na tela. No wp-config.php, localize a linha de WP_DEBUG e deixe assim:
define( 'WP_DEBUG', true );
Nunca deixe isso ligado em um site em produção. Em ambiente local, ele é seu melhor amigo: mostra exatamente onde o erro está em vez de uma tela branca misteriosa. Para entender melhor o que existe nesse arquivo, veja o glossário sobre o wp-config.
Depois da instalação, entre em Configurações > Links permanentes e escolha Nome do post. É uma configuração que deixa as URLs limpas e amigáveis, algo importante também para o SEO.
Abra wp-content/themes/ e crie uma pasta com o nome do seu tema. Vou usar meu-tema. Dentro dela, crie o style.css com este cabeçalho:
/*
Theme Name: Meu Tema
Theme URI: https://seusite.com.br
Author: Seu Nome
Description: Tema personalizado criado do zero
Version: 1.0.0
Text Domain: meu-tema
*/
Esse comentário não é decoração. É assim que o WordPress identifica o tema e mostra nome, autor e descrição no painel. Sem ele, o tema não aparece na lista.
Agora crie um index.php vazio, por enquanto. Entre em Aparência > Temas no painel e você verá o “Meu Tema” disponível. Ative-o.
Neste momento, o site vai aparecer em branco, e está tudo certo. O tema existe, só não tem conteúdo ainda. Vamos construir isso agora.
Aqui está a primeira armadilha de quem vem do HTML puro. Em um site estático, você escreve <link href="style.css"> e pronto. No WordPress, o caminho relativo não funciona, porque a URL do site não é a mesma da pasta do tema.
A forma correta de carregar estilos e scripts é registrá-los em um arquivo chamado functions.php, usando as funções oficiais do WordPress. Crie esse arquivo na pasta do tema:
<?php
// Configurações iniciais do tema
function meutema_configurar() {
// Deixa o WordPress gerar a tag <title> automaticamente
add_theme_support( 'title-tag' );
// Habilita imagem destacada nos posts e páginas
add_theme_support( 'post-thumbnails' );
// Gera HTML5 semântico em formulários e comentários
add_theme_support( 'html5', array(
'search-form',
'comment-form',
'comment-list',
'gallery',
'caption',
) );
// Registra um local de menu
register_nav_menus( array(
'principal' => 'Menu principal',
) );
}
add_action( 'after_setup_theme', 'meutema_configurar' );
// Carrega CSS e JS do tema
function meutema_carregar_arquivos() {
wp_enqueue_style(
'meutema-estilo',
get_stylesheet_uri(),
array(),
wp_get_theme()->get( 'Version' )
);
}
add_action( 'wp_enqueue_scripts', 'meutema_carregar_arquivos' );
Vamos entender o que acontece aqui:
add_action é o mecanismo de “ganchos” do WordPress. Você diz: “quando acontecer tal momento, execute minha função”.add_theme_support( 'title-tag' ) faz o WordPress cuidar da tag <title> de cada página. Você nunca mais precisa escrever isso na mão, e o SEO agradece.wp_enqueue_style registra o CSS. Ele evita carregar o mesmo arquivo duas vezes e permite que plugins e temas filhos convivam sem conflito.Para carregar um JavaScript, o raciocínio é igual, usando wp_enqueue_script. Isso é bem diferente de colar <script> direto no rodapé, e é a prática recomendada pela documentação oficial.
Em um HTML estático, tudo mora num único arquivo. Em um tema, repetir o mesmo cabeçalho em cada página seria um pesadelo. Por isso o WordPress usa arquivos separados que se encaixam, como peças de montar.
O cabeçalho contém tudo desde o <!DOCTYPE> até o menu de navegação:
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
<?php wp_body_open(); ?>
<header class="site-header">
<div class="container">
<a class="site-titulo" href="<?php echo esc_url( home_url( '/' ) ); ?>">
<?php bloginfo( 'name' ); ?>
</a>
<p class="site-descricao"><?php bloginfo( 'description' ); ?></p>
<nav class="menu-principal" aria-label="Menu principal">
<?php
wp_nav_menu( array(
'theme_location' => 'principal',
'container' => false,
) );
?>
</nav>
</div>
</header>
Os pontos que mais importam:
wp_head() precisa existir antes de </head>. É por ali que o WordPress e os plugins injetam CSS, scripts, tags de SEO e dados estruturados. Sem ele, metade dos plugins simplesmente não funciona.language_attributes() e bloginfo( 'charset' ) entregam o idioma e a codificação configurados no painel.body_class() adiciona classes automáticas no <body>, que facilitam estilizar páginas específicas.wp_nav_menu desenha o menu que o cliente edita em Aparência > Menus, sem tocar em código.O rodapé fecha a página e carrega o gancho final:
<footer class="site-footer">
<div class="container">
<p>
© <?php echo esc_html( date_i18n( 'Y' ) ); ?>
<?php bloginfo( 'name' ); ?>. Todos os direitos reservados.
</p>
</div>
</footer>
<?php wp_footer(); ?>
</body>
</html>
Assim como o wp_head(), o wp_footer() é obrigatório. É por ali que scripts e a barra de administração entram na página.
A sidebar guarda informações secundárias, como busca, arquivos e categorias:
<aside class="sidebar">
<h2>Buscar</h2>
<?php get_search_form(); ?>
<h2>Arquivos</h2>
<ul>
<?php wp_get_archives( array( 'type' => 'monthly' ) ); ?>
</ul>
</aside>
Repare que nada aqui é texto fixo. A busca e a lista de arquivos são geradas pelo WordPress com base no conteúdo real do site.
Aqui está o coração de qualquer tema WordPress. O The Loop (o “laço”) é o trecho de código que percorre os posts que o WordPress separou para aquela página e repete um bloco de HTML para cada um.
A lógica em português é simples: se existem posts, enquanto houver posts, mostre um por vez.
Substitua o conteúdo do index.php por:
<?php get_header(); ?>
<main class="container layout">
<section class="conteudo">
<?php if ( have_posts() ) : ?>
<?php while ( have_posts() ) : the_post(); ?>
<?php get_template_part( 'template-parts/content', get_post_type() ); ?>
<?php endwhile; ?>
<?php the_posts_pagination(); ?>
<?php else : ?>
<p>Nenhum conteúdo encontrado.</p>
<?php endif; ?>
</section>
<?php get_sidebar(); ?>
</main>
<?php get_footer(); ?>
Um detalhe importante: o Loop não sabe quais posts mostrar. Quem decide isso é o WordPress, com base na URL acessada. Na página inicial, ele separa os posts mais recentes. Em uma categoria, separa os daquela categoria. Em uma busca, separa os resultados. O mesmo código atende todos esses casos.
Agora crie a pasta template-parts dentro do tema e, nela, o arquivo content.php, que representa um único post na listagem:
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<h2>
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
</h2>
<p class="meta">
<time datetime="<?php echo esc_attr( get_the_date( 'c' ) ); ?>">
<?php echo esc_html( get_the_date() ); ?>
</time>
por <?php the_author(); ?>
</p>
<?php if ( has_post_thumbnail() ) : ?>
<?php the_post_thumbnail( 'large' ); ?>
<?php endif; ?>
<?php the_excerpt(); ?>
</article>
As funções de template começam com the_ quando imprimem o resultado na tela (the_title, the_content, the_permalink) e com get_ quando devolvem o valor para você usar em outra expressão (get_the_date, get_the_title). Guardar essa diferença evita muita dor de cabeça.
Quanto ao get_template_part( 'template-parts/content', get_post_type() ): ele procura primeiro por content-post.php e, se não achar, usa content.php. Isso permite criar versões diferentes para cada tipo de conteúdo no futuro, como um Custom Post Type de portfólio, sem mexer no index.php.
A listagem mostra só o resumo. Quando o visitante clica em um post, ele precisa ver o conteúdo completo. Para isso o WordPress procura um arquivo chamado single.php:
<?php get_header(); ?>
<main class="container layout">
<section class="conteudo">
<?php while ( have_posts() ) : the_post(); ?>
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<h1><?php the_title(); ?></h1>
<p class="meta">
<?php echo esc_html( get_the_date() ); ?>
por <?php the_author(); ?>
</p>
<?php the_content(); ?>
</article>
<?php comments_template(); ?>
<?php endwhile; ?>
</section>
<?php get_sidebar(); ?>
</main>
<?php get_footer(); ?>
Aproveite para notar o <h1>. Na listagem, cada título de post é um <h2>, porque a página tem outro foco. No post individual, o título passa a ser o <h1>, e só deve existir um por página. Isso é básico de SEO on-page e muita gente erra.
Para as páginas institucionais (Sobre, Contato, Serviços), crie o page.php. Ele é parecido com o single.php, mas sem data, autor e comentários, e normalmente sem a sidebar, para ocupar a largura toda:
<?php get_header(); ?>
<main class="container">
<?php while ( have_posts() ) : the_post(); ?>
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<h1><?php the_title(); ?></h1>
<?php the_content(); ?>
</article>
<?php endwhile; ?>
</main>
<?php get_footer(); ?>
Esse é um dos grandes poderes do WordPress: posts e páginas usam o mesmo mecanismo, mas podem ter layouts totalmente diferentes, porque cada um tem o seu arquivo.
Você acabou de usar, sem perceber, uma das ideias mais importantes do WordPress: a hierarquia de templates. Quando alguém acessa uma URL, o WordPress percorre uma lista de arquivos, do mais específico ao mais genérico, e usa o primeiro que existir na pasta do tema. Se nenhum específico for encontrado, ele cai no index.php.
| Arquivo | Quando é usado |
|---|---|
front-page.php | Página inicial do site |
home.php | Listagem de posts do blog |
single.php | Um post individual |
page.php | Uma página estática |
archive.php | Categorias, tags, autores e datas |
category.php | Somente listagem de categorias |
search.php | Resultados de busca |
404.php | Página não encontrada |
index.php | Fallback para qualquer caso sem arquivo próprio |
Na prática, você não precisa criar todos de uma vez. Comece pelo index.php, adicione single.php e page.php, e só crie os demais quando sentir necessidade de um layout diferente. Vale muito a pena criar um 404.php com uma mensagem útil e um link para a página inicial, porque ele impede que o visitante desista do site ao cair em um endereço quebrado. Se quiser entender melhor o assunto, veja o glossário sobre o erro 404.
A página oficial da hierarquia de templates traz o diagrama completo, e vale mantê-la nos favoritos.
Algumas partes do tema precisam ser editáveis pelo cliente, e o WordPress oferece três recursos principais para isso.
Menus. Você já registrou o local principal no functions.php. Agora, no painel, vá em Aparência > Menus, crie um menu, adicione páginas e associe ao local “Menu principal”. O wp_nav_menu do cabeçalho cuida do resto.
Widgets. Para que a sidebar aceite blocos editáveis, registre uma área de widgets no functions.php:
function meutema_areas_de_widgets() {
register_sidebar( array(
'name' => 'Sidebar principal',
'id' => 'sidebar-principal',
'before_widget' => '<section class="widget">',
'after_widget' => '</section>',
'before_title' => '<h2 class="widget-titulo">',
'after_title' => '</h2>',
) );
}
add_action( 'widgets_init', 'meutema_areas_de_widgets' );
E no sidebar.php, exiba os widgets quando houver algum ativo:
<aside class="sidebar">
<?php if ( is_active_sidebar( 'sidebar-principal' ) ) : ?>
<?php dynamic_sidebar( 'sidebar-principal' ); ?>
<?php else : ?>
<?php get_search_form(); ?>
<?php endif; ?>
</aside>
Imagem destacada. Como você habilitou o post-thumbnails, cada post ganha um campo de imagem destacada no editor, e o the_post_thumbnail() exibe a imagem no lugar certo.
Para o tema não ficar com cara de página crua, adicione este CSS ao final do style.css, logo abaixo do cabeçalho:
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
line-height: 1.6;
color: #222;
}
.container {
max-width: 1100px;
margin: 0 auto;
padding: 0 1rem;
}
.site-header {
background: #111;
color: #fff;
padding: 1.5rem 0;
}
.site-titulo {
color: #fff;
font-size: 1.5rem;
font-weight: 700;
text-decoration: none;
}
.menu-principal ul {
display: flex;
gap: 1rem;
list-style: none;
margin: 1rem 0 0;
padding: 0;
}
.menu-principal a {
color: #fff;
text-decoration: none;
}
.layout {
display: grid;
grid-template-columns: 1fr;
gap: 2rem;
padding-top: 2rem;
padding-bottom: 2rem;
}
@media (min-width: 800px) {
.layout {
grid-template-columns: 2fr 1fr;
}
}
.site-footer {
background: #f3f3f3;
padding: 1.5rem 0;
text-align: center;
}
img {
max-width: 100%;
height: auto;
}
O importante aqui é a base responsiva: uma coluna no celular e duas colunas em telas maiores. Se você quer entender o conceito por trás disso, veja o glossário sobre responsividade.
Um tema que funciona é diferente de um tema bem feito. Estes cuidados evitam dores de cabeça no futuro.
Sempre que for exibir um dado dinâmico dentro do HTML, use a função de escape certa:
esc_html() para texto comum.esc_url() para endereços e links.esc_attr() para valores dentro de atributos HTML.Isso protege contra ataques de injeção de código (XSS). As funções the_title() e the_content() já tratam isso internamente, mas qualquer valor que você buscar manualmente precisa de escape. A documentação oficial sobre escaping explica cada caso.
Use home_url(), get_template_directory_uri() e get_stylesheet_uri(). Se o site mudar de domínio, de localhost para produção, nada quebra.
Todas as funções do functions.php deste artigo começam com meutema_. Isso evita conflito com plugins e com o próprio WordPress, que tem milhares de funções com nomes comuns.
Se você personalizar um tema que não é seu, use um tema filho. Qualquer edição direta será apagada na próxima atualização.
Um tema bem construído já entrega boa parte do SEO técnico sem plugin:
<h1> por página, seguido de uma hierarquia lógica de <h2> e <h3>.<title> gerada pelo add_theme_support( 'title-tag' ).header, nav, main, article, aside, footer).Mesmo assim, plugins de SEO continuam úteis para meta descrições, sitemap e dados estruturados. O tema só precisa deixar o caminho livre, com o wp_head() no lugar.
Quando o tema estiver pronto no ambiente local, você tem alguns caminhos para colocá-lo no ar:
meu-tema em um arquivo .zip e enviar em Aparência > Temas > Adicionar novo > Enviar tema.wp-content/themes/ na hospedagem.Antes de ativar em um site com visitantes, teste em um ambiente de homologação. O staging permite validar tudo sem risco. Se o site já existe e você está trocando de tema, planeje também para não perder posicionamento: o artigo sobre migrar site WordPress sem perder SEO mostra o que conferir.
Use esta lista antes de entregar o projeto:
WP_DEBUG ligado.wp_head() e wp_footer() estão presentes.wp_enqueue_style e wp_enqueue_script.index.php, single.php, page.php e 404.php.<h1> por página.Não precisa ser especialista. Para um tema básico, basta entender a estrutura de abrir e fechar as tags do PHP e usar as funções prontas do WordPress, como as deste artigo. Com a prática, você vai aprendendo PHP naturalmente, conforme os projetos pedem mais recursos.
Um tema clássico exige apenas o style.css (com o cabeçalho de identificação) e o index.php. Na prática, convém ter também functions.php, header.php, footer.php, single.php e page.php para ter um tema completo e organizado.
the_content() e get_the_content()?A função the_content() imprime o conteúdo já formatado, aplicando filtros como parágrafos automáticos e blocos do editor. Já get_the_content() apenas devolve o texto bruto, sem esses filtros. Para exibir um post na tela, o correto é usar the_content().
O motivo mais comum é usar um caminho relativo, como <link href="style.css">. No WordPress, isso aponta para o endereço do site, e não para a pasta do tema. A solução é registrar o arquivo com wp_enqueue_style no functions.php, como mostrado no Passo 3.
É o trecho de código que percorre os posts selecionados para a página atual e repete um bloco de HTML para cada um. O WordPress decide quais posts entram no laço com base na URL, e o tema decide como cada um aparece.
Depende do projeto. Temas clássicos em PHP oferecem controle total e continuam muito usados, principalmente em sites sob medida. Temas em blocos, com o editor completo do site, são indicados quando o cliente precisa ajustar o layout visualmente. Para quem quer aprender como o WordPress funciona, começar pelo clássico dá uma base muito sólida.
Pode. Um tema leve e bem estruturado funciona muito bem com construtores visuais, desde que você deixe o the_content() no lugar correto. Só tenha em mente que o construtor adiciona peso à página, e isso precisa ser avaliado no projeto. Veja o que é o Elementor e quando ele compensa.
Sim. O processo é sempre o mesmo: separar o HTML em cabeçalho, conteúdo e rodapé, trocar textos fixos por funções do WordPress, carregar o CSS pelo functions.php e deixar o Loop montar a parte dinâmica. O design não importa, seja ele feito à mão ou com um framework.
O valor varia conforme a quantidade de layouts, integrações, tipos de conteúdo e campos personalizados. Um tema simples exige bem menos trabalho do que um site com portfólio, loja ou área de membros. O caminho mais seguro é fazer um levantamento do que o site precisa antes de qualquer orçamento fechado. Veja também como identificar se o orçamento do seu site está superfaturado.
Com a base pronta, o aprendizado continua em alguns caminhos naturais:
Vale lembrar também que o WordPress não é a resposta para todos os projetos. Em alguns cenários, uma stack sob medida entrega mais performance e controle. Para refletir sobre isso, leia o momento certo de sair do WordPress para uma stack sob medida.
Criar um tema WordPress do zero se resume a três ideias: dividir o layout em partes reutilizáveis (header.php, footer.php, sidebar.php), usar o Loop para exibir o conteúdo dinâmico e deixar o WordPress escolher o template certo pela hierarquia. O restante é refinamento: menus, widgets, imagem destacada, segurança, SEO e performance.
O ganho de dominar esse processo é grande. Você deixa de depender de temas prontos e passa a entregar sites leves, com a identidade do cliente e sem recursos sobrando. E, se o projeto crescer, a base que você construiu aguenta.
Se você prefere ter um tema sob medida, feito com performance, SEO técnico e edição simples para sua equipe, sem precisar aprender tudo isso agora, esse é exatamente o tipo de projeto que desenvolvo como desenvolvedor freelancer. E, se o seu site já existe e precisa de cuidado contínuo, conheça o serviço de manutenção de site WordPress.
WordPress Developer Resources. “Theme Handbook”. Documentação oficial para desenvolvimento de temas, cobrindo estrutura, templates e boas práticas.
WordPress Developer Resources. “Template Hierarchy”. Explica a ordem em que o WordPress escolhe os arquivos de template para cada tipo de página.
WordPress Developer Resources. “The Loop”. Detalha o funcionamento do laço principal e das funções de template relacionadas.
WordPress Developer Resources. “Escaping Data”. Guia oficial de segurança para escapar dados antes de exibi-los na página.
WordPress Developer Resources. “wp_enqueue_style()”. Referência da função usada para carregar folhas de estilo do jeito correto.