Skip to content
This page has been auto-translated and may contain errors.View in English

Diseño responsivo

docs.scrimba.com

Construyes una página en tu laptop, se ve bien, y luego alguien la abre en un teléfono. Las columnas que cuidadosamente alineaste ahora están aplastadas en una franja angosta, el texto se sale del borde, y aparece una barra de desplazamiento horizontal donde no debería haber ninguna. Nadie escribió una versión separada de la página para teléfono. Hay una sola página, y tiene que verse bien tanto en un teléfono de 380 píxeles como en un monitor de 1400 píxeles sin que tengas que enviar dos versiones de todo. Esa capacidad de adaptación es el diseño responsivo, y la mayoría está construida con herramientas que ya tienes.

Qué significa responsivo y la ventana gráfica

Una página responsiva es una sola página que se remodela a sí misma para ajustarse a cualquier pantalla en la que caiga. El mismo HTML y el mismo CSS sirven un teléfono, una tableta y un escritorio, y el diseño se ajusta para que nada se desborde y nada se sienta apretado. No estás construyendo tres sitios. Estás construyendo uno que se flexiona.

Antes de que todo eso funcione, el navegador necesita una instrucción en el HTML. Los teléfonos solían pretender que eran del ancho del escritorio y encogían la página completa para ajustarse, por eso los sitios antiguos aparecían como un desorden diminuto y alejado. Esta línea, que vive en la etiqueta <head> de tu HTML, le dice al teléfono que use su ancho real en su lugar:

html
<meta name="viewport" content="width=device-width, initial-scale=1" />

Sin ella, tu CSS está diseñando una pantalla ancha imaginaria y tu cuidadoso diseño nunca tiene la oportunidad de funcionar.

El diseño responsivo significa un único código que adapta su diseño al tamaño de la ventana gráfica, el área visible de la página dentro de la ventana del navegador. Hay un conjunto de HTML y una hoja de estilos; lo que cambia es cómo esa hoja de estilos responde al espacio que se le da. La alternativa, sitios separados para móvil y escritorio, duplica tu mantenimiento y es por eso que la industria optó por el diseño responsivo hace años.

El requisito inicial es la etiqueta de meta de ventana gráfica en el encabezado HTML. Establece el ancho contra el que el navegador presenta el contenido al ancho real del dispositivo, y evita que los navegadores móviles se representen a un ancho de escritorio falso y se reduzcan:

html
<meta name="viewport" content="width=device-width, initial-scale=1" />

width=device-width hace coincidir la ventana gráfica de diseño con la pantalla, y initial-scale=1 establece el zoom inicial en 100%. Si lo omites, ninguna cantidad de CSS correcto salvará el diseño, porque el navegador está midiendo contra el ancho equivocado.

El diseño responsivo es la práctica de construir un documento cuyo diseño se adapta a un rango continuo de tamaños de ventana gráfica, en lugar de apuntar a un puñado de pantallas fijas. La ventana gráfica es la región que el navegador usa para presentar y pintar la página, y su ancho es el valor contra el cual cada unidad relativa, porcentaje y media query eventualmente se resuelve. Si obtienes ese ancho incorrecto, todo lo que sigue está midiendo algo equivocado.

Exactamente eso es lo que la etiqueta de meta de ventana gráfica previene. Los navegadores móviles históricamente distinguieron una ventana gráfica de diseño (el ancho contra el que CSS se presenta) de la ventana gráfica visual (lo que realmente está en pantalla), estableciendo por defecto la ventana gráfica de diseño en alrededor de 980px para que los sitios heredados solo de escritorio se reprodujeran y luego se reducieran para ajustarse. La etiqueta de meta cierra esa brecha:

html
<meta name="viewport" content="width=device-width, initial-scale=1" />

width=device-width vincula la ventana gráfica de diseño al ancho de píxeles CSS del dispositivo, e initial-scale=1 fija el zoom inicial para que las dos ventanas gráficas comiencen alineadas. Pertenece al encabezado HTML, y es una precondición, no una amabilidad: sin ella el navegador evalúa tus media queries y porcentajes contra aproximadamente 980px en un teléfono de 390px, entonces una consulta min-width: 40rem se dispara cuando no debería y el diseño que probaste nunca aparece. Todo en este capítulo asume que esa etiqueta está presente.

JunoQué significa responsivo y la ventana gráfica Una página responsiva es una sola página que se remodela a sí misma para ajustarse a cualquier pantalla, teléfono hasta escritorio, desde un único conjunto de HTML y CSS. Antes de que tu CSS tenga una oportunidad justa, el encabezado HTML necesita la etiqueta de meta de ventana gráfica, que le dice a los teléfonos que usen su ancho real en lugar de pretender ser un escritorio. Si la omites, el diseño se verá roto sin importar qué tan bueno sea el CSS.
JunoQué significa responsivo y la ventana gráfica Responsivo significa un código único que se adapta a la ventana gráfica, el área visible de la página, no compilaciones separadas para móvil y escritorio. La etiqueta de meta de ventana gráfica en el encabezado HTML es el requisito inicial: width=device-width hace que el navegador se presente contra el ancho de pantalla real. Si la omites, tus media queries se disparan contra un ancho falso de escritorio, así que el CSS correcto se sigue viendo mal.
JunoQué significa responsivo y la ventana gráfica Cada porcentaje y media query se resuelve contra el ancho de la ventana gráfica, así que la etiqueta de meta de ventana gráfica es una precondición más que una amabilidad. width=device-width, initial-scale=1 vincula la ventana gráfica de diseño al ancho real del dispositivo en lugar del valor predeterminado heredado de 980px. Olvídala en un teléfono y una consulta min-width: 40rem se dispara cuando no debería, y el diseño que probaste nunca se representa.

Diseños fluidos primero

El reflejo es llegar a las reglas especiales de teléfono de inmediato, pero gran parte de la capacidad de respuesta viene gratis antes de que escribas una sola. Si construyes con valores fluidos, los que se estiran y encogen con el espacio, el diseño ya se adapta.

Dos hábitos llevan la mayor parte. Establece anchos como porcentajes para que una caja tome una parte de su contenedor en lugar de un número fijo de píxeles, y usa max-width para que algo pueda encogerse en una pantalla pequeña pero nunca crezca más allá de un tamaño de lectura cómodo en una grande:

css
.container {
  width: 90%;              /* toma el 90% del espacio que tiene */
  max-width: 60rem;        /* pero nunca más ancho que 60rem en pantallas grandes */
  margin: 0 auto;          /* centrado */
}

En un teléfono este contenedor es el 90% de una pantalla angosta. En un monitor deja de crecer a 60rem y se sienta centrado. No escribiste una regla de teléfono; los valores hicieron la adaptación.

Antes de media queries, construye el diseño con valores fluidos para que se flexione por sí solo. Las unidades relativas y porcentajes permiten que los elementos tomen una parte de su contenedor en lugar de un tamaño fijo, y flexbox y grid ya refluyen a sus hijos mientras el espacio cambia. Un buen diseño fluido necesita muchos menos puntos de quiebre que uno rígido, porque no está luchando contra la pantalla en primer lugar.

Recurre a media queries solo después de que el diseño fluido deje de funcionar. Los porcentajes y max-width manejan el ancho, y un patrón de grid maneja el caso común de pared de tarjetas sin ninguna consulta en absoluto:

css
.card-grid {
  display: grid;
  gap: 1.5rem;
  /* tantas columnas como quepan a un mínimo de 16rem, compartiendo el espacio sobrante equitativamente */
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
}

repeat(auto-fit, minmax(16rem, 1fr)) dice "cabe tantas columnas como puedas a un mínimo de 16rem cada una, luego estíralas para llenar la fila". Tres columnas en una pantalla ancha, dos en una tableta, una en un teléfono, y ni una sola media query. Qué unidades relativas preferir para estos valores se cubre en unidades de tamaño.

Los diseños responsivos más fuertes son mayormente fluidos antes de que una sola media query se escriba, porque un punto de quiebre es un salto discreto y la mayoría del trabajo es continuo. Los porcentajes, max-width, y el tamaño intrínseco construido en flexbox y grid permiten que el diseño siga la ventana gráfica suavemente, y las media queries entonces manejan solo los puntos donde el diseño realmente necesita cambiar de forma, no cada píxel de redimensionamiento en medio.

El patrón que justifica su lugar es el grid que se ajusta a sí mismo, porque colapsa un conjunto entero de puntos de quiebre en una declaración:

css
.card-grid {
  display: grid;
  gap: 1.5rem;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
}

minmax(16rem, 1fr) le da a cada pista un piso de 16rem y un techo de una parte igual del espacio libre, y auto-fit crea tantas pistas como quepan en ese piso, luego las expande para llenar la fila. El conteo de columnas sale del ancho del contenedor automáticamente, así que un diseño que habría tomado tres puntos de quiebre no toma ninguno. Una nota de precisión que vale la pena recordar: auto-fit colapsa pistas vacías para que los elementos presentes se estiren para llenar la fila, mientras que auto-fill mantiene las pistas vacías reservadas, así que elige auto-fit cuando quieras que los elementos crezcan en el espacio sobrante y auto-fill cuando quieras un grid estable. Ver unidades de tamaño para cómo estos valores rem y fr se resuelven.

JunoDiseños fluidos primero Gran parte de la capacidad de respuesta es gratis antes de que escribas ninguna regla especial: usa porcentajes para que las cajas tomen una parte de su espacio, y max-width para que se encojan en teléfonos sin estirarse demasiado en monitores. Esos dos valores adaptan el diseño por sí solos. Construye fluido primero, y necesitarás muchas menos de las reglas específicas para teléfono que vienen después.
JunoDiseños fluidos primero Construye fluido antes de construir puntos de quiebre: porcentajes y max-width manejan el ancho, y flexbox y grid ya refluyen por sí solos. La única línea de grid para recordar es repeat(auto-fit, minmax(16rem, 1fr)), que te da una pared de tarjetas responsiva sin media queries. Recurre a una consulta solo una vez que el diseño fluido realmente deje de funcionar.
JunoDiseños fluidos primero Un punto de quiebre es un salto discreto, pero el redimensionamiento es continuo, así que deja que los porcentajes, max-width, y el tamaño intrínseco de flex y grid lleven la parte suave y reserva las media queries para cambios de forma real. repeat(auto-fit, minmax(16rem, 1fr)) colapsa varios puntos de quiebre en una línea. Recuerda que auto-fit colapsa pistas vacías para estirar tus elementos, mientras que auto-fill las mantiene reservadas.

Media queries

A veces los valores fluidos no son suficientes y necesitas que el diseño realmente cambie a cierto tamaño, por ejemplo un menú que se apila verticalmente en un teléfono pero se sienta en una fila en un escritorio. Eso es para lo que sirve una media query: un bloque de CSS que solo se aplica cuando la pantalla cumple una condición que estableces.

Comienza con los estilos de pantalla pequeña como tu CSS normal, luego agrega una consulta que superponga los cambios de pantalla más ancha:

css
.nav {
  display: flex;
  flex-direction: column;   /* apilado en pantallas pequeñas */
}

@media (min-width: 40rem) {
  .nav {
    flex-direction: row;    /* uno al lado del otro una vez que hay espacio */
  }
}

La regla dentro de @media (min-width: 40rem) solo se activa una vez que la pantalla tiene al menos 40rem de ancho. Por debajo de eso, se aplica la regla plana .nav y el menú se apila.

Una media query envuelve un conjunto de reglas en una condición, más a menudo una prueba de ancho, y esas reglas se aplican solo cuando la condición se mantiene. El patrón a adoptar es mobile-first: escribe tus estilos base para la pantalla más pequeña sin ninguna consulta en absoluto, luego superpone mejoras hacia arriba con min-width.

css
.layout {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr;      /* base: una sola columna, pantallas pequeñas */
}

@media (min-width: 40rem) {
  .layout {
    grid-template-columns: 1fr 1fr; /* dos columnas una vez que hay espacio */
  }
}

Mobile-first importa por más que la limpieza. Tus estilos base son los que siempre se aplican, así que hacerlos el diseño más simple y confiable significa que los dispositivos más pequeños y limitados obtienen la experiencia más segura por defecto, y cada consulta solo agrega capacidad. Construirlo al revés, desktop-first con consultas max-width que quitan cosas, tiende a dejar la vista móvil como una idea tardía que se rompe.

Una media query aplica un bloque de reglas solo cuando una condición de media se evalúa como verdadera, y para el diseño responsivo esa condición es casi siempre una prueba de ancho de ventana gráfica. La disciplina que se mantiene es mobile-first: estilos base sin condiciones que describen el diseño angosto, y cada consulta min-width es puramente aditiva sobre ellos.

css
.layout {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr;       /* base, se aplica en todas partes */
}

@media (min-width: 40rem) {         /* tableta y superior */
  .layout { grid-template-columns: 1fr 1fr; }
}

@media (min-width: 64rem) {         /* escritorio y superior */
  .layout { grid-template-columns: 1fr 2fr 1fr; }
}

La razón para preferir min-width aditivo sobre max-width sustractivo es la cascada. Porque estas consultas comparten especificidad, las que se disparan más tarde anulan las anteriores, así que ordenarlas de pequeño a grande significa que cada punto de quiebre más ancho gana limpiamente donde se aplica. Dos precisiones que vale la pena mantener: prefiere rem sobre px en la condición para que el punto de quiebre siga el tamaño de fuente del usuario, y sabe que las consultas de ancho leen la ventana gráfica de diseño, que solo es correcta porque la etiqueta de meta de ventana gráfica la fijó al ancho del dispositivo. Una consulta max-width extraviada en medio de una pila min-width es la causa usual de una regla que misteriosamente deja de aplicarse, porque está luchando contra el orden en lugar de extenderlo.

JunoMedia queries Una media query es un bloque de CSS que solo se activa cuando la pantalla cumple una condición, como tener al menos 40rem de ancho. Escribe tus estilos de pantalla pequeña como CSS normal primero, luego usa @media (min-width: ...) para agregar los cambios para pantallas más grandes. De esa manera la vista de teléfono es tu punto de partida, no un parche unido después.
JunoMedia queries Las media queries aplican reglas solo cuando una condición, generalmente un ancho, se mantiene verdadera. Comienza con mobile-first: estilos base sin consulta para la pantalla más pequeña, luego superpone con min-width para que cada consulta solo agregue. Construyelo al revés con max-width y la vista móvil tiende a terminar siendo la idea tardía rota.
JunoMedia queries Mobile-first significa estilos base sin condiciones para el diseño angosto y consultas min-width aditivas apiladas de pequeño a grande, así que la cascada resuelve cada punto de quiebre limpiamente. Usa rem en la condición para que siga el tamaño de fuente del usuario, y recuerda que las consultas de ancho leen la ventana gráfica de diseño que la etiqueta de meta fijó. Un max-width solitario en una pila min-width es la razón clásica por la que una regla silenciosamente deja de aplicarse.

Elegir puntos de quiebre

Un punto de quiebre es el ancho donde una media query se activa y el diseño cambia. La forma tentadora de elegir uno es buscar el ancho de un teléfono o tableta popular y hacerlo coincidir. Esa es la trampa. Hay cientos de tamaños de dispositivos, cambian cada año, y perseguirlos es un juego que no puedes ganar.

La pregunta mejor es: ¿a qué ancho este diseño empieza a verse mal? Amplía tu navegador lentamente y observa. Cuando una línea de texto se pone demasiado larga para leerla cómodamente, o dos columnas se ponen demasiado estrechas, ese es donde un punto de quiebre pertenece, cualquiera que sea el número que resulte ser.

css
/* Punto de quiebre elegido porque el texto se puso demasiado ancho aquí, */
/* no porque un teléfono resulte ser de este tamaño */
@media (min-width: 45rem) {
  .article { max-width: 38rem; }
}

Un punto de quiebre es el ancho de ventana gráfica en el que cambias el diseño. Elige uno observando tu propio contenido, no haciendo coincidir nombres de dispositivos. Los números redondos como "768px porque eso es un iPad" suenan autorizados y son una trampa: el panorama de dispositivos cambia constantemente, y un diseño afinado para los tamaños populares del año pasado se rompe en los del este año.

Deja que el contenido decida. Cambia el tamaño de la ventana y agrega un punto de quiebre en el ancho donde el diseño realmente se estira, una línea que se pone demasiado larga, una tarjeta que se aprieta demasiado, un nav que se queda sin espacio. Generalmente necesitarás solo dos o tres en todo el sitio:

css
/* Impulsado por contenido: esta línea llegó a ~75 caracteres y se volvió difícil de leer */
@media (min-width: 42rem) {
  .prose { max-width: 65ch; }   /* tapa la medida una vez que hay espacio */
}

/* Impulsado por contenido: el diseño de barra lateral solo justifica su espacio aquí */
@media (min-width: 60rem) {
  .page { grid-template-columns: 16rem 1fr; }
}

Un punto de quiebre es donde el diseño cambia de forma, y la forma duradera de elegir uno es dejar que el contenido lo establezca en lugar de una hoja de especificaciones de dispositivos. Hacer coincidir anchos de dispositivos nombrados es frágil por una razón estructural: la población de tamaños de pantalla es grande y deriva cada año, así que cualquier diseño vinculado a dimensiones de dispositivos específicas está vinculado a un objetivo móvil y se pudre en el horario. Un punto de quiebre justificado por el contenido, "la medida pasó una longitud de línea legible aquí", permanece justificado sin importar qué hardware se envíe después.

En la práctica eso significa redimensionar hasta que el diseño se estira y colocar un punto de quiebre allí, y significa que la mayoría de los sitios necesitan solo un pequeño puñado:

css
/* Tapa la medida donde las líneas cruzan una longitud legible, ~65 caracteres */
@media (min-width: 42rem) {
  .prose { max-width: 65ch; }
}

/* Introduce la barra lateral solo donde la columna principal puede ahorrar el ancho */
@media (min-width: 60rem) {
  .page { grid-template-columns: 16rem 1fr; }
}

El movimiento avanzado es apoyarse en clamp() para tipo y espaciado fluido para que necesites menos puntos de quiebre en absoluto. clamp(min, preferred, max) elige un valor que escala con la ventana gráfica pero está acotado en ambos extremos, así que los encabezados y espacios crecen suavemente en lugar de saltar en cada consulta:

css
h1 {
  /* nunca por debajo de 1.75rem, nunca por encima de 3rem, fluido en medio */
  font-size: clamp(1.75rem, 4vw + 1rem, 3rem);
}

Eso cubre la mayoría del escalado tipográfico sin ningún punto de quiebre en absoluto; ver unidades de tamaño para cómo el término vw se resuelve y tipografía para el lado de escala de tipo. Tres herramientas relacionadas redondean esto. Las consultas de contenedor diseñan un componente por el ancho de su propio contenedor en lugar de la ventana gráfica, así que una tarjeta puede reaccionar a la columna en la que se sienta en lugar de la página completa, que es la contraparte basada en componentes a las media queries basadas en ventana gráfica. La consulta prefers-reduced-motion te permite cortar la animación para lectores que le pidan a su sistema reducirla, y prefers-color-scheme te permite respetar una preferencia de luz u oscuridad del sistema, ambas escritas como media queries:

css
@media (prefers-reduced-motion: reduce) {
  * { animation: none; transition: none; }  /* respeta la configuración del OS */
}

@media (prefers-color-scheme: dark) {
  body { background: #111; color: #eee; }
}

Para imágenes específicamente, la capacidad de respuesta se mueve al HTML: el atributo srcset permite que el navegador elija un archivo de tamaño apropiado por pantalla, que el capítulo de imágenes responsivas de HTML cubre en lugar de CSS.

JunoElegir puntos de quiebre Un punto de quiebre es el ancho donde tu diseño cambia, y la trampa es elegirlo para hacer coincidir un teléfono o tableta específicos. Hay demasiados tamaños de dispositivos para perseguir, y cambian cada año. Amplía tu navegador lentamente y agrega un punto de quiebre donde el diseño realmente empieza a verse mal, cualquiera que sea el número que resulte ser.
JunoElegir puntos de quiebre Deja que el contenido elija tus puntos de quiebre, no nombres de dispositivos: una línea que se pone demasiado larga o una tarjeta que se aprieta demasiado es la señal real, y los anchos de dispositivos redondos como 768px son un objetivo móvil que se pudre. Cambia el tamaño hasta que el diseño se estire, y pon el punto de quiebre allí. La mayoría de los sitios necesitan solo dos o tres en todo.
JunoElegir puntos de quiebre Los puntos de quiebre impulsados por contenido sobreviven porque la población de pantallas deriva cada año, así que cualquier cosa vinculada a dimensiones de dispositivos se pudre en el horario. Apóyate en clamp() para tipo y espaciado fluido para necesitar menos puntos de quiebre en absoluto, ten en mente las consultas de contenedor para el diseño a nivel de componente en lugar de nivel de ventana gráfica, y respeta prefers-reduced-motion y prefers-color-scheme. Para imágenes, la capacidad de respuesta vive en HTML srcset, no CSS.