Ya sabes seleccionar cualquier elemento y darle color, tamaño y tipografía. Pero hay algo que has estado dando por sentado en cada playground: cómo se colocan las cajas en la página sin que toques nada. Antes de aprender a alinearlas con Flexbox o a distribuirlas con Grid, hay que entender ese comportamiento por defecto. Es el cimiento que esos dos capítulos dan por sabido.
El flujo normal#
Cuando el navegador pinta una página, coloca cada elemento siguiendo una regla sencilla, sin que tú hagas nada: el flujo normal. Los elementos aparecen en el mismo orden en que están en el HTML, de arriba abajo. No hay layout todavía; solo cajas que se apilan o fluyen según su naturaleza.
Esa “naturaleza” es lo que cambia entre dos grandes familias de elementos: los de bloque y los de en línea.
Elementos de bloque y en línea#
De bloque#
Un elemento de bloque se comporta como un párrafo: empieza en una línea nueva y ocupa todo el ancho disponible de su contenedor, aunque su contenido sea corto. Por eso dos de ellos seguidos quedan uno debajo del otro.
Son de bloque, entre otros: <div>, <p>, <h1>–<h6>, <section>, <header>,
<footer>, <ul>, <li>, <article>. Aceptan width y height: puedes fijar
su tamaño.
<p>Primer párrafo.</p>
<p>Segundo párrafo.</p>Aunque cada texto sea corto, el segundo párrafo aparece debajo del primero, porque cada uno ocupa una línea completa.
En línea#
Un elemento en línea fluye dentro del renglón, junto al texto. Solo ocupa el ancho de su contenido, y varios caben uno al lado del otro en la misma línea.
Son en línea, entre otros: <a>, <strong>, <em> y <span>. La clave:
no aceptan width ni height (los ignoran), y su relleno vertical no
empuja a los vecinos: se dibuja por encima de las líneas de alrededor.
<img> es la excepción que conviene tener presente: también fluye en línea, pero
es un elemento reemplazado (el navegador lo sustituye por la imagen) y sí
acepta width y height.
<p>Tracer está <strong>en línea</strong> ahora mismo.</p>El <strong> no rompe la frase: sigue dentro del párrafo, en su sitio. Eso es lo
correcto para un trozo de texto destacado. El problema aparece cuando quieres que
un elemento en línea se comporte como una cajita con tamaño propio —un chip, un
botón pequeño— y le pones relleno: se solapa con el texto, porque sigue siendo en
línea.
La propiedad display#
display es la propiedad que decide a qué familia pertenece una caja. Sus cuatro
valores básicos:
| Valor | Comportamiento |
|---|---|
block | Empieza en línea nueva, ocupa todo el ancho. Acepta tamaño. |
inline | Fluye en la línea, solo ocupa su contenido. Ignora width/height. |
inline-block | Fluye en la línea como el texto, pero respeta tamaño y relleno. |
none | Desaparece: sale del flujo y del render, no deja hueco. |
Cambiar display cambia el comportamiento, no el significado: un <span> sigue
siendo un <span> en el HTML aunque le pongas display: block. Eliges el valor
según cómo quieres que la caja se comporte en el flujo.
inline-block: lo mejor de los dos#
inline-block es el valor que más sorprende al principio y el más útil para
piezas pequeñas. El elemento fluye en la línea (varios caben en una fila,
como palabras), pero se comporta como una caja: respeta width, height y
el relleno, y su relleno vertical sí empuja.
.etiqueta {
/* fluye en línea con el texto, pero respeta tamaño y relleno */
display: inline-block;
/* espacio interior: da cuerpo al chip */
padding: 0.25rem 0.6rem;
/* fondo de color: hace visible la caja del chip */
background: #f1e5ec;
}Con esto, una serie de <span class="etiqueta"> se convierte en una fila de
chips bien formados, en lugar de un texto con fondos que se montan unos sobre
otros.
display: none (y por qué no es visibility: hidden)#
display: none quita el elemento por completo: ni se ve ni ocupa espacio, como
si no estuviera en el HTML. Es lo que usas para esconder algo que en esta vista
no debe aparecer.
Cuidado con confundirlo con visibility: hidden: este último también esconde
el elemento, pero su caja sigue en el flujo y deja un hueco vacío de su
tamaño. Si quieres que algo desaparezca sin dejar rastro, display: none; si
quieres reservar su sitio (raro), visibility: hidden.
Esto es el cimiento de Flexbox y Grid#
Aquí está la conexión que lo ata todo: cuando en los próximos capítulos escribas
display: flex o display: grid en un contenedor, estarás usando la misma
propiedad display. No son herramientas aparte: son dos valores más que
cambian cómo se colocan los hijos de ese contenedor. Por eso este capítulo va
antes: sin entender el flujo normal y display, Flexbox parece magia.
Y un apunte sobre algo que llevas viendo: el retrato circular del héroe centra sus
iniciales en vertical con un viejo truco de line-height (uno de los pocos casos en
que se le pone una unidad, igualándolo a la altura de la caja). No hace falta que lo
domines ahora —cuando lleguemos a Flexbox, centrar en vertical será una sola línea
directa y podrás olvidarte de ese truco—.
Pruébalo#
Cambia el valor de display en .item (la línea está señalada) entre block,
inline, inline-block y none, y observa qué le pasa a la fila de etiquetas.
Fíjate sobre todo en la diferencia entre inline (ignora el ancho, el relleno se
solapa) e inline-block (lo respeta todo).
Comprueba lo que sabes#
Pregunta 1 de 5
¿Qué hace un elemento de bloque (como `<div>` o `<p>`) por defecto, sin nada de CSS?
Tu turno#
La ficha de héroe tiene tres cajas con el display equivocado. Arréglalas aquí
mismo cambiando solo esa propiedad: las etiquetas y los botones deben fluir en
fila respetando su caja, y la biografía no debe ocupar sitio. Cuando lo tengas,
despliega las soluciones y compara el criterio detrás de cada decisión.
Ejercicio · en esta página
Arregla la ficha de héroe con display
La ficha compacta de un héroe ya tiene su HTML y sus colores, pero tres cajas tienen el display equivocado: las etiquetas y los botones se solapan por ser en línea, y la biografía ocupa sitio cuando no debería. Tu única herramienta es la propiedad display. Completa los tres TODO de starter/styles.css.
Paso 1: Que funcione
- Las etiquetas y los botones ya no solapan su relleno con el texto.
- La biografía no se muestra.
- Nada queda roto: la ficha se lee.
Paso 2: El display correcto
- `inline-block` en las etiquetas y en los botones: fluyen en fila y respetan su caja.
- `display: none` en la biografía: ni se ve ni deja hueco.
- No has tocado el `<span>` de estado: en línea es lo correcto ahí.
Paso 3: Con criterio
- Eliges cada `display` por comportamiento (apilar / fluir con tamaño / desaparecer), no por aspecto.
- Distingues `display: none` de `visibility: hidden` y sabes por qué aquí toca `none`.
- Reconoces que la fila perfectamente espaciada la dará `gap` de Flexbox en el próximo capítulo: hoy `inline-block` es lo correcto.
Ver soluciones
/* SOLUCIÓN OK — funciona, pero abusa de `block` y deja un hueco.
Todo se lee y nada está roto, pero las decisiones de display no son las
adecuadas: las cajas que deberían ir en fila se apilan, y la biografía
oculta sigue ocupando su espacio. */
body {
margin: 0;
font-family:
system-ui,
-apple-system,
"Segoe UI",
Roboto,
sans-serif;
background: #f7f6fb;
color: #1c1b22;
line-height: 1.5;
padding: 2rem;
}
.hero-card {
max-width: 22rem;
margin: 0 auto;
background: #fff;
border: 1px solid #e6e3ee;
border-radius: 12px;
padding: 1.5rem;
}
.hero-name {
font-size: 1.3rem;
margin: 0;
}
.estado {
font-size: 0.7rem;
text-transform: uppercase;
letter-spacing: 0.06em;
color: #2e7d32;
}
.hero-role {
font-size: 0.78rem;
text-transform: uppercase;
letter-spacing: 0.06em;
color: #5b5966;
margin: 0.2rem 0 1rem;
}
.etiqueta {
background: #f1e5ec;
color: #b8336a;
font-size: 0.75rem;
padding: 0.25rem 0.6rem;
border-radius: 999px;
margin: 0 0.3rem 0.3rem 0;
/* `block` arregla el solapamiento del relleno, pero ahora cada chip ocupa
su propia línea: una columna de pastillas en vez de una fila. */
display: block;
}
.bio {
color: #5b5966;
font-size: 0.9rem;
margin: 1rem 0 0;
/* `visibility: hidden` la esconde, pero su caja SIGUE en el flujo: queda un
hueco vacío del tamaño del párrafo. No es lo que queremos. */
visibility: hidden;
}
.acciones {
margin-top: 1.25rem;
}
.acciones a {
background: #b8336a;
color: #fff;
text-decoration: none;
font-size: 0.85rem;
padding: 0.5rem 0.9rem;
border-radius: 8px;
margin-right: 0.5rem;
/* Mismo problema que los chips: `block` respeta el relleno pero estira cada
botón a todo el ancho y los apila. No parece una fila de acciones. */
display: block;
} Por qué este nivel
- Resuelve los tres TODO y nada está roto: todo se lee. Ese es el mínimo.
- Usa `display: block` en chips y botones: respeta el relleno, pero los apila en columna y los estira a todo el ancho. No parece una fila.
- Oculta la biografía con `visibility: hidden`: desaparece a la vista, pero su caja sigue en el flujo y deja un hueco vacío del tamaño del párrafo.
/* SOLUCIÓN MEJOR — el display correcto en cada caja.
Los chips y los botones fluyen en fila respetando su caja (inline-block);
la biografía sale del flujo del todo (none), sin dejar hueco. */
body {
margin: 0;
font-family:
system-ui,
-apple-system,
"Segoe UI",
Roboto,
sans-serif;
background: #f7f6fb;
color: #1c1b22;
line-height: 1.5;
padding: 2rem;
}
.hero-card {
max-width: 22rem;
margin: 0 auto;
background: #fff;
border: 1px solid #e6e3ee;
border-radius: 12px;
padding: 1.5rem;
}
.hero-name {
font-size: 1.3rem;
margin: 0;
}
.estado {
font-size: 0.7rem;
text-transform: uppercase;
letter-spacing: 0.06em;
color: #2e7d32;
}
.hero-role {
font-size: 0.78rem;
text-transform: uppercase;
letter-spacing: 0.06em;
color: #5b5966;
margin: 0.2rem 0 1rem;
}
.etiqueta {
background: #f1e5ec;
color: #b8336a;
font-size: 0.75rem;
padding: 0.25rem 0.6rem;
border-radius: 999px;
margin: 0 0.3rem 0.3rem 0;
/* inline-block: fluye en fila como un texto, pero respeta su tamaño y su
relleno como una caja. Es el display de un chip. */
display: inline-block;
}
.bio {
color: #5b5966;
font-size: 0.9rem;
margin: 1rem 0 0;
/* none la quita del flujo Y del render: ni se ve ni deja hueco. */
display: none;
}
.acciones {
margin-top: 1.25rem;
}
.acciones a {
background: #b8336a;
color: #fff;
text-decoration: none;
font-size: 0.85rem;
padding: 0.5rem 0.9rem;
border-radius: 8px;
margin-right: 0.5rem;
/* Mismos motivos que los chips: en fila, respetando la caja. */
display: inline-block;
} Por qué es mejor que el anterior
- `inline-block` en chips y botones: fluyen en fila como el texto, pero respetan su tamaño y su relleno. Es el display de un chip o un botón pequeño.
- `display: none` en la biografía: la saca del flujo y del render, sin dejar hueco. A diferencia de `visibility: hidden`, que la escondería dejando su espacio reservado.
- Cada decisión es de comportamiento, no de aspecto: bloque para lo que se apila, inline-block para lo que fluye con tamaño, none para lo que no debe estar.
/* SOLUCIÓN EXCELENTE — el display correcto, entendiendo POR QUÉ y qué viene
después. El código de display coincide con el de "mejor": cuando hay una sola
respuesta correcta, lo que sube el nivel no es más CSS, sino el criterio.
- block / inline / inline-block / none NO se eligen por aspecto, sino por
comportamiento: ¿esta caja debe apilarse, fluir en la línea, fluir pero con
tamaño propio, o desaparecer del flujo?
- `.estado` se deja en línea a propósito: es texto dentro del título.
- El último botón arrastra un margin-right colgante y entre chips queda el
hueco propio de inline-block. Ninguno se arregla con display: la herramienta
limpia para una fila —espaciado uniforme, sin márgenes sueltos— es flexbox,
el próximo capítulo. Aquí inline-block es la respuesta correcta para hoy. */
body {
margin: 0;
font-family:
system-ui,
-apple-system,
"Segoe UI",
Roboto,
sans-serif;
background: #f7f6fb;
color: #1c1b22;
line-height: 1.5;
padding: 2rem;
}
.hero-card {
max-width: 22rem;
margin: 0 auto;
background: #fff;
border: 1px solid #e6e3ee;
border-radius: 12px;
padding: 1.5rem;
}
.hero-name {
font-size: 1.3rem;
margin: 0;
}
/* En línea a propósito: el estado es una palabra del propio título. */
.estado {
font-size: 0.7rem;
text-transform: uppercase;
letter-spacing: 0.06em;
color: #2e7d32;
}
.hero-role {
font-size: 0.78rem;
text-transform: uppercase;
letter-spacing: 0.06em;
color: #5b5966;
margin: 0.2rem 0 1rem;
}
.etiqueta {
background: #f1e5ec;
color: #b8336a;
font-size: 0.75rem;
padding: 0.25rem 0.6rem;
border-radius: 999px;
margin: 0 0.3rem 0.3rem 0;
/* Un chip fluye en la línea (como el texto) pero es una caja con tamaño:
ese híbrido es exactamente inline-block. */
display: inline-block;
}
.bio {
color: #5b5966;
font-size: 0.9rem;
margin: 1rem 0 0;
/* none, no visibility: la ficha compacta no debe reservar su espacio.
visibility la escondería dejando el hueco; none la saca del flujo. */
display: none;
}
.acciones {
margin-top: 1.25rem;
}
.acciones a {
background: #b8336a;
color: #fff;
text-decoration: none;
font-size: 0.85rem;
padding: 0.5rem 0.9rem;
border-radius: 8px;
margin-right: 0.5rem;
display: inline-block;
} Por qué es mejor que el anterior
- Mismo código de display que «mejor»: cuando solo hay una respuesta correcta, lo que sube el nivel es el criterio, no más CSS.
- Deja el `<span>` de estado en línea a propósito: es una palabra dentro del título. Saber qué NO tocar es parte del trabajo.
- Reconoce el límite: el margen colgante del último botón y el hueco entre chips de inline-block no se arreglan con `display`. La fila limpia —espaciado uniforme, sin márgenes sueltos— la dará `gap` de Flexbox, el próximo capítulo. Hoy, inline-block es lo correcto.