Dar estilo a un feed RSS con CSS: lo que sigue funcionando en Chrome
Una hoja CSS enlazada desde un feed seguirá funcionando en Chrome cuando desaparezca XSLT, siempre que el servidor envíe el feed como application/xml o text/xml. Si lo envía como application/rss+xml, aparece como texto plano y el CSS se ignora. Lo comprobamos en Chromium 156 y en un sitio de prueba con WordPress. La configuración se hace en tres pasos.
¿Se puede dar estilo a un feed RSS con CSS sin XSLT?
Sí, si el servidor envía el feed con el tipo de contenido adecuado. El anuncio de Chrome sobre XSLT indica que la instrucción de procesamiento <?xml-stylesheet ... ?> sigue siendo compatible con CSS, mediante type="text/css". Lo único que desaparece es XSLT, en Chrome 158, el 17 de noviembre de 2026.
Esto afecta a quienes publican un feed que hoy usa una hoja XSL. Chrome señala que muchos feeds RSS y Atom usan XSLT para que se puedan leer al abrirlos directamente en el navegador. A partir del 17 de noviembre, esos feeds perderán su diseño en Chrome. Una hoja CSS es el sustituto más ligero: no hay transformación, solo reglas sobre el aspecto de cada elemento.
El tipo de contenido importa por la forma en que Chrome trata los tipos MIME de los feeds. Chrome abre como texto plano un feed enviado como application/rss+xml o application/atom+xml, y a ese texto no se le aplica ninguna hoja de estilo, ni CSS ni XSL. Nuestra guía sobre feeds RSS que aparecen como texto explica ese comportamiento y qué pueden hacer quienes quieren leer el feed.
Para dar estilo a un feed RSS con CSS hacen falta, por tanto, dos cosas: la línea de la hoja de estilo en el feed y un servidor que lo envíe como application/xml o text/xml. Si hoy tu feed con formato XSL se ve con su diseño en Chrome, tu servidor ya envía uno de esos tipos y solo tienes que cambiar la línea de la hoja de estilo.
¿Con qué tipo de contenido aplica Chrome el CSS a un feed?
Con application/xml o text/xml. El 14 de octubre de 2026 abrimos en Chromium 156 un feed Atom y un feed RSS pequeños, alojados en un servidor local. Ambos empezaban con esta línea, justo después de la declaración XML:
<?xml-stylesheet type="text/css" href="/feed.css"?>
La hoja de prueba mostraba cada elemento title en rojo, a 28 píxeles, y ocultaba los demás, de modo que el resultado se podía comprobar en el estilo calculado de cada elemento. Probamos cada caso dos veces: con la función XSLT de Chromium activada y con ella desactivada, que es como estará en Chrome 158. Los resultados fueron idénticos.
| Feed | Tipo enviado por el servidor | Lo que mostró Chromium |
|---|---|---|
| Atom | application/xml |
CSS aplicado: títulos en rojo |
| Atom | text/xml |
CSS aplicado |
| RSS | application/xml |
CSS aplicado |
| RSS | text/xml |
CSS aplicado |
| Atom | application/atom+xml |
Texto plano del feed, CSS ignorado |
| RSS | application/rss+xml |
Texto plano del feed, CSS ignorado |
Cuando el feed aparecía como texto plano, la página mostraba el código fuente del feed tal como se envió, en fuente monoespaciada y con la línea de la hoja incluida. Cuando se aplicaba el estilo, Chrome no mostraba ningún mensaje encima del contenido. Los elementos ocultos, como id y updated, ya no se veían, pero seguían presentes en el documento.
Sin la línea de la hoja de estilo, el mismo feed RSS enviado como application/xml apareció en la vista en árbol de Chrome, debajo del mensaje «no style information» (sin información de estilo). Nuestra guía para abrir archivos XML en Chrome explica qué significa. Con XSLT desactivado, Chrome muestra otro mensaje para un feed enlazado a una hoja XSL: «This document cannot be formatted as intended» (el documento no puede mostrarse con el formato previsto).
¿Cómo se enlaza una hoja CSS a un feed?
En tres pasos.
1. Añade la instrucción de procesamiento. La define la recomendación del W3C «Associating Style Sheets with XML documents». Debe ir en el prólogo, es decir, justo después de <?xml version="1.0"?> y antes del elemento raíz, <rss> o <feed>. El pseudoatributo href es obligatorio. Los demás son opcionales: type, title, media, charset y alternate. Un feed RSS completo con su línea de hoja de estilo queda así:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/feed.css"?>
<rss version="2.0">
<channel>
<title>Blog de ejemplo</title>
<link>https://example.com/</link>
<description>Últimos artículos</description>
<item>
<title>Primer artículo</title>
<link>https://example.com/primero/</link>
</item>
</channel>
</rss>
2. Escribe el CSS. Según MDN, el valor inicial de display es inline. Un feed no tiene estilos HTML por defecto: sin reglas propias, todos los elementos se muestran seguidos en una sola línea. Empieza por convertir los contenedores en bloques:
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; }
También probamos esta hoja: en un feed RSS, los títulos aparecieron a 1,4 veces el tamaño base y los enlaces quedaron ocultos. En RSS, tanto el canal como cada entrada (item) tienen su propio elemento title. Para darles estilos distintos, usa channel > title e item > title, o feed > title y entry > title en Atom. Un selector title a secas también se aplica a los títulos de un feed Atom, aunque sus elementos pertenezcan al espacio de nombres de Atom. Según la especificación Selectors del W3C, si la hoja CSS no declara un espacio de nombres por defecto, un selector de tipo coincide con elementos de cualquier espacio de nombres.
3. Envía el tipo de contenido correcto. La lista de tipos MIME comunes de MDN recomienda application/xml para XML y señala que text/xml todavía se usa a veces, así que elige application/xml. El servicio de validación de feeds del W3C avisará de que este tipo no es lo bastante específico para que cualquier programa reconozca un feed. Cuando no se puede usar un tipo más preciso, pide que <rss o <feed aparezca en los primeros 512 bytes, y un feed que empieza con las dos líneas de arriba lo cumple.
En WordPress, basta con dos hooks para hacer ambos cambios. Salvo que un filtro cambie el resultado, la función feed_content_type() devuelve application/rss+xml para RSS y application/atom+xml para Atom. La acción rss_tag_pre, por su parte, se ejecuta entre la declaración XML y el elemento raíz. Este código, guardado como archivo PHP en wp-content/mu-plugins/, la carpeta de los plugins imprescindibles (must-use), funcionó en un sitio de prueba con WordPress 7.1.3:
<?php
// Envía los feeds RSS y Atom como application/xml para que Chrome aplique la hoja CSS.
add_filter( 'feed_content_type', function ( $content_type, $type ) {
return in_array( $type, array( 'rss2', 'atom' ), true ) ? 'application/xml' : $content_type;
}, 10, 2 );
// Escribe la línea de la hoja de estilo entre la declaración XML y el elemento raíz.
add_action( 'rss_tag_pre', function () {
echo '<?xml-stylesheet type="text/css" href="/feed.css"?>' . "\n";
} );
En nginx, si el feed es un archivo estático, vacía la tabla de tipos para esa dirección y fija un tipo por defecto, como en el ejemplo de la documentación de la directiva types:
location = /feed.xml {
types { }
default_type application/xml;
}
En nuestra prueba con nginx 1.27, con este bloque /feed.xml se sirvió como application/xml, y los demás archivos .xml mantuvieron el tipo por defecto, text/xml.
Para ver qué envía tu servidor, con el feed abierto en Chrome, abre DevTools (herramientas para desarrolladores), recarga la página y selecciona la petición del feed en el panel Network (Red). En la pestaña Headers (Encabezados), content-type aparece en Response Headers (encabezados de respuesta). En un terminal, curl -s -o /dev/null -D - https://example.com/feed/ muestra los mismos encabezados de respuesta.
Los feeds de pódcast siguen las mismas reglas: son archivos RSS, así que el tipo de contenido determina si Chrome aplica el CSS o muestra el texto plano.
El enlace de autodescubrimiento de tus páginas HTML se queda como está. El RSS Advisory Board pide type="application/rss+xml" en ese elemento link. Ese atributo está en tu página HTML; el encabezado Content-Type del feed lo fija por separado el servidor que lo envía.
¿Qué no puede hacer el CSS en un feed RSS?
El CSS modifica el aspecto de los elementos que ya existen, pero no lo que son, y de ahí vienen tres límites.
El elemento link de cada entrada sigue siendo texto. El CSS no lo convierte en un enlace, así que no se puede hacer clic en él para ir al artículo.
El HTML dentro de una description también sigue siendo texto. En nuestra prueba, tanto el HTML escapado como el incluido en una sección CDATA mostraban las etiquetas tal cual, por ejemplo <p> y <b>. Oculta la descripción o déjala en texto sin formato.
El CSS tampoco toca los datos: una fecha conserva el formato del feed, y las entradas no se pueden ordenar por fecha ni por título.
Para tener una página de verdad con enlaces en los que se pueda hacer clic hace falta HTML; una opción es mantener una hoja XSL en lugar de CSS. Si el feed conserva su XSL, el anuncio de Chrome sugiere añadir una línea que cargue el script xslt-polyfill, algo que, según Chrome, no debería impedir que los lectores de feeds analicen el XML. El polyfill solo aplica una hoja XSL que el feed ya enlaza, y aquí también influye el tipo de contenido. En nuestra prueba con XSLT desactivado, un script colocado en el feed se ejecutó cuando se enviaba como application/xml, pero nunca como application/rss+xml, porque en ese caso Chrome lo mostraba como texto plano. La alternativa es generar tú mismo el HTML y publicarlo en una dirección distinta, para que el feed siga siendo XML. Nuestros ejemplos de XSLT en el servidor muestran cómo.
XMLNest ya está disponible en Chrome Web Store. Con este visor XML puedes comparar tu versión CSS con el diseño XSL al que sustituye: aplica las hojas XSL (versión 1.0) como lo hacía Chrome y abre los feeds RSS y Atom en una vista de lectura.
Fuentes
- Chrome for Developers: Removing XSLT for a more secure browser (consultada el 14 de octubre de 2026)
- W3C: Associating Style Sheets with XML documents 1.0 (Second Edition) (consultada el 14 de octubre de 2026)
- W3C: Selectors Level 3, selectores de tipo y espacios de nombres (consultada el 14 de octubre de 2026)
- MDN: display (consultada el 14 de octubre de 2026)
- MDN: Tipos MIME comunes (consultada el 14 de octubre de 2026)
- W3C Feed Validation Service: tipo de medio poco específico (consultada el 14 de octubre de 2026)
- WordPress Developer Resources: feed_content_type() (consultada el 14 de octubre de 2026)
- WordPress Developer Resources: rss_tag_pre (consultada el 14 de octubre de 2026)
- WordPress Developer Resources: Must Use Plugins (consultada el 14 de octubre de 2026)
- Documentación de nginx: módulo ngx_http_core_module, directiva types (consultada el 14 de octubre de 2026)
- Chrome for Developers: Network features reference (consultada el 14 de octubre de 2026)
- RSS Advisory Board: RSS Autodiscovery (consultada el 14 de octubre de 2026)
- XSLT Polyfill, README de mfreed7/xslt_polyfill en GitHub (consultada el 14 de octubre de 2026)
- Prueba de XMLNest : Prueba realizada por XMLNest en Chromium 156.0.8078.4 el 14 de octubre de 2026, con la función XSLT activada y después desactivada: un feed Atom y un feed RSS enlazados a una hoja CSS con <?xml-stylesheet type="text/css"?> se mostraron con estilo cuando se servían como application/xml o text/xml; servidos como application/atom+xml o application/rss+xml, aparecieron como texto plano, sin ninguna hoja de estilo. La hoja publicada en este artículo se aplicó a un feed RSS; el HTML de una description, escapado o en una sección CDATA, mostró sus etiquetas como texto; el feed RSS sin línea de hoja de estilo mostró el árbol XML de Chrome; con la función XSLT desactivada, un feed enlazado a una hoja XSL mostró «This document cannot be formatted as intended», y un elemento script del espacio de nombres XHTML colocado en él se ejecutó cuando el feed se enviaba como application/xml, no como application/rss+xml. En un sitio de prueba con WordPress 7.1.3, creado con la imagen oficial de Docker, el código de este artículo envió /feed/ y /feed/atom/ como application/xml con la línea de la hoja de estilo, y Chromium aplicó el CSS; nginx 1.27 envió /feed.xml como application/xml con el bloque location de este artículo, y los demás archivos .xml como text/xml (consultada el 14 de octubre de 2026)