HTML
Tutorial HTML: Compatibilidad con navegadores
Aprende a gestionar diferencias entre navegadores, implementar fallbacks y aplicar mejora progresiva para sitios web accesibles y robustos.
Aprende HTML y certifícateDiferencias entre navegadores y motores de renderizado
Cuando desarrollamos sitios web, es fundamental entender que no todos los navegadores interpretan y muestran el código HTML de la misma manera. Estas diferencias pueden afectar significativamente la apariencia y funcionalidad de nuestras páginas web.
Navegadores web: más que simples ventanas a internet
Un navegador web es un software completo que nos permite acceder a contenido en internet. Los navegadores más populares incluyen:
- Chrome
- Firefox
- Safari
- Edge
- Opera
Cada navegador tiene sus propias características, interfaz de usuario y forma de procesar el código HTML. Sin embargo, el componente más importante que determina cómo se muestra realmente una página web es el motor de renderizado.
Motores de renderizado: el corazón de los navegadores
El motor de renderizado es el componente central que interpreta el código HTML, CSS y JavaScript para convertirlo en la página web que vemos en pantalla. Es como el "traductor" entre el código y la representación visual.
Los principales motores de renderizado son:
- Blink: Utilizado por Chrome, Opera y Edge (desde 2020)
- Gecko: Utilizado por Firefox
- WebKit: Utilizado por Safari
- Trident: Utilizado por Internet Explorer (obsoleto)
<!-- Este código puede verse diferente según el motor de renderizado -->
<div style="border-radius: 10px; box-shadow: 0 4px 8px rgba(0,0,0,0.2);">
<h2>Ejemplo de contenido</h2>
<p>Este elemento podría verse ligeramente diferente en distintos navegadores.</p>
</div>
Diferencias clave entre motores de renderizado
Las diferencias entre motores de renderizado pueden manifestarse en varios aspectos:
1. Interpretación de CSS
Cada motor puede implementar las propiedades CSS de manera ligeramente diferente:
<!-- Ejemplo de diferencias en CSS -->
<style>
.gradient-box {
background: linear-gradient(to right, blue, green);
border-radius: 8px;
padding: 20px;
}
</style>
<div class="gradient-box">
<p>Los degradados pueden verse diferentes entre navegadores</p>
</div>
En este ejemplo, el degradado podría verse con ligeras variaciones de color o suavizado entre WebKit (Safari) y Blink (Chrome).
2. Soporte de características HTML5
No todos los motores implementan las nuevas características de HTML al mismo tiempo:
<!-- La etiqueta details puede comportarse diferente -->
<details>
<summary>Haz clic para expandir</summary>
<p>Este contenido expandible puede tener diferente animación o estilo según el navegador.</p>
</details>
3. Rendimiento y velocidad
Los motores procesan el JavaScript y renderizan las páginas a diferentes velocidades:
- Blink (Chrome): Generalmente ofrece un rendimiento rápido en JavaScript
- Gecko (Firefox): Buen equilibrio entre rendimiento y consumo de memoria
- WebKit (Safari): Optimizado para dispositivos Apple
4. Prefijos de proveedor
Históricamente, los navegadores han usado prefijos para implementar características experimentales:
/* Ejemplo de prefijos de proveedor */
.box {
-webkit-transition: all 0.3s; /* Safari/Chrome */
-moz-transition: all 0.3s; /* Firefox */
-ms-transition: all 0.3s; /* Internet Explorer */
-o-transition: all 0.3s; /* Opera */
transition: all 0.3s; /* Estándar */
}
Aunque la tendencia actual es reducir el uso de prefijos, todavía existen algunas propiedades que los requieren.
Cómo identificar el motor de renderizado
Podemos detectar qué motor está utilizando un navegador mediante JavaScript:
// Código para detectar el motor de renderizado
function detectRenderingEngine() {
const userAgent = navigator.userAgent;
if (userAgent.indexOf("Gecko") > -1 && userAgent.indexOf("Firefox") > -1) {
return "Gecko (Firefox)";
} else if (userAgent.indexOf("AppleWebKit") > -1) {
if (userAgent.indexOf("Chrome") > -1) {
return "Blink (Chrome)";
} else {
return "WebKit (Safari)";
}
} else if (userAgent.indexOf("Trident") > -1) {
return "Trident (Internet Explorer)";
} else {
return "Motor desconocido";
}
}
console.log("Motor de renderizado: " + detectRenderingEngine());
Impacto en el desarrollo web
Estas diferencias entre motores tienen implicaciones prácticas para los desarrolladores:
- Pruebas cruzadas: Es necesario probar nuestro sitio en múltiples navegadores
- Hacks específicos: A veces necesitamos código específico para ciertos navegadores
- Degradación elegante: Debemos planificar cómo se comportará nuestro sitio en navegadores con menos capacidades
<!-- Ejemplo de HTML con consideraciones de compatibilidad -->
<picture>
<source srcset="imagen-moderna.webp" type="image/webp">
<source srcset="imagen-fallback.jpg" type="image/jpeg">
<img src="imagen-fallback.jpg" alt="Descripción de la imagen">
</picture>
En este ejemplo, los navegadores que soportan el formato WebP mostrarán la primera imagen, mientras que los demás utilizarán el formato JPG como alternativa.
Herramientas para desarrollo multiplataforma
Para facilitar el desarrollo con estas diferencias, podemos utilizar:
- Frameworks CSS: Como Bootstrap o Tailwind CSS, que normalizan las diferencias
- Autoprefixer: Herramienta que añade automáticamente los prefijos necesarios
- Reset CSS: Hojas de estilo que normalizan el comportamiento base entre navegadores
<!-- Uso de normalize.css para estandarizar estilos base -->
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css">
<link rel="stylesheet" href="estilos-propios.css">
</head>
Evolución de los motores de renderizado
Es importante destacar que los motores de renderizado están en constante evolución. Con cada actualización, los navegadores implementan más estándares web y reducen sus diferencias. La tendencia actual es hacia una mayor estandarización y compatibilidad.
Por ejemplo, Edge abandonó su motor EdgeHTML para adoptar Blink (el mismo que usa Chrome), lo que redujo significativamente las diferencias entre estos navegadores.
Entender estas diferencias nos permite desarrollar sitios web más robustos que funcionen correctamente en diversos entornos, preparándonos para abordar las estrategias de fallback que veremos en la siguiente sección.
Estrategias de fallback para características no soportadas
Cuando desarrollamos sitios web, nos enfrentamos al desafío de que no todos los navegadores soportan las mismas características de HTML. Para crear experiencias web consistentes y funcionales en todos los navegadores, necesitamos implementar estrategias de fallback (alternativas de respaldo).
¿Qué son las estrategias de fallback?
Las estrategias de fallback son técnicas que permiten ofrecer una experiencia alternativa cuando un navegador no soporta una característica específica de HTML. En lugar de que nuestra página se rompa o muestre errores, proporcionamos una solución de respaldo que mantiene la funcionalidad básica.
Detección de soporte de características
Antes de implementar alternativas, necesitamos detectar si un navegador soporta una característica específica:
1. Detección mediante JavaScript
Podemos comprobar si una característica está disponible antes de usarla:
// Comprobar si el navegador soporta la API de geolocalización
if ("geolocation" in navigator) {
// El navegador soporta geolocalización
navigator.geolocation.getCurrentPosition(showPosition);
} else {
// Fallback: mostrar un mapa estático o un mensaje
showStaticLocationOption();
}
2. Detección mediante CSS
Para características CSS, podemos usar @supports
para aplicar estilos alternativos:
/* Estilo principal usando grid */
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
/* Fallback para navegadores que no soportan grid */
@supports not (display: grid) {
.container {
display: flex;
flex-wrap: wrap;
}
.container > div {
width: 30%;
margin: 1.5%;
}
}
Estrategias de fallback para elementos HTML5
Elementos semánticos
Para navegadores antiguos que no reconocen elementos semánticos como <article>
, <section>
o <nav>
:
<!-- Solución: definir los elementos como bloque en CSS -->
<style>
article, section, nav, header, footer, aside, main {
display: block;
}
</style>
<!-- O usar un script de polyfill como HTML5Shiv -->
<!--[if lt IE 9]>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script>
<![endif]-->
Elementos multimedia
Para el elemento <video>
:
<video controls width="400">
<source src="video.webm" type="video/webm">
<source src="video.mp4" type="video/mp4">
<!-- Fallback para navegadores sin soporte para video -->
<a href="video.mp4">Descargar el video</a>
<img src="poster.jpg" alt="Miniatura del video">
</video>
Para el elemento <audio>
:
<audio controls>
<source src="audio.ogg" type="audio/ogg">
<source src="audio.mp3" type="audio/mpeg">
<!-- Fallback para navegadores sin soporte para audio -->
<a href="audio.mp3">Descargar el audio</a>
</audio>
Formatos de imagen modernos
Para imágenes en formatos nuevos como WebP:
<picture>
<source srcset="imagen.webp" type="image/webp">
<source srcset="imagen.jpg" type="image/jpeg">
<img src="imagen.jpg" alt="Descripción de la imagen">
</picture>
Polyfills: rellenando los vacíos de compatibilidad
Los polyfills son scripts que implementan características modernas en navegadores antiguos:
<head>
<!-- Polyfill para fetch API -->
<script>
if (!window.fetch) {
document.write('<script src="https://cdn.jsdelivr.net/npm/whatwg-fetch@3.6.2/dist/fetch.umd.min.js"><\/script>');
}
</script>
</head>
Algunos polyfills populares:
- Promises: Para navegadores que no soportan promesas nativas
- Fetch: Para implementar la API Fetch en navegadores antiguos
- ClassList: Para añadir soporte a la manipulación de clases CSS
<!-- Ejemplo de uso de polyfill para promesas -->
<script>
if (typeof Promise === 'undefined') {
document.write('<script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"><\/script>');
}
</script>
Fallbacks para CSS
Propiedades con prefijos de proveedor
Aunque cada vez menos necesarios, los prefijos siguen siendo útiles para algunas propiedades:
.box {
-webkit-user-select: none; /* Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE/Edge */
user-select: none; /* Estándar */
}
Múltiples declaraciones como fallback
Podemos proporcionar múltiples valores, donde los navegadores ignoran los que no entienden:
.container {
/* Fallback para navegadores antiguos */
background: #f0f0f0;
/* Para navegadores modernos */
background: linear-gradient(to right, #f0f0f0, #e0e0e0);
}
Variables CSS con valores de respaldo
.elemento {
/* Fallback para navegadores que no soportan variables CSS */
color: #0066cc;
/* Versión con variables CSS */
color: var(--color-primario, #0066cc);
}
Estrategias para JavaScript
Comprobación de existencia de APIs
// Verificar si existe la API de almacenamiento local
function saveData(key, data) {
if (window.localStorage) {
localStorage.setItem(key, JSON.stringify(data));
} else {
// Fallback: usar cookies
document.cookie = key + "=" + JSON.stringify(data);
}
}
Carga condicional de scripts
<script>
// Cargar una librería alternativa si la API nativa no está disponible
if (!window.IntersectionObserver) {
const script = document.createElement('script');
script.src = 'intersection-observer-polyfill.js';
document.head.appendChild(script);
}
</script>
Fallbacks para formularios HTML5
Los nuevos tipos de input como date
, email
o range
se convierten automáticamente en inputs de texto en navegadores que no los soportan:
<form>
<!-- Se convierte en input text en navegadores antiguos -->
<input type="date" name="fecha">
<!-- Podemos mejorar la experiencia con JavaScript -->
<script>
if (!Modernizr.inputtypes.date) {
// Cargar un datepicker alternativo
loadDatepickerFallback();
}
</script>
</form>
Herramientas para gestionar fallbacks
Existen herramientas que facilitan la implementación de fallbacks:
- Modernizr: Biblioteca que detecta características del navegador
- Autoprefixer: Añade automáticamente prefijos de proveedor a las propiedades CSS
- Babel: Transpila JavaScript moderno a versiones compatibles con navegadores antiguos
<!-- Ejemplo de uso de Modernizr -->
<script src="modernizr.js"></script>
<script>
if (Modernizr.webgl) {
// Inicializar visualización 3D con WebGL
initWebGL();
} else {
// Mostrar alternativa 2D
showFallbackVisualization();
}
</script>
Estrategia de fallback para fuentes web
/* Cascada de fuentes con alternativas seguras */
body {
font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI',
Oxygen, Ubuntu, Cantarell, 'Open Sans', sans-serif;
}
<!-- Precargar fuentes con fallback para navegadores antiguos -->
<link rel="preload" href="fonts/roboto.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="fonts/roboto.woff" as="font" type="font/woff" crossorigin>
<style>
@font-face {
font-family: 'Roboto';
src: url('fonts/roboto.woff2') format('woff2'),
url('fonts/roboto.woff') format('woff'),
url('fonts/roboto.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
</style>
Consideraciones finales sobre fallbacks
Al implementar estrategias de fallback, es importante:
- Probar en múltiples navegadores para verificar que las alternativas funcionan correctamente
- Mantener el equilibrio entre soporte para navegadores antiguos y carga de código adicional
- Priorizar la experiencia del usuario sobre la apariencia exacta en todos los navegadores
- Documentar las decisiones sobre qué navegadores se soportan oficialmente
Implementar estas estrategias de fallback nos permite crear sitios web robustos que funcionan en una amplia gama de navegadores, asegurando que todos los usuarios puedan acceder al contenido y funcionalidad básica, independientemente del navegador que utilicen.
Herramientas para probar compatibilidad: Can I Use
Cuando desarrollamos sitios web, es fundamental saber qué características HTML son compatibles con los diferentes navegadores. Una de las herramientas más valiosas para los desarrolladores web es "Can I Use", un recurso que nos permite verificar rápidamente la compatibilidad de características web en distintos navegadores.
¿Qué es Can I Use?
Can I Use (caniuse.com) es una base de datos en línea que proporciona información actualizada sobre el soporte de características web en los principales navegadores. Esta herramienta nos permite:
- Consultar la compatibilidad de características HTML, CSS y JavaScript
- Ver estadísticas de uso global de navegadores
- Identificar qué versiones de navegadores soportan determinadas funcionalidades
- Tomar decisiones informadas sobre qué tecnologías implementar
<!-- Ejemplo: queremos usar la etiqueta <dialog> -->
<dialog open>
<p>Este es un cuadro de diálogo nativo de HTML5</p>
<button>Cerrar</button>
</dialog>
Antes de implementar este código, podríamos consultar Can I Use para verificar su compatibilidad.
Cómo utilizar Can I Use
Búsqueda de características
La forma más directa de usar Can I Use es a través de su barra de búsqueda:
- Visita caniuse.com
- Escribe el nombre de la característica que quieres verificar (por ejemplo, "flexbox", "webp" o "dialog")
- Revisa la tabla de compatibilidad que aparece
Interpretación de resultados
Can I Use muestra una tabla con códigos de colores que indican:
- Verde: Soporte completo
- Amarillo: Soporte parcial (puede requerir prefijos o tener limitaciones)
- Rojo: Sin soporte
- Gris: Característica en desarrollo o descontinuada
Además, proporciona información sobre:
- Porcentaje de usuarios globales que pueden usar la característica
- Notas específicas sobre implementaciones particulares
- Problemas conocidos en ciertos navegadores
Filtrado de resultados
Puedes personalizar los resultados según tus necesidades:
- Seleccionar regiones geográficas específicas
- Mostrar solo navegadores de escritorio o móviles
- Ajustar el rango de versiones de navegadores
Ejemplos prácticos de uso
Verificando soporte para formatos de imagen modernos
Supongamos que queremos usar imágenes WebP por su mejor compresión:
<img src="imagen.webp" alt="Descripción de la imagen">
Al consultar "webp" en Can I Use, podríamos descubrir que:
- Chrome, Edge y Firefox tienen soporte completo
- Safari añadió soporte en versiones recientes
- Internet Explorer no lo soporta en absoluto
Con esta información, implementaríamos una solución con alternativas:
<picture>
<source srcset="imagen.webp" type="image/webp">
<img src="imagen.jpg" alt="Descripción de la imagen">
</picture>
Comprobando APIs de JavaScript modernas
Si queremos usar la API Intersection Observer para implementar lazy loading:
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
document.querySelectorAll('img[data-src]').forEach(img => {
observer.observe(img);
});
Can I Use nos mostraría que esta API tiene buen soporte en navegadores modernos, pero necesitaríamos un polyfill para navegadores más antiguos.
Integración con herramientas de desarrollo
Can I Use se puede integrar en nuestro flujo de trabajo de varias maneras:
Extensiones para navegadores
Existen extensiones para Chrome y Firefox que permiten consultar Can I Use directamente desde las herramientas de desarrollo:
- Can I Use for DevTools: Muestra información de compatibilidad al inspeccionar elementos
- CanIUse Command Line: Permite consultas rápidas desde la consola
Integración con editores de código
Varios editores de código como VS Code tienen extensiones que muestran datos de Can I Use:
- Can I Use Insights: Muestra información de compatibilidad al pasar el cursor sobre propiedades CSS
- HTML Hints: Proporciona sugerencias basadas en datos de compatibilidad
Uso mediante npm
Para proyectos que utilizan herramientas de construcción modernas:
npm install caniuse-api --save-dev
// Ejemplo de uso en un script de construcción
const caniuse = require('caniuse-api');
if (!caniuse.isSupported('flexbox', 'ie 10')) {
console.log('Flexbox no es compatible con IE10, añadiendo polyfill...');
// Lógica para añadir polyfill
}
Alternativas y herramientas complementarias
Aunque Can I Use es la herramienta más popular, existen otras opciones:
- MDN Browser Compatibility Data: La documentación de Mozilla incluye tablas de compatibilidad detalladas
- Browserstack: Permite probar sitios web en navegadores reales
- Browserslist: Define qué navegadores soportar en herramientas frontend
// Ejemplo de configuración de Browserslist en package.json
{
"browserslist": [
"> 1%",
"last 2 versions",
"not dead",
"not ie <= 11"
]
}
Esta configuración se puede usar con herramientas como Autoprefixer para generar automáticamente código compatible.
Uso de Can I Use para tomar decisiones informadas
Can I Use nos ayuda a tomar decisiones basadas en datos sobre qué características implementar:
Análisis de audiencia
Si los datos de analítica muestran que el 95% de tus usuarios utilizan navegadores modernos, podrías implementar características avanzadas con fallbacks mínimos.
Soporte progresivo
Puedes implementar características avanzadas para navegadores modernos mientras mantienes una experiencia básica funcional para navegadores antiguos:
/* Ejemplo: diseño básico con fallback */
.container {
/* Fallback para navegadores antiguos */
overflow: hidden;
}
@supports (display: grid) {
.container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 20px;
}
}
Evaluación de riesgos
Can I Use te permite evaluar el riesgo de usar nuevas características:
- Características estables: Alto soporte en navegadores (>95%)
- Características emergentes: Soporte moderado (70-95%)
- Características experimentales: Soporte limitado (<70%)
Limitaciones de Can I Use
Es importante entender que Can I Use tiene algunas limitaciones:
- No muestra bugs específicos de implementación
- No cubre todas las interacciones complejas entre características
- La información puede no estar completamente actualizada para las versiones más recientes
- No sustituye las pruebas reales en navegadores
Por ello, es recomendable complementar Can I Use con pruebas directas en los navegadores objetivo de tu proyecto.
Uso de datos de Can I Use en documentación
Una buena práctica es incluir información de compatibilidad en la documentación de tu proyecto:
<!--
Feature: <dialog> element
Compatibility:
- Chrome 37+
- Firefox 98+
- Safari 15.4+
- Edge 79+
- Not supported in IE
See: https://caniuse.com/dialog
-->
<dialog id="myDialog">
<h2>Título del diálogo</h2>
<p>Contenido del diálogo...</p>
<button id="closeDialog">Cerrar</button>
</dialog>
Esta documentación ayuda a otros desarrolladores a entender las limitaciones de compatibilidad del código.
Can I Use es una herramienta esencial que nos permite tomar decisiones informadas sobre qué características HTML implementar y cómo proporcionar alternativas adecuadas, complementando perfectamente las estrategias de fallback y el enfoque de mejora progresiva que veremos a continuación.
Enfoque "progressive enhancement"
El enfoque de mejora progresiva (progressive enhancement) es una filosofía de desarrollo web que prioriza la creación de experiencias digitales accesibles para todos los usuarios, independientemente del navegador o dispositivo que utilicen. Este método se basa en construir por capas, comenzando con un núcleo funcional básico y añadiendo mejoras graduales para navegadores más modernos.
Principios fundamentales de la mejora progresiva
La mejora progresiva se sustenta en tres capas principales que se construyen una sobre otra:
- Contenido HTML: La base semántica y estructural accesible para todos
- Presentación CSS: Mejoras visuales que se aplican cuando están disponibles
- Comportamiento JavaScript: Funcionalidades avanzadas que enriquecen la experiencia
<!-- Ejemplo básico de mejora progresiva -->
<!-- 1. Capa de contenido: funciona en cualquier navegador -->
<div class="tarjeta-producto">
<h2>Auriculares inalámbricos</h2>
<p>Auriculares con cancelación de ruido y 20h de batería</p>
<p class="precio">89,99€</p>
<a href="/comprar/auriculares" class="boton-comprar">Comprar ahora</a>
</div>
A esta base HTML podemos añadir capas de mejora:
/* 2. Capa de presentación: mejoras visuales */
.tarjeta-producto {
padding: 1rem;
border: 1px solid #ddd;
}
/* Mejora para navegadores que soportan sombras */
@supports (box-shadow: 0 0 10px rgba(0,0,0,0.1)) {
.tarjeta-producto {
border: none;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
border-radius: 8px;
}
}
// 3. Capa de comportamiento: funcionalidades avanzadas
// Solo se ejecuta si el navegador soporta estas características
if ('IntersectionObserver' in window) {
// Implementar animación de entrada cuando la tarjeta es visible
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
observer.unobserve(entry.target);
}
});
});
document.querySelectorAll('.tarjeta-producto').forEach(card => {
observer.observe(card);
});
}
Mejora progresiva vs. degradación elegante
Es importante distinguir entre estos dos enfoques complementarios:
- Mejora progresiva: Comienza con lo básico y añade capas de mejora (de abajo hacia arriba)
- Degradación elegante: Comienza con todas las características y proporciona alternativas cuando no están disponibles (de arriba hacia abajo)
La mejora progresiva suele considerarse un enfoque más robusto porque garantiza que el contenido básico siempre sea accesible, mientras que las mejoras se tratan como "extras" opcionales.
Implementación práctica de la mejora progresiva
Veamos cómo aplicar este enfoque en diferentes aspectos del desarrollo web:
Formularios con validación
<!-- Nivel básico: formulario funcional en cualquier navegador -->
<form action="/registro" method="post">
<div>
<label for="email">Email:</label>
<input type="text" id="email" name="email" required>
</div>
<div>
<label for="password">Contraseña:</label>
<input type="password" id="password" name="password" required>
</div>
<button type="submit">Registrarse</button>
</form>
Mejora para navegadores modernos:
<!-- Mejora: usar tipos de input específicos y validación del lado del cliente -->
<form action="/registro" method="post" novalidate>
<div>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required
pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$">
<span class="error" aria-live="polite"></span>
</div>
<!-- Resto del formulario... -->
</form>
<script>
// Solo se ejecuta si el navegador soporta JavaScript
const form = document.querySelector('form');
if (form && 'validity' in document.createElement('input')) {
form.addEventListener('submit', function(event) {
const emailInput = document.getElementById('email');
if (!emailInput.validity.valid) {
event.preventDefault();
// Mostrar mensaje de error personalizado
document.querySelector('.error').textContent =
emailInput.validity.valueMissing ? 'Por favor, introduce un email' :
emailInput.validity.typeMismatch ? 'Por favor, introduce un email válido' : '';
}
});
}
</script>
Diseño responsive con mejora progresiva
/* Base: diseño simple de una columna que funciona en cualquier navegador */
.contenedor {
width: 100%;
max-width: 1200px;
margin: 0 auto;
}
.tarjetas {
padding: 1rem;
}
.tarjeta {
margin-bottom: 1rem;
padding: 1rem;
border: 1px solid #ddd;
}
/* Mejora: diseño de cuadrícula para navegadores modernos */
@supports (display: grid) {
.tarjetas {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 1rem;
}
.tarjeta {
margin-bottom: 0; /* Eliminar margen ya que grid usa gap */
}
}
Imágenes responsivas
<!-- Base: imagen estándar que funciona en todos los navegadores -->
<img src="imagen-mediana.jpg" alt="Descripción de la imagen">
<!-- Mejora: imágenes responsivas con diferentes resoluciones -->
<picture>
<!-- Formato WebP para navegadores que lo soportan -->
<source
srcset="imagen-pequeña.webp 400w,
imagen-mediana.webp 800w,
imagen-grande.webp 1200w"
sizes="(max-width: 600px) 400px,
(max-width: 1200px) 800px,
1200px"
type="image/webp">
<!-- Formato JPEG como fallback -->
<source
srcset="imagen-pequeña.jpg 400w,
imagen-mediana.jpg 800w,
imagen-grande.jpg 1200w"
sizes="(max-width: 600px) 400px,
(max-width: 1200px) 800px,
1200px">
<!-- La imagen base que se mostrará si nada más funciona -->
<img src="imagen-mediana.jpg" alt="Descripción de la imagen">
</picture>
Funcionalidades avanzadas con detección de características
// Ejemplo: implementación de un mapa interactivo con mejora progresiva
// 1. Versión básica: enlace a un mapa estático
const mapContainer = document.getElementById('mapa');
mapContainer.innerHTML = '<a href="https://maps.google.com/?q=Madrid,España">Ver ubicación en Google Maps</a>';
// 2. Mejora: mapa interactivo si el navegador lo soporta
if ('geolocation' in navigator && 'fetch' in window) {
// Cargar la API de mapas dinámicamente
const script = document.createElement('script');
script.src = 'https://maps.example.com/api.js';
script.onload = initMap;
document.head.appendChild(script);
function initMap() {
// Inicializar mapa interactivo
mapContainer.innerHTML = '';
const map = new MapAPI.Map(mapContainer, {
center: { lat: 40.416775, lng: -3.703790 },
zoom: 12
});
// Añadir marcadores, controles, etc.
}
}
Ventajas de la mejora progresiva
Este enfoque ofrece numerosos beneficios:
- Accesibilidad universal: El contenido básico está disponible para todos los usuarios
- Rendimiento optimizado: Las características avanzadas solo se cargan cuando son necesarias
- Mantenimiento simplificado: La separación por capas facilita las actualizaciones
- Compatibilidad a largo plazo: El sitio seguirá funcionando incluso en navegadores antiguos
- SEO mejorado: Los motores de búsqueda pueden indexar el contenido base sin problemas
Implementación en proyectos reales
Para aplicar la mejora progresiva en proyectos reales, podemos seguir estas pautas:
1. Identificar funcionalidades críticas vs. mejoras
Antes de comenzar a desarrollar, clasifica las características de tu sitio:
- Críticas: Contenido principal, navegación, formularios básicos
- Mejoras: Animaciones, interacciones avanzadas, efectos visuales
2. Establecer una base HTML semántica
<!-- Estructura semántica básica -->
<header>
<nav>
<ul>
<li><a href="/">Inicio</a></li>
<li><a href="/productos">Productos</a></li>
<li><a href="/contacto">Contacto</a></li>
</ul>
</nav>
</header>
<main>
<section class="productos">
<h1>Nuestros productos</h1>
<!-- Contenido principal -->
</section>
</main>
<footer>
<p>© 2023 Mi Empresa</p>
</footer>
3. Aplicar CSS con detección de características
/* Estilos base que funcionan en todos los navegadores */
.galeria-items {
display: block;
}
.galeria-item {
margin-bottom: 1rem;
}
/* Mejora: Flexbox para navegadores que lo soportan */
@supports (display: flex) {
.galeria-items {
display: flex;
flex-wrap: wrap;
margin: -0.5rem;
}
.galeria-item {
flex: 0 0 calc(50% - 1rem);
margin: 0.5rem;
}
}
/* Mejora adicional: Grid para navegadores más modernos */
@supports (display: grid) {
.galeria-items {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 1rem;
margin: 0;
}
.galeria-item {
margin: 0;
}
}
4. Cargar JavaScript de forma condicional
<script>
// Función para cargar scripts solo si se cumplen ciertas condiciones
function cargarScriptSiSeSoporta(caracteristica, ruta) {
if (caracteristica in window) {
const script = document.createElement('script');
script.src = ruta;
document.head.appendChild(script);
return true;
}
return false;
}
// Cargar características avanzadas solo si están disponibles
if (!cargarScriptSiSeSoporta('IntersectionObserver', '/js/lazy-loading.js')) {
// Fallback: cargar todas las imágenes inmediatamente
document.querySelectorAll('img[data-src]').forEach(img => {
img.src = img.dataset.src;
});
}
</script>
Herramientas para facilitar la mejora progresiva
Varias herramientas pueden ayudarnos a implementar este enfoque:
- Modernizr: Biblioteca que detecta características del navegador y añade clases CSS
- Feature-detect: Técnicas nativas para detectar soporte de características
- PostCSS: Procesador CSS que puede añadir prefijos y fallbacks automáticamente
- Babel: Transpilador que convierte JavaScript moderno en versiones compatibles
<!-- Ejemplo de uso de Modernizr -->
<script src="modernizr.js"></script>
<style>
/* Estilos basados en capacidades detectadas */
.mi-elemento {
background: #f0f0f0;
}
.cssgradients .mi-elemento {
background: linear-gradient(to bottom, #f0f0f0, #e0e0e0);
}
</style>
Mejora progresiva en la era de las SPA
Incluso en aplicaciones de página única (SPA), podemos aplicar mejora progresiva:
<!-- Base: versión sin JavaScript -->
<noscript>
<p>Esta aplicación requiere JavaScript para funcionar correctamente.
Por favor, <a href="/version-estatica">accede a la versión estática</a>.</p>
</noscript>
<!-- Contenedor para la aplicación -->
<div id="app">
<!-- Contenido inicial que se verá antes de que cargue JavaScript -->
<header>
<h1>Mi Aplicación</h1>
</header>
<main>
<p>Cargando contenido...</p>
</main>
</div>
<!-- Cargar la aplicación con detección de características -->
<script>
// Verificar características mínimas necesarias
if ('Promise' in window && 'fetch' in window && 'querySelector' in document) {
// Cargar la aplicación moderna
const script = document.createElement('script');
script.src = '/js/app.modern.js';
document.head.appendChild(script);
} else {
// Cargar versión simplificada con polyfills
const script = document.createElement('script');
script.src = '/js/app.legacy.js';
document.head.appendChild(script);
}
</script>
Equilibrio entre mejora progresiva y experiencia de usuario
Es importante encontrar un equilibrio entre la compatibilidad universal y la experiencia de usuario moderna:
- No sacrifiques la experiencia principal por compatibilidad con navegadores extremadamente antiguos
- Establece una línea base razonable de navegadores a soportar (por ejemplo, últimos 2 años)
- Utiliza analíticas para entender qué navegadores usan realmente tus visitantes
- Considera el contexto de tu proyecto (una aplicación interna corporativa vs. un sitio público)
La mejora progresiva no significa que todos los usuarios deban tener exactamente la misma experiencia, sino que todos deben poder acceder al contenido y funcionalidad esencial, mientras que aquellos con navegadores más modernos pueden disfrutar de una experiencia mejorada.
Al adoptar este enfoque, creamos sitios web más resilientes, accesibles y sostenibles a largo plazo, preparados para funcionar en el ecosistema diverso de dispositivos y navegadores que caracteriza la web actual.
Otras lecciones de HTML
Accede a todas las lecciones de HTML y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A Html
Introducción Y Entorno
Doctype
Sintaxis Y Estructura
Elementos Y Etiquetas
Sintaxis Y Estructura
Atributos
Sintaxis Y Estructura
Anidación De Etiquetas
Sintaxis Y Estructura
Comentarios
Sintaxis Y Estructura
Encabezados (H1-h6)
Textos Y Enlaces
Enlace (A)
Textos Y Enlaces
Párrafo (P)
Textos Y Enlaces
Listas (Ul, Ol, Li)
Textos Y Enlaces
Imagen (Img)
Textos Y Enlaces
División (Div)
Organización De Contenido
Etiquetas Semánticas (Article, Section, Header, Footer, Nav, Aside)
Organización De Contenido
Tablas (Table, Tr, Td, Th)
Organización De Contenido
Formularios (Form, Input, Select, Textarea, Button)
Organización De Contenido
Imágenes Vectoriales (Svg)
Elementos Multimedia
Incrustación De Contenido (Iframe)
Elementos Multimedia
Audio (Audio)
Elementos Multimedia
Video (Video)
Elementos Multimedia
Estilo Incorporado (Style)
Metadatos Y Seo
Metadatos (Meta, Title, Link)
Metadatos Y Seo
Atributos De Aria
Metadatos Y Seo
Navegación Por Teclado
Metadatos Y Seo
Contraste Y Legibilidad
Optimización Html
Validación De Html
Optimización Html
Compatibilidad Con Navegadores
Optimización Html
Optimización De La Carga De La Página (Lazy Loading)
Optimización Html
Ejercicios de programación de HTML
Evalúa tus conocimientos de esta lección Compatibilidad con navegadores con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
Reto etiquetas semánticas HTML
Divisiones
Reto atributos ARIA en HTML
Reto trabajar con imágenes en HTML
Formularios
Encabezados
Reto metadatos en HTML
Validación de HTML
Navegación por teclado
Párrafos
Uso de DOCTYPE
Etiquetas semánticas
Contraste y legibilidad
Atributos
Reto formatear texto en HTML
Reto crear listas HTML
Metadatos
Comentarios
Incrustación de contenido (iframe)
Uso de elementos y etiquetas
Audio
Proyecto crear páginas HTML
Enlace
Video
Imágenes
DOCTYPE
Compatibilidad con navegadores
Reto crear tablas HTML
Introducción a HTML
Imágenes vectoriales
Anidación de etiquetas
Reto Validación HTML
Optimización de la carga de la página (Lazy loading)
Listas
Estilos
Reto de enlaces HTML
Atributos de ARIA
Reto geolocalización en HTML
Tablas
Reto LocalStorage en HTML
Uso de atributos
Elementos y etiquetas
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender las diferencias entre navegadores y motores de renderizado.
- Aprender a implementar estrategias de fallback para características no soportadas.
- Utilizar herramientas como Can I Use para verificar compatibilidad.
- Aplicar el enfoque de mejora progresiva en el desarrollo web.
- Identificar buenas prácticas para mantener la compatibilidad y accesibilidad en proyectos reales.