Estilizar um feed RSS com CSS: o que ainda funciona no Chrome
Uma folha CSS ligada a um feed continua funcionando no Chrome depois da remoção do XSLT, desde que o servidor envie o feed como application/xml ou text/xml. Enviado como application/rss+xml, o mesmo feed aparece como texto puro e o CSS é ignorado. Verificamos isso no Chromium 156 e em um site de teste com WordPress. A configuração tem três passos.
Dá para estilizar um feed RSS com CSS sem XSLT?
Sim, se o servidor enviar o feed com o tipo de conteúdo certo. O anúncio do Chrome sobre o XSLT diz que a instrução de processamento <?xml-stylesheet ... ?> continua aceitando folhas CSS, com type="text/css". Só o XSLT é removido, no Chrome 158, em 17 de novembro de 2026.
Isso afeta quem publica um feed que hoje usa uma folha XSL. O Chrome observa que muitos feeds RSS e Atom usam XSLT para ficar legíveis quando alguém abre o feed direto no navegador. A partir de 17 de novembro, esses feeds perdem o layout no Chrome. Uma folha CSS é a substituta mais leve: nada de transformação, só regras sobre a aparência de cada elemento.
Essa exigência sobre o tipo de conteúdo se deve ao jeito como o Chrome trata os tipos de mídia próprios de feeds. Um feed enviado como application/rss+xml ou application/atom+xml abre como texto puro no Chrome, e texto puro não recebe nenhuma folha de estilo, nem CSS nem XSL. Nosso guia sobre feed RSS que aparece como texto explica esse comportamento e o que o visitante pode fazer.
Para estilizar um feed RSS com CSS, você precisa de duas coisas: a linha da folha de estilo no arquivo e um servidor que o envie como application/xml ou text/xml. Se hoje o seu feed aparece formatado pelo XSL no Chrome, o seu servidor já envia um desses tipos, e só a linha da folha de estilo precisa mudar.
Com qual tipo de conteúdo o Chrome aplica CSS a um feed?
Com application/xml ou text/xml. Em 14 de outubro de 2026, abrimos no Chromium 156 dois feeds pequenos, um Atom e um RSS, hospedados em um servidor local. Os dois começavam com esta linha, logo depois da declaração XML:
<?xml-stylesheet type="text/css" href="/feed.css"?>
A folha de teste transformava cada elemento title em um título vermelho de 28 pixels e escondia os outros elementos, para que pudéssemos conferir o resultado no estilo computado de cada elemento. Testamos cada caso duas vezes: com o XSLT do Chromium ativado e depois desativado, como vai ficar no Chrome 158. Os resultados foram os mesmos.
| Feed | Tipo enviado pelo servidor | O que o Chromium mostrou |
|---|---|---|
| Atom | application/xml |
CSS aplicado: títulos em vermelho |
| Atom | text/xml |
CSS aplicado |
| RSS | application/xml |
CSS aplicado |
| RSS | text/xml |
CSS aplicado |
| Atom | application/atom+xml |
Texto puro do feed, CSS ignorado |
| RSS | application/rss+xml |
Texto puro do feed, CSS ignorado |
Nos casos de texto puro, a página mostrava o código-fonte do feed do jeito que foi enviado, em fonte monoespaçada, incluindo a linha da folha de estilo. Nos casos estilizados, o Chrome não mostrava nenhuma mensagem acima do conteúdo. Os elementos escondidos, como id e updated, sumiram da tela, mas continuavam no documento.
Sem a linha da folha de estilo, o mesmo feed RSS enviado como application/xml apareceu na visualização em árvore do Chrome, abaixo da mensagem “no style information” (sem informações de estilo), explicada na nossa página sobre a árvore XML do Chrome. Um feed ligado a uma folha XSL mostra outra mensagem quando o XSLT está desativado: “This document cannot be formatted as intended” (o documento não pode ser formatado como previsto).
Como ligar uma folha CSS a um feed?
Em três passos.
1. Adicione a instrução de processamento. A recomendação do W3C “Associating Style Sheets with XML documents” define essa instrução. Ela precisa ficar no prólogo, ou seja, logo depois de <?xml version="1.0"?> e antes do elemento raiz, <rss> ou <feed>. O pseudoatributo href é obrigatório. Os outros são opcionais: type, title, media, charset e alternate. Um feed RSS completo com a linha da folha de estilo fica assim:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/feed.css"?>
<rss version="2.0">
<channel>
<title>Blog de exemplo</title>
<link>https://example.com/</link>
<description>Últimos artigos</description>
<item>
<title>Primeiro artigo</title>
<link>https://example.com/primeiro/</link>
</item>
</channel>
</rss>
2. Escreva o CSS. No CSS, o valor inicial de display é inline, segundo a MDN. Um feed não tem estilos padrão de HTML: sem regras próprias, todos os elementos se juntam em uma linha só. Comece transformando os contêineres em blocos:
rss, channel, item, feed, entry { display: block; }
title { display: block; font-size: 1.4em; margin: 1em 0 0.3em; }
link, guid, id, updated, pubDate { display: none; }
Também testamos essa folha: em um feed RSS, os títulos ficaram com 1,4 vez o tamanho base e os links foram escondidos. No RSS, o canal e cada item têm o próprio elemento title. Para dar um estilo diferente a cada um, use channel > title e item > title, ou feed > title e entry > title no Atom. Um seletor title simples também se aplica aos títulos de um feed Atom, embora esses elementos pertençam ao namespace do Atom: segundo a especificação Selectors do W3C, quando a folha CSS não declara um namespace padrão, um seletor de tipo vale para elementos de qualquer namespace.
3. Envie o tipo de conteúdo certo. A lista de tipos MIME comuns da MDN recomenda application/xml para XML e observa que text/xml ainda é usado às vezes, então prefira application/xml. O serviço de validação de feeds do W3C vai avisar que esse tipo é genérico demais para que todos os programas reconheçam ali um feed. Quando não dá para usar um tipo mais específico, o validador pede que <rss ou <feed apareça nos primeiros 512 bytes, e um feed que começa com as duas linhas acima atende a essa exigência.
No WordPress, dois hooks fazem as duas mudanças. A função feed_content_type() devolve application/rss+xml para RSS e application/atom+xml para Atom, a menos que um filtro mude isso, e a ação rss_tag_pre é disparada entre a declaração XML e o elemento raiz. Este código, salvo como arquivo PHP em wp-content/mu-plugins/, a pasta dos plugins obrigatórios (must-use), funcionou em um site de teste com WordPress 7.1.3:
<?php
// Envia os feeds RSS e Atom como application/xml, para que o Chrome aplique uma folha CSS.
add_filter( 'feed_content_type', function ( $content_type, $type ) {
return in_array( $type, array( 'rss2', 'atom' ), true ) ? 'application/xml' : $content_type;
}, 10, 2 );
// Escreve a linha da folha de estilo entre a declaração XML e o elemento raiz.
add_action( 'rss_tag_pre', function () {
echo '<?xml-stylesheet type="text/css" href="/feed.css"?>' . "\n";
} );
No nginx, para um arquivo de feed estático, esvazie a tabela de tipos nesse bloco location e defina um tipo padrão, como no exemplo da documentação da diretiva types:
location = /feed.xml {
types { }
default_type application/xml;
}
No nosso teste com o nginx 1.27, esse bloco enviou /feed.xml como application/xml, enquanto os outros arquivos .xml mantiveram o tipo padrão do nginx, text/xml.
Para ver o que o seu servidor envia, acesse o feed no Chrome, abra o DevTools (ferramentas do desenvolvedor), recarregue a página e selecione a requisição do feed no painel Network (Rede). Na aba Headers (Cabeçalhos), o content-type aparece em Response Headers (cabeçalhos de resposta). No terminal, curl -s -o /dev/null -D - https://example.com/feed/ mostra os mesmos cabeçalhos de resposta.
Feeds de podcast seguem as mesmas regras: são arquivos RSS, então o tipo de conteúdo decide se o Chrome aplica o CSS ou mostra o texto puro.
Não mexa no link de descoberta automática (autodiscovery) das suas páginas HTML. O RSS Advisory Board pede type="application/rss+xml" nesse elemento link. Esse atributo fica na sua página HTML, enquanto o cabeçalho Content-Type do feed é definido à parte, pelo servidor.
O que o CSS não consegue fazer em um feed RSS?
O CSS muda a aparência dos elementos que já existem. Não muda o que eles são. Daí vêm três limites.
O elemento link de cada item continua sendo texto. O CSS não o transforma em link, por isso quem lê o feed não consegue clicar nele para abrir o artigo.
O HTML dentro de uma description também continua sendo texto. No nosso teste, com escape ou dentro de uma seção CDATA, o HTML apareceu com as tags à mostra, como <p> e <b>. Esconda a descrição ou mantenha-a em texto simples.
O CSS também não reescreve nem reorganiza os dados. Uma data fica no formato do feed, e não dá para ordenar os itens por data ou por título.
Para ter uma página de verdade, com links clicáveis, é preciso HTML, ou seja, manter uma folha XSL em vez de CSS. Para os feeds que mantêm o XSL, o anúncio do Chrome sugere acrescentar uma linha que carrega o script xslt-polyfill e afirma que isso não deve impedir os leitores de feed de analisar o XML. O polyfill só aplica uma folha XSL indicada no próprio feed, e aqui o tipo de conteúdo também faz diferença: no nosso teste com o XSLT desativado, o script rodou quando o arquivo era enviado como application/xml, e nunca como application/rss+xml, porque nesse caso o Chrome o mostrava como texto puro. O outro caminho é gerar o HTML você mesmo e publicá-lo em outro endereço, para que o feed continue em XML. Os nossos exemplos de XSLT no servidor mostram como.
Para comparar a sua versão em CSS com o layout XSL que ela substitui, você pode abrir o feed em um visualizador de XML com XSL: o XMLNest, disponível na Chrome Web Store, aplica folhas XSL (versão 1.0) do jeito que o Chrome fazia e abre feeds RSS e Atom em uma visualização de leitura.
Fontes
- Chrome for Developers: Removing XSLT for a more secure browser (consultada em 14 de outubro de 2026)
- W3C: Associating Style Sheets with XML documents 1.0 (Second Edition) (consultada em 14 de outubro de 2026)
- W3C: Selectors Level 3, seletores de tipo e namespaces (consultada em 14 de outubro de 2026)
- MDN: display (consultada em 14 de outubro de 2026)
- MDN: Tipos MIME comuns (consultada em 14 de outubro de 2026)
- W3C Feed Validation Service: tipo de mídia pouco específico (consultada em 14 de outubro de 2026)
- WordPress Developer Resources: feed_content_type() (consultada em 14 de outubro de 2026)
- WordPress Developer Resources: rss_tag_pre (consultada em 14 de outubro de 2026)
- WordPress Developer Resources: Must Use Plugins (consultada em 14 de outubro de 2026)
- Documentação do nginx: módulo ngx_http_core_module, diretiva types (consultada em 14 de outubro de 2026)
- Chrome for Developers: Network features reference (consultada em 14 de outubro de 2026)
- RSS Advisory Board: RSS Autodiscovery (consultada em 14 de outubro de 2026)
- XSLT Polyfill, README de mfreed7/xslt_polyfill no GitHub (consultada em 14 de outubro de 2026)
- Teste do XMLNest : Testado pelo XMLNest no Chromium 156.0.8078.4 em 14 de outubro de 2026, com o XSLT ativado e depois desativado: um feed Atom e um feed RSS ligados a uma folha CSS com <?xml-stylesheet type="text/css"?> foram estilizados quando servidos como application/xml ou text/xml; servidos como application/atom+xml ou application/rss+xml, apareceram como texto puro, sem nenhuma folha de estilo. A folha publicada neste artigo foi aplicada a um feed RSS; o HTML de uma description, com escape ou em uma seção CDATA, mostrou as tags como texto; o feed RSS sem a linha da folha de estilo mostrou a árvore XML do Chrome; com o XSLT desativado, um feed ligado a uma folha XSL mostrou “This document cannot be formatted as intended”, e um elemento script do namespace XHTML colocado nele rodou quando o feed era enviado como application/xml, não como application/rss+xml. Em um site de teste com WordPress 7.1.3, executado a partir da imagem oficial do Docker, o código deste artigo enviou /feed/ e /feed/atom/ como application/xml com a linha da folha de estilo, e o Chromium aplicou o CSS; o nginx 1.27 enviou /feed.xml como application/xml com o bloco location deste artigo, e os outros arquivos .xml como text/xml (consultada em 14 de outubro de 2026)