Tres horas. Media hora para entender cómo coloca el navegador cuando no le dices nada y cómo se razona un Flexbox, y dos horas y media rompiendo el flujo a propósito y construyendo los componentes de tu sitio.
Hoy · Hoja de ruta
- 1. Aprende: Cómo coloca el navegador los elementos por defecto, qué pasa cuando sacas uno de ese flujo, y los dos ejes con los que se razona cualquier Flexbox.
- 2. Haz: Experimenta con
displayyposition, convierte tu navegación en un Flexbox y construye tres componentes justificando cada decisión. - 3. Comprueba: Sabes decir para cada componente cuál es su eje principal, y nada desborda a 360 px.
Antes de empezar · 5 minutos, sin apuntes
- ¿Qué problema resuelve una custom property?
- ¿En qué se diferencia un valor fijo de uno limitado con
clamp()? - Predice qué cambia si sustituyes
var(--color-principal)en la declaración de:root.
Se explica
25 minutos · conceptos y demostración
Antes de colocar nada conviene saber cómo se coloca solo. Después, dos formas de intervenir: sacar un elemento del flujo, que se usa poco y para cosas concretas, y repartir el espacio de una línea, que es Flexbox y se usa constantemente.
Antes de Flexbox y Grid está el flujo normal
Flujo normal
La forma en que el navegador coloca los elementos por defecto: unos detrás de otros, siguiendo el orden del documento. Todo lo que veremos después son maneras de modificarlo, no de sustituirlo.
Merece la pena entenderlo porque el flujo normal ya resuelve bien muchas cosas. Un artículo con sus párrafos y sus encabezados, uno debajo de otro y ocupando el ancho disponible, no necesita nada.
| Comportamiento | Qué hace | Elementos típicos |
|---|---|---|
| Bloque | Ocupa todo el ancho disponible y empieza en una línea nueva | div, section, article, p, h1 |
| En línea | Ocupa solo lo que mide su contenido y se coloca dentro del texto | a, strong, em, span, img |
display: block; /* fuerza el comportamiento de bloque */
display: inline; /* fuerza el de línea */
display: inline-block; /* fluye como texto, pero acepta ancho, alto y márgenes verticales */
display: none; /* lo saca del documento por completo */
display: flex; /* lo de hoy */
display: grid; /* la sesión que viene */
inline-block resuelve la limitación clásica: a un elemento en línea no puedes darle width ni márgenes verticales útiles. Con inline-block sí, y sigue colocándose en la misma línea que su texto.
display: none no es «invisible»
Elimina el elemento del documento: no ocupa espacio y tampoco existe para un lector de pantalla ni para el recorrido con Tab. Eso es correcto cuando quieres ocultar algo de verdad, y es un error cuando solo querías que no se viera.
Si necesitas que algo siga estando disponible para quien no ve la pantalla, existen otras técnicas. Si la intención era únicamente que ocupara su hueco sin verse, eso es visibility: hidden o una opacidad, no display: none.
Sacar un elemento del flujo
position: static; /* el valor por defecto: sigue el flujo */
position: relative; /* sigue ocupando su hueco, pero se desplaza respecto a él */
position: absolute; /* sale del flujo y se coloca respecto a su ancestro posicionado */
position: fixed; /* sale del flujo y se coloca respecto al viewport */
position: sticky; /* sigue el flujo hasta llegar a un límite, y entonces se queda */
La distinción que importa es si el elemento deja o no su hueco:
| Valor | ¿Deja hueco? | Consecuencia |
|---|---|---|
relative |
Sí | Se mueve, pero los demás siguen contando con él |
absolute |
No | Los demás ocupan su sitio como si no existiera |
fixed |
No | Igual, y además no se mueve al hacer scroll |
sticky |
Sí | Se comporta normal hasta que toca su límite |
relative casi nunca se usa para mover nada: se usa para crear el punto de referencia al que un absolute hijo se agarrará.
.card { position: relative; }
.card .etiqueta{ position: absolute; top: 0; right: 0; }
No se maqueta con position: absolute
Colocar cada bloque de la página con coordenadas parece que funciona, y es la maqueta más frágil que existe: los elementos ya no saben nada unos de otros, así que en cuanto un texto crece se solapan, y en una pantalla más estrecha todo queda fuera de sitio.
absolute es para lo que de verdad es posicionamiento: una etiqueta de «oferta» sobre una esquina, un icono dentro de un campo. La distribución de la página se hace con Flexbox y con Grid.
Cuando algo no cabe, overflow decide qué se ve:
overflow: visible; /* por defecto: el contenido se sale y se ve */
overflow: auto; /* aparece barra de scroll si hace falta */
overflow: hidden; /* se recorta lo que no cabe */
overflow: hidden es tentador cuando algo desborda, y muchas veces es tapar el problema en lugar de resolverlo: el contenido sigue sin caber, ahora además no se puede leer. Donde sí es la respuesta correcta es en contenido que legítimamente es más ancho que la pantalla, como una tabla de datos: ahí overflow-x: auto en un contenedor le da su propia barra de scroll sin romper la página.
Flexbox distribuye en una dimensión
Flexbox distribuye elementos en una línea: o en fila, o en columna. Ese es el criterio para elegirlo, y lo veremos enfrentado a Grid en la sesión 4.
En la UD1 dejaste el menú así:
<nav aria-label="Navegación principal">
<ul>
<li><a href="index.html">Inicio</a></li>
<li><a href="productos.html">Productos</a></li>
</ul>
</nav>
Con dos declaraciones deja de ser una lista vertical, sin tocar el HTML:
nav ul {
display: flex;
gap: 1rem;
list-style: none;
padding: 0;
margin: 0;
}
display: flex cambia la distribución; gap crea únicamente el espacio entre enlaces.
Los dos ejes
flex-direction: row- Eje principal · horizontal
- Eje transversal · vertical
Todo Flexbox tiene un eje principal, que es por donde se colocan los elementos, y un eje transversal, el perpendicular. Cuál es cuál lo decide flex-direction:
flex-direction: row; /* por defecto: principal horizontal */
flex-direction: column; /* principal vertical */
La confusión que te va a pasar
justify-content siempre actúa sobre el eje principal y align-items sobre el transversal. No sobre «horizontal» y «vertical».
Por eso, en cuanto pones flex-direction: column, las dos se intercambian: justify-content pasa a mover en vertical y align-items en horizontal. Cuando algo no se alinee como esperas, la primera pregunta es cuál es ahora el eje principal.
.barra {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
gap: 1rem;
flex-wrap: wrap;
}
| Propiedad | Qué hace |
|---|---|
justify-content |
Reparte el espacio sobrante en el eje principal |
align-items |
Alinea los elementos en el eje transversal |
gap |
Separación entre elementos, sin márgenes ni el último elemento sobrando |
flex-wrap |
Permite que los elementos salten de línea cuando no caben |
gap
La separación entre elementos de un contenedor Flexbox o Grid. Sustituye a los márgenes y evita su problema clásico: no deja un margen sobrante en el último elemento, y no sufre el colapso de márgenes.
En los hijos, flex resume cuánto puede crecer un elemento, cuánto encogerse y cuál es su tamaño de partida:
.logo { flex: 0 0 auto; } /* no crece, no se encoge, mide lo que mida */
.buscador{ flex: 1; } /* se queda con todo el espacio sobrante */
margin-left: auto en un hijo también tiene un efecto muy útil: empuja ese elemento y todos los siguientes hasta el final del eje. Es la forma limpia de separar un grupo del resto en una barra.
El método, en tres preguntas
Cuando te enfrentes a un componente, no busques la propiedad: contesta esto.
- ¿Qué elementos tengo que colocar en una misma línea?
- ¿En qué dirección van: fila o columna? Ese es el eje principal
- ¿Qué hago con el espacio que sobra en ese eje, y cómo alineo en el otro?
Con eso, justify-content y align-items dejan de ser prueba y error.
Se trabaja
150 minutos · laboratorio y componentes de tu proyecto
El paso 1 se hace en un archivo de pruebas, no sobre el proyecto: conviene romper cosas en un sitio donde romperlas no cueste nada. A partir del paso 2 se trabaja sobre el sitio.
Paso 1 · Rompe el flujo · 30 min
Crea un archivo de pruebas laboratorio.html con cuatro cajas de colores, una debajo de otra, y experimenta. Para cada apartado anota qué le pasa a la caja y, sobre todo, qué le pasa al hueco que ocupaba.
- Cambia la segunda a
display: inline. ¿Por qué deja de hacer caso alwidth? - Cambia la segunda a
display: inline-block. ¿Qué recupera? - Ponle
position: relativey desplázala contop: 20px. ¿Se han movido las demás? - Ponle
position: absolutecontop: 0; right: 0. ¿Respecto a qué se ha colocado? Ahora daleposition: relativea su contenedor y observa la diferencia. - Ponle
position: sticky; top: 0a la primera y haz scroll. - Ponle
display: nonea la tercera y compáralo convisibility: hidden.
| Apartado | Qué le pasa al elemento | Qué le pasa a su hueco |
|---|---|---|
Estoy atascado · mi absolute se va a la esquina de la pantalla
Un elemento absolute se coloca respecto a su ancestro posicionado más cercano, y si no encuentra ninguno, respecto al documento entero. Por eso acaba en la esquina de la página en lugar de en la de su tarjeta.
La solución es la del ejemplo: darle position: relative al contenedor que quieres que sirva de referencia. Es prácticamente el único uso de relative que verás en código profesional.
Paso 2 · La navegación de tu sitio · 30 min
Transforma la cabecera de tus cuatro páginas:
- La navegación en fila, con separación mediante
gapy sin viñetas. - El nombre del sitio a un lado y el menú al otro, en la misma línea.
- Los dos bloques alineados verticalmente entre sí.
flex-wrappara que el menú no desborde cuando falte espacio.- Comprueba a 360 px de ancho en DevTools que nada se sale de la pantalla.
Lo que no vale
Nada de margin-left: 73px para colocar cada elemento en su sitio. Si un número así aparece en tu CSS, significa que has medido la pantalla en la que estás mirando: en otra estará mal.
La forma de colocar en Flexbox es decir cómo se reparte el espacio, no dónde va cada cosa.
Estoy atascado · align-items: center no centra nada
Comprueba dos cosas, en este orden:
- Que lo has puesto en el contenedor, no en los hijos.
justify-contentyalign-itemsvan siempre en el elemento que tienedisplay: flex. - Cuál es el eje principal. Si has puesto
flex-direction: column, para centrar en vertical necesitasjustify-content, noalign-items.
Y usa el inspector de Flexbox: junto al elemento aparece un icono flex en DevTools que dibuja los ejes y el espacio libre.
Paso 3 · Tres casos razonados · 20 min
Reproduce los tres, aplicando el método de las tres preguntas antes de escribir ninguna propiedad.
3.1 · Una botonera
<div class="acciones">
<button type="submit">Guardar</button>
<button type="button">Cancelar</button>
</div>
- ¿Qué coloco?
- Dos botones, uno al lado del otro.
- ¿Eje principal?
- Fila. Es el valor por defecto, así que no hace falta escribir
flex-direction. - ¿Y el espacio sobrante?
- Depende de lo que quiera: pegados a la izquierda es
flex-start; a la derecha, como en un formulario, esflex-end.
.acciones {
display: flex;
justify-content: flex-end;
gap: var(--space-sm);
}
3.2 · Una tarjeta horizontal
┌───────────────────────────────────┐
│ imagen │ título │
│ │ descripción │
│ │ precio botón │
└───────────────────────────────────┘
Aquí hay dos Flexbox anidados, y verlo es media solución:
- Uno exterior en fila: imagen a un lado, información al otro.
- Uno interior en columna dentro de la información: título, descripción y la línea del precio.
- Un tercero en fila para esa última línea, con el precio a la izquierda y el botón a la derecha.
.producto { display: flex; gap: var(--space-md); }
.producto__datos { display: flex; flex-direction: column; gap: var(--space-xs); }
.producto__pie { display: flex; justify-content: space-between; align-items: center; }
Anidar contenedores es normal y no es un síntoma de nada malo. Cada uno resuelve una dimensión.
3.3 · Centrar
El problema con más recetas copiadas de internet de toda la historia de CSS. Con Flexbox son dos líneas, pero conviene entenderlas:
.caja {
display: flex;
justify-content: center; /* centra en el eje principal */
align-items: center; /* centra en el transversal */
}
Centrar es simplemente centrar en los dos ejes a la vez. Si solo necesitas uno, solo escribes uno.
Paso 4 · Los tres centrados · 10 min
Tienes tres cajas, cada una con un cuadrado dentro. Consigue, sin position y sin márgenes fijos:
- El cuadrado centrado en horizontal, arriba del todo.
- El cuadrado centrado en vertical, pegado a la derecha.
- El cuadrado centrado en los dos ejes.
Ver respuesta
Con display: flex y dirección por defecto (fila):
1 · justify-content: center; y nada más: el eje principal es el horizontal, y sin align-items el hijo se queda arriba si tiene altura propia.
2 · justify-content: flex-end; align-items: center;
3 · justify-content: center; align-items: center;
Y la comprobación de que lo has entendido: con flex-direction: column, los tres se resuelven intercambiando las dos propiedades.
Paso 5 · Flexbox Challenge · 45 min
Es el trabajo central de la sesión. Construye estos tres componentes usando solo Flexbox, y aplícalos a tu proyecto donde encajen:
A · La barra de cabecera, con el nombre del sitio a la izquierda, la navegación a la derecha y todo alineado verticalmente.
B · La tarjeta horizontal del paso 3.2, que debe seguir funcionando cuando la descripción sea el doble de larga.
C · Una línea de metadatos —fecha, autor, categoría— separada por gap, que salte de línea con elegancia cuando no quepa.
Para cada uno responde por escrito:
| Componente | Eje principal | Por qué ese justify-content |
Por qué ese align-items |
¿Necesitó flex-wrap? |
|---|---|---|---|---|
| A | ||||
| B | ||||
| C |
Esa tabla es la tarea. El CSS lo puede escribir cualquiera copiando; la tabla solo la puede rellenar quien ha entendido los ejes.
Paso 6 · Revisión cruzada de una decisión · 15 min
Intercambia con un compañero únicamente una sección que ya hayas maquetado. Encuentra una decisión de layout que no puedas justificar y descríbela así:
- Qué intenta resolver: tamaño, espacio, distribución o estado.
- Qué regla actúa: compruébala en DevTools.
- Qué duda queda: por qué Flexbox, Grid o el flujo normal podrían encajar mejor.
El autor decide si cambia el código o conserva la decisión y la justifica. No se valora la coincidencia de criterio estético entre ambas partes.
Ampliación si has completado el trabajo
Primero termina y comprueba los seis pasos. El primer reto se resuelve sin escribir CSS, y es el más difícil de los dos.
Reto 1 · Antes de la herramienta, la pregunta
Para cada uno de estos seis casos, decide si lo resolverías con el flujo normal, con Flexbox, o si necesitarás algo que todavía no hemos visto. Escribe la respuesta y el motivo antes de probar nada.
- Un artículo de blog: título, párrafos, una imagen y más párrafos.
- Una barra de cabecera con logotipo, buscador que ocupa el resto y dos iconos a la derecha.
- Una galería de doce fotos en cuadrícula regular, alineadas en filas y columnas.
- Una lista de etiquetas de longitud variable que fluyen y saltan de línea.
- Una ficha con la foto a la izquierda y cinco datos a la derecha, uno bajo otro.
- El esqueleto de una página: cabecera arriba, barra lateral, contenido y pie.
Dos de los seis no son trabajo de Flexbox, y uno no necesita ninguna herramienta. Identifícalos y explica por qué. Después comprueba tus respuestas construyendo los que puedas con lo que ya sabes, y deja anotados los que tengas que aplazar hasta la sesión 4.
Reto 2 · La barra que no cabe
Una cabecera tiene cuatro elementos: el nombre del sitio, un menú de cinco enlaces, un buscador y un menú de usuario. A 1400 px caben todos en una línea; a 360 px, no caben ni de lejos.
Construye una cabecera que degrade con dignidad sin una sola media query y sin ocultar nada con display: none. Solo puedes usar flex-wrap, gap, flex en los hijos, min-width y max-width.
- Decide qué elemento se queda con el espacio sobrante cuando sobra, y cuál cede primero cuando falta. Justifícalo.
- Consigue que el buscador nunca baje de una anchura utilizable, en lugar de encogerse hasta ser inservible.
- Anota las tres anchuras en las que la barra cambia de disposición. No las has escrito tú: las decide el contenido. Eso es exactamente lo que discutiremos en la sesión 4 al hablar de breakpoints.
- Comprueba que en ninguna anchura entre 320 y 1600 px aparece una barra de scroll horizontal.
Cierre
5 minutos · comprobación y recuerdo
Lista de verificación de la sesión
- Sabes identificar el eje principal de cualquier Flexbox.
- Sabes que
justify-contentyalign-itemsse intercambian al cambiar la dirección. - Usas
gapen lugar de márgenes para separar. - Tu navegación funciona a 360 px sin desbordar.
- No hay ningún valor en píxeles colocando elementos a mano.
- La tabla de ejes de los tres componentes está rellenada y justificada.
Antes de cerrar · 3 minutos, sin mirar
- ¿Qué diferencia hay entre
relativeyabsoluterespecto al hueco? - ¿Por qué
display: noneno es lo mismo que «no se ve»? - ¿Sobre qué eje actúa
justify-content? - ¿Qué le pasa a
align-itemssi cambias aflex-direction: column? - Enuncia las tres preguntas con las que se razona un Flexbox.
- ¿Qué hace
margin-left: autoen un hijo de un Flexbox?
Ver respuestas
1 · relative sigue ocupando su hueco aunque se desplace; absolute sale del flujo y los demás elementos ocupan su sitio.
2 · Porque lo elimina del documento: deja de existir también para los lectores de pantalla y para el recorrido con Tab.
3 · Sobre el eje principal, sea cual sea su dirección.
4 · Pasa a alinear en horizontal, porque el eje transversal ahora es el horizontal.
5 · Qué elementos van en la misma línea, en qué dirección —ese es el eje principal— y qué hago con el espacio sobrante y con la alineación en el otro eje.
6 · Absorbe todo el espacio sobrante por ese lado, empujando ese elemento y los siguientes al final del eje.
Microprueba semanal 3 · 5–10 minutos
Individual, sin IA y sin apuntes.
- Elige cuáles resolverías con Flexbox: navegación, botonera, tabla de datos y tarjeta horizontal.
- Escribe únicamente el CSS imprescindible para una botonera que pueda saltar de línea.
- Predice qué cambia al pasar de
rowacolumn.