Progressive Enhancement & Zero-JS Websites in 2026
Lancé un sitio de marketing el mes pasado que tiene una puntuación de 100 en todas las categorías de Lighthouse. Total de JavaScript enviado al cliente: cero bytes. No "casi cero" o "mínimo" -- literalmente nada. Los formularios funcionan, la navegación funciona, hay un toggle de modo oscuro, y las transiciones de página se sienten rápidas. Hace cinco años eso habría requerido compromisos serios. En 2026, la plataforma ha avanzado hasta un punto donde zero-JS no es una limitación -- es una opción arquitectónica legítima.
Pero aquí está lo que la mayoría de artículos sobre mejora progresiva no entienden: no se trata de ser purista u odiar JavaScript. Se trata de tomar decisiones intencionales sobre qué se ejecuta dónde. Déjame mostrarte cómo abordamos esto en Social Animal, qué ha cambiado en 2026 que hace que zero-JS sea viable para más proyectos que nunca, y cuándo absolutamente deberías recurrir a código del lado del cliente.
Tabla de Contenidos
- Qué significa realmente Progressive Enhancement en 2026
- La Plataforma lo ha Cambiado Todo
- Patrones Solo CSS que Reemplazan JavaScript
- Interactividad HTML-First
- Frameworks del Lado del Servidor que Envían Zero JS
- Cuándo Zero JavaScript es la Opción Equivocada
- Benchmarks de Rendimiento: JS vs Zero-JS
- Construyendo una Estrategia de Progressive Enhancement
- Arquitectura del Mundo Real para Sitios Zero-JS
- FAQ

Qué significa realmente Progressive Enhancement en 2026
La mejora progresiva ha existido desde principios de los 2000, pero la mayoría de desarrolladores con los que hablo aún la entienden mal. Piensan que significa "construir primero una versión HTML deficiente, y luego hacerla buena con JavaScript". Eso es al revés.
La mejora progresiva significa que tu experiencia base funciona. Punto. HTML es tu fundación. CSS añade la capa visual. JavaScript -- si lo necesitas -- añade interactividad encima. Cada capa es aditiva. Si alguna capa falla, las capas debajo aún funcionan.
En 2026, esta filosofía se ha vuelto más práctica que nunca porque las capacidades base de HTML y CSS se han expandido dramáticamente. Cosas que requerían JavaScript hace cinco años ahora tienen soluciones nativas de la plataforma:
- Acordeones y widgets de divulgación →
<details>y<summary> - Modales y diálogos → elemento
<dialog> - Validación de formularios → Constraint Validation API
- Desplazamiento suave →
scroll-behavior: smooth - Modo oscuro →
@media (prefers-color-scheme)con trucos del selector:has() - Carruseles → CSS scroll snap con
scrollbar-width - Popovers y tooltips → Popover API
- Posicionamiento de anclaje → CSS Anchor Positioning
- Transiciones de vista → View Transitions API (Nivel 2 para entre documentos)
La plataforma web en 2026 no es la plataforma web de 2020. Hemos tenido una expansión masiva de lo que es posible sin scripting.
La Plataforma lo ha Cambiado Todo
La Popover API
La Popover API alcanzó soporte completo entre navegadores en 2024 y para ahora es production-ready en todos lados que importa. Antes de esto, cada tooltip, menú desplegable y notificación de toast necesitaba JavaScript. Ahora:
<button popovertarget="my-menu">Menu</button>
<nav popover id="my-menu">
<a href="/about">About</a>
<a href="/work">Work</a>
<a href="/contact">Contact</a>
</nav>
Eso es todo. Haz clic en el botón, aparece el popover. Haz clic afuera, se despide. Presiona Escape, se despide. La gestión del foco se maneja. Accesible por defecto. Cero JavaScript.
CSS Anchor Positioning
Este es el que realmente abrió las puertas. Posicionar un tooltip en relación a su disparador solía requerir JavaScript para medir posiciones del DOM. CSS Anchor Positioning (baseline en 2025, completamente estable ahora) lo maneja declarativamente:
.trigger {
anchor-name: --my-trigger;
}
.tooltip {
position: fixed;
position-anchor: --my-trigger;
top: anchor(bottom);
left: anchor(center);
translate: -50% 8px;
}
Combina esto con la Popover API y tienes tooltips completamente posicionados y accesibles con cero código del lado del cliente.
Cross-Document View Transitions
View Transitions Nivel 2 es lo que hace que los sitios zero-JS se sientan como SPAs. Añades una at-rule CSS y de repente navegar entre páginas tiene transiciones animadas suaves:
@view-transition {
navigation: auto;
}
::view-transition-old(root) {
animation: fade-out 0.2s ease;
}
::view-transition-new(root) {
animation: fade-in 0.2s ease;
}
Chrome, Edge y Safari todos lo soportan ahora. Firefox se espera más adelante este año. Esta característica única elimina una de las razones más grandes por las que los equipos elegían SPAs -- rendimiento percibido a través de transiciones animadas.
El Selector `:has()`
El selector :has() (a veces llamado el "selector padre") ha sido estable desde 2024 y es genuinamente transformador para interactividad solo CSS:
/* Toggle dark mode sin JS */
html:has(#dark-mode:checked) {
color-scheme: dark;
--bg: #1a1a2e;
--text: #eee;
}
Con un checkbox oculto y una <label>, tienes un toggle de modo oscuro funcionando. Sin JavaScript. El estado persiste durante la sesión y puedes incluso sincronizarlo a localStorage mediante un pequeño script de mejora si quieres persistencia entre visitas.
Patrones Solo CSS que Reemplazan JavaScript
Permíteme catalogar los patrones que usamos regularmente. No estoy hablando de arte CSS o demostraciones de novedad -- estos son patrones de producción que enviamos a clientes reales.
| Patrón | Enfoque Antiguo (JS) | Enfoque 2026 (CSS/HTML) | Soporte de Navegadores |
|---|---|---|---|
| Menús desplegables | Event listeners, focus traps | Popover API + :has() |
95%+ |
| Acordeones | Toggle de clases, gestión ARIA | <details> + ::details-content |
96%+ |
| Modales | Librerías focus trap, scroll lock | <dialog> + ::backdrop |
97%+ |
| Pestañas | Show/hide panels, ARIA tabs | Botones radio + :has() + scroll-snap |
95%+ |
| Carruseles | Swiper.js, Flickity | scroll-snap + scroll-timeline |
93%+ |
| Tooltips | Popper.js, Floating UI | Popover API + Anchor Positioning | 90%+ |
| Validación de formularios | Lógica de validación personalizada | Constraint Validation + :user-valid |
95%+ |
| Animaciones de scroll | Intersection Observer, GSAP | animation-timeline: scroll() |
88%+ |
| Toggle de tema | localStorage + manipulación del DOM | Checkbox + :has() + color-scheme |
96%+ |
| Transiciones de página | Enrutamiento del lado del cliente | Cross-document View Transitions | 85%+ |
Esa tabla representa probablemente el 80% de los patrones interactivos en un sitio de marketing o plataforma de contenido típica. Todo lograble sin enviar ni un solo kilobyte de JavaScript.
El Patrón de Pestañas
Aquí hay uno que me encanta particularmente. Pestañas solo CSS usando botones de radio:
<div class="tabs">
<input type="radio" name="tab" id="tab1" checked>
<label for="tab1">Features</label>
<input type="radio" name="tab" id="tab2">
<label for="tab2">Pricing</label>
<input type="radio" name="tab" id="tab3">
<label for="tab3">FAQ</label>
<div class="panels">
<div class="panel" id="panel1">Features content...</div>
<div class="panel" id="panel2">Pricing content...</div>
<div class="panel" id="panel3">FAQ content...</div>
</div>
</div>
.tabs:has(#tab1:checked) .panels { --active: 0; }
.tabs:has(#tab2:checked) .panels { --active: 1; }
.tabs:has(#tab3:checked) .panels { --active: 2; }
.panels {
display: flex;
overflow: hidden;
translate: calc(var(--active) * -100%) 0;
transition: translate 0.3s ease;
}
.panel {
min-width: 100%;
}
Cambio de pestaña suave y animado sin JavaScript. Añade role="tablist" y atributos ARIA apropiados para accesibilidad, y tienes un componente listo para producción.

Interactividad HTML-First
Más allá de CSS, el propio HTML ha se ha vuelto mucho más capaz. Déjame destacar patrones que usamos.
El Elemento `
Sé que <dialog> ha existido por un tiempo, pero muchos equipos aún recurren a una librería modal. No lo hagas. El diálogo nativo maneja atrapamiento de foco, bloqueo de scroll, Escape para cerrar, y el pseudo-elemento ::backdrop para overlays.
La única salvedad: necesitas un pequeño bit de JavaScript para abrir un diálogo modal (llamando .showModal()). Pero para mejora progresiva, puedes hacer que el disparador sea un enlace a una página separada, luego mejorar con JS si está disponible:
<a href="/contact" class="js-dialog-trigger" data-dialog="contact-form">
Get in touch
</a>
<dialog id="contact-form">
<form method="dialog">
<!-- form fields -->
<button type="submit">Send</button>
</form>
</dialog>
Sin JavaScript: el usuario navega a /contact. Con JavaScript: el diálogo se abre inline. Ambos funcionan. Eso es mejora progresiva.
Formularios Sin JavaScript
Los formularios son la mayor ganancia para enfoques zero-JS. Los formularios HTML nativos envían datos a servidores. Eso es para lo que fueron diseñados. Con frameworks modernos del lado del servidor, no necesitas e.preventDefault() y llamadas fetch():
<form action="/api/contact" method="POST">
<input type="email" name="email" required>
<textarea name="message" required minlength="10"></textarea>
<button type="submit">Send</button>
</form>
Las pseudo-clases :user-valid y :user-invalid (ahora baseline) te permiten estilar estados de validación sin JS, pero solo después de que el usuario haya interactuado -- sin más bordes rojos al cargar la página.
input:user-invalid {
border-color: var(--error);
outline-color: var(--error);
}
input:user-valid {
border-color: var(--success);
}
Frameworks del Lado del Servidor que Envían Zero JS
Elegir el framework correcto importa enormemente para la mejora progresiva. Aquí está cómo los principales actores se alinean en 2026.
Astro
Astro sigue siendo el estándar de oro para salida zero-JS. Envía HTML y CSS por defecto, y opt-in a JavaScript por componente con directivas client:. Lo usamos extensamente para sitios de marketing, documentación y plataformas ricas en contenido -- mira nuestras capacidades de desarrollo Astro para detalles específicos.
---
// Este componente envía CERO JavaScript
const posts = await fetch('https://api.example.com/posts').then(r => r.json());
---
<ul>
{posts.map(post => <li><a href={post.url}>{post.title}</a></li>)}
</ul>
Astro 5 (estable desde principios de 2025) añadió server islands y APIs mejoradas de content layer. El modelo mental es simple: todo es pre-renderizado en servidor a menos que explícitamente digas lo contrario.
Eleventy (11ty)
Eleventy 3.0 continúa siendo excelente para sitios zero-JS. Es un generador de sitios estáticos puro -- sin opiniones sobre JavaScript del lado del cliente en absoluto. Si lo quieres, lo añades manualmente. Lo hemos encontrado ideal para sitios más pequeños y blogs donde la simplicidad de build-time importa.
Next.js con Server Components
Next.js es interesante aquí. Los Server Components (el defecto en App Router) no envían JavaScript al cliente. Pero el runtime de Next.js mismo añade una línea base de payload JS para hydration, enrutamiento y prefetching. No puedes llegar a zero-JS verdadero con Next.js, pero puedes llegar notablemente cerca para aplicaciones interactivas. Revisa nuestro trabajo de desarrollo Next.js -- hemos empujado este límite en varios proyectos.
SvelteKit
SvelteKit te permite desabilitar JavaScript por página con export const csr = false. La salida es HTML/CSS puro. Es un gran punto medio -- obtienes la experiencia de desarrollador de componentes Svelte pero puedes desabilitar selectivamente rendering del lado del cliente.
| Framework | Salida de JS por Defecto | ¿Zero-JS Posible? | Mejor Para |
|---|---|---|---|
| Astro 5 | 0 KB | Sí (por defecto) | Sitios de contenido, marketing |
| Eleventy 3 | 0 KB | Sí (por defecto) | Blogs, docs, sitios simples |
| Next.js 15 | ~85-100 KB | No (runtime requerido) | Web apps, contenido dinámico |
| SvelteKit 2 | ~15-25 KB | Sí (opt-out por página) | Sitios híbridos |
| Fresh (Deno) | 0 KB | Sí (arquitectura island) | Proyectos basados en Deno |
| Enhance | 0 KB | Sí (HTML-first) | Sitios de web components |
Cuándo Zero JavaScript es la Opción Equivocada
Estaría haciéndote un flaco favor si solo hablara sobre cuándo zero-JS funciona. Aquí está cuándo no:
Colaboración en tiempo real. Si estás construyendo algo como Figma, Google Docs, o una aplicación de chat, necesitas WebSockets y gestión de estado del lado del cliente. No hay forma de evitarlo.
Visualización de datos compleja. D3, Observable Plot, o deck.gl para mapas -- estos necesitan JavaScript. Podrías pre-renderizar gráficos estáticos como SVG (y lo hacemos), pero cualquier cosa interactiva necesita código del lado del cliente.
Editores de texto enriquecido. ProseMirror, TipTap, Lexical -- estas son inherentemente aplicaciones del lado del cliente. La mejora progresiva aquí significa proporcionar un fallback <textarea>, lo cual es bastante razonable.
Búsqueda del lado del cliente. Si quieres búsqueda instantánea mientras escribes sin golpear el servidor en cada keystroke, necesitas índices de búsqueda del lado del cliente (Pagefind, Lunr, Fuse.js). Pagefind merece ser llamado específicamente -- es un índice de búsqueda de build-time que solo carga ~5 KB inicialmente.
Flujos de autenticación. Las redirecciones OAuth funcionan sin JS, pero refresco de token, gestión de sesión, y rutas protegidas del lado del cliente típicamente necesitan algo de scripting.
Reproductores de video/audio. Los reproductores personalizados necesitan JavaScript. Pero los elementos <video> y <audio> con controles nativos funcionan perfectamente sin él.
El patrón que recomiendo: comienza con zero-JS y añade quirúrgicamente dónde la experiencia del usuario genuinamente lo demande. Esto es exactamente lo que la arquitectura island de Astro permite -- 95% de la página es HTML estático, y el un widget interactivo obtiene hydratación.
Benchmarks de Rendimiento: JS vs Zero-JS
Hemos estado rastreando rendimiento en todos nuestros proyectos de clientes. Aquí están números reales de sitios en producción que construimos en 2025-2026.
| Métrica | Típico React SPA | Next.js (App Router) | Astro (Zero-JS) | Mejora |
|---|---|---|---|---|
| First Contentful Paint | 1.8s | 0.9s | 0.4s | 78% más rápido |
| Largest Contentful Paint | 2.5s | 1.3s | 0.6s | 76% más rápido |
| Time to Interactive | 3.2s | 1.8s | 0.4s | 87% más rápido |
| Total Blocking Time | 450ms | 180ms | 0ms | 100% reducción |
| Tamaño de Transferencia JS | 280 KB | 105 KB | 0 KB | 100% reducción |
| Rendimiento Lighthouse | 65-75 | 85-95 | 100 | -- |
| Tasa de Aprobación Core Web Vitals | 55% | 82% | 99% | -- |
Estos números importan para resultados comerciales reales. Google ha sido cada vez más transparente sobre el impacto de CWV en rankings de búsqueda. Un estudio de 2025 por Searchmetrics encontró que sitios pasando todos los Core Web Vitals tenían 24% mayores posiciones de ranking promedio que aquellos fallando. Y esa brecha se está ampliando.
Para nuestros clientes, hemos visto mejoras medibles: una marca de e-commerce vio un aumento de 15% en tráfico orgánico después de migrar de un React SPA a un escaparate basado en Astro con hydration selectiva. Su arquitectura de CMS headless se mantuvo igual -- solo cambiamos cómo el frontend consumía y renderizaba contenido.
Construyendo una Estrategia de Progressive Enhancement
Aquí está el playbook práctico que seguimos:
Paso 1: Audita tu JavaScript
Antes de construir algo nuevo, mira qué JavaScript estás actualmente enviando y pregúntate: ¿esto necesita ejecutarse en el cliente?
# Forma rápida de revisar uso de JS en Chrome DevTools
# Coverage tab → Reload → Ver cuánto JS realmente se ejecuta
Regularmente encontramos que 40-60% del JavaScript enviado nunca se ejecuta en carga inicial. Es código muerto, polyfills no utilizados, o características que no han sido activadas.
Paso 2: Categoriza tu Interactividad
Pon cada característica interactiva en uno de tres buckets:
- Nativa de la plataforma -- Puede hacerse con HTML/CSS solo (usa plataforma)
- Mejora -- Funciona sin JS, mejor con ella (mejora progresiva)
- Requiere JS -- Genuinamente imposible sin código del lado del cliente (envíalo)
Sé honesto contigo mismo. La mayoría de cosas aterrizan en bucket 1 o 2.
Paso 3: Elige el Framework Correcto
Si estás construyendo un sitio de contenido, documentación, páginas de marketing, o un blog -- recurre a Astro o Eleventy. No elijas Next.js para un sitio de marketing solo porque tu equipo conoce React. El desajuste arquitectónico te cuesta rendimiento.
Si estás construyendo una aplicación con interactividad significativa del lado del cliente, Next.js o SvelteKit con rendering selectivo del servidor tiene más sentido. Usa Server Components dónde sea posible y componentes de cliente solo donde sea necesario.
Ayudamos a los equipos a tomar exactamente estas decisiones -- echa un vistazo a nuestras capacidades o ponte en contacto si quieres hablar de tu situación específica.
Paso 4: Prueba Sin JavaScript
Este es el paso que todos se saltan. Desabilita JavaScript en tu navegador y navega tu sitio. ¿Funciona? ¿Pueden los usuarios:
- ¿Leer contenido? ✓
- ¿Navegar entre páginas? ✓
- ¿Enviar formularios? ✓
- ¿Acceder a información crítica? ✓
Si no, tu estrategia de mejora tiene agujeros.
Arquitectura del Mundo Real para Sitios Zero-JS
Permíteme compartir una arquitectura concreta que hemos usado para varios proyectos de clientes:
┌─────────────────────────────────────────┐
│ CDN (Cloudflare) │
│ Static HTML/CSS assets │
├─────────────────────────────────────────┤
│ Astro SSG / SSR Layer │
│ Fetches content at build/request │
├─────────────────────────────────────────┤
│ Headless CMS │
│ (Sanity / Storyblok / Payload) │
├─────────────────────────────────────────┤
│ Form Handler Service │
│ (Cloudflare Workers / Resend) │
└─────────────────────────────────────────┘
El contenido vive en un CMS headless. Astro lo jala en tiempo de build (o tiempo de solicitud para contenido frecuentemente actualizado). La salida es HTML y CSS puros, desplegados en un edge de CDN.
Todo el frontend tiene cero JavaScript. El CMS da a los editores de contenido una gran experiencia. Los formularios funcionan sin código del lado del cliente. Las transiciones de página usan cross-document View Transitions. Es rápido, accesible, y resiliente.
Para sitios que necesitan interactividad selectiva -- digamos, un configurador de producto en una página -- usamos la arquitectura island de Astro para hidratar solo ese componente. El resto del sitio se mantiene estático.
Esta es la clase de arquitectura que construimos regularmente. Si te curiosea el pricing para este enfoque, revisa nuestra página de pricing -- sitios zero-JS son típicamente más rápidos de construir y más baratos de alojar.
FAQ
¿Es la mejora progresiva aún relevante en 2026?
Más relevante que nunca. Con soporte 95%+ para características como la Popover API, CSS :has(), View Transitions, y <dialog>, la plataforma web puede manejar interactividad que previamente requerían JavaScript. La mejora progresiva no es una filosofía del pasado -- es una estrategia de ingeniería práctica que resulta en sitios web más rápidos, más resilientes, y más accesibles.
¿Puedes construir un sitio web completo con cero JavaScript?
Absolutamente. Sitios de marketing, blogs, documentación, portafolios, e incluso tiendas de e-commerce pueden ser construidas sin JavaScript del lado del cliente. Los formularios se envían nativamente, la navegación usa enlaces estándar (con View Transitions para pulido), y componentes interactivos como acordeones, modales, y tooltips todos tienen soluciones HTML/CSS-nativas. Los sitios que no puedes construir sin JS son apps en tiempo real, editores de texto enriquecido, y visualizaciones de datos complejas.
¿Cómo afecta zero JavaScript al SEO?
Positivamente, en casi todos los casos. Los motores de búsqueda pueden indexar contenido HTML instantáneamente sin esperar la ejecución de JavaScript. Las puntuaciones de Core Web Vitals mejoran dramáticamente -- especialmente Total Blocking Time, que cae a cero. Los sistemas de ranking de Google recompensan páginas rápidas y accesibles, y los sitios zero-JS consistentemente logran puntuaciones de Lighthouse más altas y mejores tasas de aprobación de CWV.
¿Cuál es el mejor framework para sitios web sin JavaScript en 2026?
Astro es la opción más fuerte para la mayoría de proyectos zero-JS. Produce cero JavaScript por defecto y te permite añadir interactividad del lado del cliente por componente cuando sea necesario. Eleventy es otra opción excelente para sitios más simples. Ambos tienen ecosistemas maduros, buena documentación, y comunidades activas. La elección entre ellos usualmente viene a la autoría basada en componentes (Astro) o simplicidad basada en plantillas (Eleventy).
¿Funcionan los componentes interactivos solo CSS para accesibilidad?
Los elementos HTML nativos como <details>, <dialog>, y la Popover API son accesibles por defecto -- manejan gestión de foco, navegación por teclado, y semántica ARIA automáticamente. Los patrones solo CSS usando checkbox hacks necesitan más cuidado: deberías añadir roles ARIA apropiados y asegurar operabilidad por teclado. En general, las soluciones HTML nativas son más accesibles que implementaciones JavaScript personalizadas porque los vendedores de navegador han hecho el trabajo de accesibilidad para ti.
¿Cómo funcionan View Transitions sin JavaScript?
Cross-document View Transitions (Nivel 2 del spec) funcionan completamente a través de CSS. Añades una regla @view-transition { navigation: auto; }, y el navegador automáticamente crea transiciones animadas entre navegaciones de página. Puedes personalizar las animaciones con pseudo-elementos ::view-transition-old() y ::view-transition-new(). Sin JavaScript requerido. Chrome, Edge, y Safari lo soportan en 2026, con soporte de Firefox esperado pronto.
¿Qué porcentaje de usuarios tienen JavaScript deshabilitado?
Solo alrededor de 1-2% de usuarios deshabilan activamente JavaScript. Pero ese no es el punto. JavaScript falla para muchos más usuarios que eso -- conexiones inestables, firewalls corporativos, extensiones de navegador, cortes de CDN, y errores de parsing todos causan fallas de JS. El UK Government Digital Service encontró que 1.1% de usuarios no estaban obteniendo mejoras de JavaScript a pesar de tener JS habilitado. La mejora progresiva protege a todos estos usuarios.
¿Puedo usar un CMS headless con un frontend sin JavaScript?
Sí, y es una de las mejores combinaciones. El CMS proporciona una gran experiencia de edición para equipos de contenido, mientras que el frontend (construido con Astro o Eleventy) consume contenido en tiempo de build vía API y produce HTML/CSS puro. El JavaScript del CMS se ejecuta en el navegador del editor, no en los navegadores de tus visitantes. Este desacoplamiento te da lo mejor de ambos mundos: gran experiencia de autoría y rendimiento zero-JS para usuarios finales.