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

Visualización y flujo normal

docs.scrimba.com

Deja tres párrafos y un par de enlaces en una página sin ningún CSS y aún se distribuyen solos: los párrafos se apilan hacia abajo en la página, los enlaces se sientan dentro del texto donde los escribiste. Nadie le dijo al navegador que hiciera eso. Antes de que escribas una sola regla de diseño, ya existe un diseño, y cada técnica que utilices después es un cambio a ese diseño en lugar de comenzar desde cero. Este capítulo trata sobre ese punto de partida y la única propiedad que lo controla.

Flujo normal

Cuando un navegador diseña una página sin tu propio CSS de diseño, utiliza flujo normal: la forma predeterminada en que se distribuyen los elementos. Las cosas de bloque como los párrafos y encabezados se apilan de arriba hacia abajo, cada una en su propia línea. El texto y los enlaces corren dentro de una línea, de izquierda a derecha, ajustándose a la siguiente línea cuando se quedan sin espacio.

Ya has conocido las piezas que fluyen alrededor: este capítulo se basa en el modelo de caja, porque son esas cajas las que fluyen. El flujo normal vale la pena nombrarlo porque todo lo demás en el diseño se define contra él. Flexbox, grid y posicionamiento son todas formas de decir "distribuye estos de forma diferente al predeterminado", así que conocer el predeterminado es lo que hace que los cambios tengan sentido.

El flujo normal es el diseño predeterminado del navegador: la distribución que obtienes antes de que entre en juego flexbox, grid, float o posicionamiento. Las cajas de bloque se apilan verticalmente hacia abajo en la página en orden de origen, cada una comenzando en una nueva línea y tomando el ancho completo disponible. Las cajas inline fluyen a lo largo de la línea, de izquierda a derecha en un idioma de izquierda a derecha, ajustándose a la siguiente línea cuando la actual se llena.

La razón para nombrarlo es que las herramientas de diseño se definen como desviaciones de él. Cuando estableces display: flex en un contenedor, le estás diciendo al navegador que distribuya los hijos de ese contenedor según reglas flex en lugar de flujo normal. El predeterminado nunca desaparece; optas por sacar contenedores individuales de él. Esa es también la razón por la que un documento sin estilo sigue siendo legible: el flujo normal es un diseño real, no la ausencia de uno.

El flujo normal es el modo de diseño que el navegador aplica por defecto, antes de que floats, posicionamiento, flex o grid cambien algo. Tiene dos submodos trabajando juntos: diseño de bloque, que apila cajas de nivel de bloque verticalmente en orden de origen hacia abajo en la página, y diseño inline, que distribuye cajas de nivel inline horizontalmente dentro de una línea y las ajusta en cajas de línea. Una caja de bloque distribuida en flujo normal toma el ancho disponible completo y comienza en una nueva línea; una caja inline toma solo el ancho que su contenido necesita y se sienta dentro de la línea actual.

Nombrarlo con precisión importa porque todo el sistema de diseño se construye como un conjunto de alternativas a él. display: flex y display: grid reemplazan el diseño interno de un contenedor con reglas flex o grid, y position: absolute o un float saca una caja del flujo normal por completo para que el contenido circundante se distribuya como si no estuviera allí. En cada caso el flujo normal es la línea de base de la que te estás desviando, y una caja que no se saca explícitamente de él o se entrega a otro modo de diseño sigue fluyendo. Esta es la razón por la que un documento sin hoja de estilos se representa en un orden sensato: el flujo de bloque e inline es el predeterminado, no un respaldo.

JunoFlujo normal El flujo normal es el diseño que obtienes gratis: los bloques se apilan hacia abajo en la página, el texto y los enlaces corren a lo largo de la línea. Nadie lo activa, ya está allí antes de que escribas cualquier CSS. Todo lo demás en el diseño es un cambio a este predeterminado, así que ayuda a imaginar primero el predeterminado.
JunoFlujo normal El flujo normal es el predeterminado del navegador: los bloques se apilan de arriba a abajo en orden de origen, las cajas inline corren a lo largo de la línea y se ajustan. Flex, grid y posicionamiento son todas formas de optar un contenedor por fuera de él, nunca un reemplazo para él en todas partes a la vez. Una página sin estilo se lee bien porque el flujo normal es un diseño real, no la falta de uno.
JunoFlujo normal El flujo normal es diseño de bloque apilándose verticalmente más diseño inline corriendo a lo largo de la línea, aplicado por defecto antes de que nada más toque la caja. display: flex y display: grid intercambian el diseño interno de un contenedor, y float o position: absolute sacan una caja del flujo para que los hermanos la ignoren. Lo que no desvías sigue en flujo, que es por qué un documento sin hoja de estilos sigue representándose en orden.

Cajas de bloque y cajas inline

Los elementos vienen en dos sabores principales en flujo normal. Una caja de bloque toma el ancho completo de su contenedor y se apila en su propia línea, empujando el siguiente elemento hacia abajo. Un párrafo <p>, un encabezado <h1> y un <div> son todos bloques, que es por qué se alinean uno debajo del otro.

Una caja inline es diferente. Se sienta dentro de una línea de texto y toma solo el espacio que su contenido necesita, así que varios pueden compartir una línea. Un <span> o un enlace <a> es inline, que es por qué un enlace dentro de una oración se mantiene en el flujo de las palabras en lugar de saltar a su propia línea.

html
<p>Este párrafo es un bloque, así que se sienta en su propia línea.</p>
<p>Lee el <a href="/css/box-model">modelo de caja</a> para más.</p>
<!-- el enlace es inline, así que se mantiene dentro de la oración -->

Cada caja en flujo normal se distribuye como nivel de bloque o nivel inline, y los dos siguen reglas diferentes. Una caja de bloque comienza en una nueva línea, llena el ancho disponible por defecto y se apila verticalmente. <div>, <p>, <h1> y <section> son bloque por defecto. Una caja inline fluye dentro de una línea junto al texto, toma solo el ancho de su contenido y se sienta al lado de sus vecinos hasta que la línea se ajusta. <span>, <a> y <strong> son inline por defecto.

La diferencia que atrapa a las personas es lo que ignoran las cajas inline. Una caja inline ignora width, height y márgenes superior e inferior. Establece width: 200px en un <span> y nada sucede, porque una caja inline se dimensiona por su contenido, no por ti. El relleno y margen izquierdo y derecho se aplican, pero el espaciado vertical no separa las líneas circundantes de la forma que lo haría en un bloque.

css
.tag {
  width: 200px;        /* ignorado: un span es inline, dimensionado por contenido */
  padding: 0 8px;      /* el relleno horizontal funciona */
  margin-top: 40px;    /* ignorado: sin margen vertical en cajas inline */
}

En flujo normal una caja se distribuye según diseño de bloque o diseño inline dependiendo de su tipo de visualización, y los dos difieren en formas que van más allá de "se apila o se ajusta". Una caja de bloque genera una pausa antes y después de sí misma, consume el tamaño inline completo de su bloque contenedor a menos que se le dé un ancho, y respeta los cuatro márgenes y ambas dimensiones. Una caja inline participa en una caja de línea, se dimensiona por su contenido, y su diseño se rige por line-height y alineación de base en lugar de por width y height.

La parte precisa es qué propiedades deja una caja inline. width y height no se aplican a una caja inline no reemplazada como un <span> o <a>, porque su tamaño proviene de su contenido y la línea circundante. Los márgenes superior e inferior se calculan pero no tienen efecto en la altura de la línea, así que nunca separan líneas adyacentes, y el relleno superior e inferior se representa visualmente pero tampoco cambia la altura de la caja de línea, así que puede superponerse con líneas vecinas. El margen y relleno izquierdo y derecho se aplican y desplazan vecinos inline. Los elementos inline reemplazados como <img> son la excepción: tienen dimensiones intrínsecas, así que width y height se aplican a ellos aunque sean de nivel inline.

css
.badge {              /* .badge es un <span>, inline por defecto */
  width: 120px;       /* sin efecto: width no se aplica a cajas inline */
  height: 40px;       /* sin efecto por la misma razón */
  padding: 12px;      /* izquierda/derecha desplaza vecinos; superior/inferior puede superponer líneas */
  margin: 8px 0;      /* el vertical 8px se ignora, el horizontal 0 se aplicaría */
}
JunoCajas de bloque y cajas inline Las cajas de bloque como <p> y <div> toman el ancho completo y se apilan en sus propias líneas. Las cajas inline como <span> y <a> se sientan dentro de una línea y toman solo el espacio que necesitan. Por eso un enlace se mantiene dentro de tu oración en lugar de romper a su propia fila.
JunoCajas de bloque y cajas inline Las cajas de bloque llenan el ancho y se apilan; las cajas inline fluyen a lo largo de la línea y se dimensionan a su contenido. La trampa es que una caja inline ignora width, height y márgenes verticales, así que establecer width en un <span> no hace nada. El relleno y margen horizontal aún funcionan, que es por qué eso atrapa a las personas.
JunoCajas de bloque y cajas inline Una caja inline se dimensiona por su contenido y su caja de línea, así que width y height no se aplican, y el margen y relleno vertical no separan líneas adyacentes. El margen y relleno horizontal se aplican y desplazan vecinos. La excepción son elementos reemplazados como <img>, que llevan sus propias dimensiones y por lo tanto aceptan width y height incluso cuando son inline.

La propiedad display

Cada elemento tiene un tipo predeterminado, bloque o inline, pero no estás atrapado con eso. La propiedad display te permite cambiar cuál se comporta un elemento. Establece display: block en un enlace y ahora toma su propia línea; establece display: inline en un elemento de lista y se sienta en una fila.

Hay un tercer valor que resuelve un problema común: display: inline-block. Fluye en la línea como una caja inline, pero acepta un ancho, una altura y relleno vertical como un bloque. Eso es lo que quieres para algo como un botón o una pastilla de navegación que debe sentarse al lado de sus vecinos pero aún tomar un tamaño establecido.

css
.nav-link {
  display: inline-block;   /* fluye en la línea, pero acepta width y padding */
  padding: 8px 16px;       /* el relleno vertical ahora funciona, a diferencia del inline simple */
}

La propiedad display establece cómo una caja se distribuye, y los tres valores de flujo son block, inline e inline-block. display: block hace que una caja comience en su propia línea y llene el ancho, sin importar cuál sea el predeterminado del elemento. display: inline hace que fluya dentro de una línea y suelte width, height y márgenes verticales. Ninguno cambia el significado del elemento, solo su diseño.

inline-block es el híbrido útil: la caja fluye en la línea como una caja inline, así que varias se sientan lado a lado, pero acepta width, height y margen y relleno vertical como un bloque. Recurre a él cuando quieres cosas en una fila que aún necesitan dimensiones reales, un conjunto de botones o enlaces de navegación, sin pasar a flexbox. Cuando necesitas diseñar una fila o cuadrícula completa de elementos con alineación y espaciado, display: flex en flexbox es la herramienta mejor; inline-block es para el caso más pequeño de algunas cajas dimensionadas en una línea.

css
.stat {
  display: inline-block;   /* se sienta en una fila con sus hermanos */
  width: 120px;            /* pero toma un ancho fijo, que inline ignoraría */
  padding: 12px;           /* el padding completo se aplica, superior e inferior incluidos */
}

display selecciona el modo de diseño para una caja, y los tres valores que la mantienen en flujo normal son block, inline e inline-block. block da una caja que se rompe antes y después y llena el tamaño inline del bloque contenedor; inline da una caja que se une a una caja de línea y suelta width, height y márgenes verticales. Establecer display nunca toca la semántica, solo el diseño: un <div> establecido a display: inline sigue siendo un <div> para el DOM y la tecnología de asistencia, solo que se distribuye inline.

inline-block es el híbrido deliberado. La caja es de nivel inline, así que participa en una caja de línea y se sienta junto a vecinos inline, pero su interior se distribuye como un bloque, así que width, height y los cuatro márgenes y rellenos se aplican y toman espacio de diseño real. Eso la hace correcta para un pequeño número de cajas dimensionadas en una línea donde no quieres un contenedor flex, por ejemplo bloques de estadísticas de ancho fijo o pastillas de navegación. La advertencia es que como es de nivel inline, el espacio en blanco entre dos elementos inline-block en tu HTML se representa como un espacio real entre ellos, que la sección avanzada abajo cubre. Para cualquier cosa con alineación, distribución o ajuste en una fila completa, prefiere el diseño flex en flexbox; inline-block es la herramienta estrecha, no la general.

css
.pill {
  display: inline-block;   /* caja de nivel inline, interiores de nivel bloque */
  width: 96px;             /* se aplica, porque el interior se distribuye como un bloque */
  padding: 10px 14px;      /* los cuatro lados toman espacio de diseño */
  margin: 0 4px;           /* el margen vertical ahora se aplica también */
}
JunoLa propiedad display La propiedad display cambia si un elemento se comporta como un bloque o como una caja inline. block toma su propia línea, inline se sienta en la línea de texto. La opción intermedia útil es inline-block, que fluye en la línea pero aún acepta un ancho y relleno, así que es lo que quieres para botones y enlaces de navegación.
JunoLa propiedad displaydisplay establece el diseño, no el significado: block, inline o el híbrido inline-block. Usa inline-block cuando quieras algunas cajas dimensionadas sentadas en una fila, ya que fluye inline pero acepta width, height y padding completo. Para una fila completa que necesita alineación y espaciado, recurre a flexbox en su lugar.
JunoLa propiedad displaydisplay elige el modo de diseño y nunca la semántica, así que un <div> inline sigue siendo un <div> para el DOM. inline-block es una caja de nivel inline con interiores de nivel bloque, así que se sienta en una línea pero honra width, height y todos los cuatro márgenes. Mantenlo para un puñado de cajas dimensionadas y entrega una fila real a flexbox, y ten cuidado con la brecha de espacio en blanco que deja entre cajas adyacentes.

Ocultando cosas: display none versus visibility hidden

A veces necesitas que un elemento no se muestre. Hay dos formas, y se comportan diferente. display: none elimina el elemento por completo: desaparece y no deja brecha, como si no estuviera en la página en absoluto. visibility: hidden lo hace invisible pero mantiene su espacio, así que hay un agujero vacío donde solía estar.

Cuál quieres depende de si quieres el espacio de vuelta. Usa display: none para soltar algo por completo, como un menú que está cerrado. Usa visibility: hidden cuando quieras ocultar algo sin que el diseño se salte, porque su caja se mantiene reservada.

css
.closed-menu {
  display: none;          /* desaparecido, y sin brecha dejada */
}
.placeholder {
  visibility: hidden;     /* invisible, pero aún ocupa su espacio */
}

Las dos formas de ocultar un elemento no son intercambiables. display: none saca el elemento del flujo normal por completo: no genera caja, no ocupa espacio, y los elementos a su alrededor se cierran como si nunca hubiera estado allí. visibility: hidden mantiene la caja en flujo y reserva su espacio, así que el diseño no se desplaza; el elemento solo se pinta invisible.

Hay una diferencia de accesibilidad que importa tanto como la visual. Un elemento con display: none se elimina del árbol de accesibilidad también, así que los lectores de pantalla lo omiten, que es correcto para contenido que no está presente en absoluto, como un panel colapsado. visibility: hidden también oculta contenido de lectores de pantalla mientras mantiene el espacio. Si quieres algo visualmente desaparecido pero aún anunciado a la tecnología de asistencia, ninguno de estos es correcto; ese es el trabajo de una clase de utilidad visualmente oculta, que puedes leer sobre ello junto con la semántica en cómo funciona CSS.

css
.tab-panel[hidden] {
  display: none;          /* removido del flujo y del árbol de accesibilidad */
}
.spacer {
  visibility: hidden;     /* mantiene su espacio, aún oculto de lectores de pantalla */
}

display: none y visibility: hidden ambos ocultan, pero difieren en flujo, en el árbol de caja y en accesibilidad. display: none no genera caja en absoluto: el elemento está ausente del diseño, no toma espacio, y sus descendientes se van con él sin importar su propio display. visibility: hidden genera la caja normalmente, así que ocupa su espacio completo en flujo y solo suprime la pintura; un descendiente incluso puede establecer visibility: visible para reaparecer dentro de un ancestro de otro modo oculto, que display: none nunca permite.

Las consecuencias de accesibilidad y comportamiento son la razón para elegir deliberadamente. Tanto display: none como visibility: hidden eliminan el elemento del árbol de accesibilidad, así que un lector de pantalla no anunciará ninguno. Eso los hace incorrectos para contenido que quieres visualmente desaparecido pero aún leído en voz alta, el caso clásico siendo un enlace "saltar al contenido" o una etiqueta solo para lectores de pantalla; esos necesitan un patrón visualmente oculto que recorte la caja a un píxel mientras la deja en el árbol de accesibilidad, no ninguna propiedad aquí. Dos notas prácticas adicionales: display: none no puede ser transitado o animado entre estados de la forma que opacity y visibility pueden, y un elemento establecido a display: none no es enfocable y sus controles de formulario no se envían, mientras que un control visibility: hidden también se omite pero su espacio se mantiene. Elige display: none para eliminar completamente, visibility: hidden para ocultar mientras mantienes el diseño quieto, y una utilidad de recorte cuando la tecnología de asistencia aún debe alcanzarlo.

css
.dropdown[aria-expanded="false"] .menu {
  display: none;          /* completamente removido: sin caja, sin espacio, no enfocable */
}
.avatar-slot {
  visibility: hidden;     /* caja y espacio mantenidos, pintura suprimida */
}
JunoOcultando cosas: display none versus visibility hidden Dos formas de ocultar: display: none elimina el elemento y no deja brecha, visibility: hidden lo hace invisible pero mantiene su espacio. Elige display: none cuando quieras que el espacio desaparezca también, como un menú cerrado. Elige visibility: hidden cuando no quieras que el diseño se salte.
JunoOcultando cosas: display none versus visibility hiddendisplay: none saca el elemento del flujo así que nada reserva su espacio; visibility: hidden mantiene la caja y su espacio y solo oculta la pintura. Ambos también ocultan el elemento de lectores de pantalla, así que si quieres algo visualmente desaparecido pero aún anunciado, ninguno es correcto. Ese trabajo pertenece a una clase de utilidad visualmente oculta.
JunoOcultando cosas: display none versus visibility hiddendisplay: none no genera caja y no toma espacio; visibility: hidden mantiene la caja y el espacio y solo suprime la pintura, y un hijo puede establecer visibility: visible para reaparecer. Ambos salen del árbol de accesibilidad, así que un enlace de salto o etiqueta de lector de pantalla necesita una utilidad de recorte, no ninguno de los dos. Recuerda que display: none no es animable y sus controles no son enfocables o enviados.

Cómo display cambia el diseño interno

Has visto display cambiar un elemento entre bloque e inline. Hace más que eso en el extremo más profundo. La misma propiedad es lo que convierte un contenedor en un flexbox o una cuadrícula, que son las dos herramientas modernas para distribuir hijos en filas y columnas. Por ahora, lo que debes recordar es que display es el único dial que decide cómo una caja se distribuye y cómo sus hijos se distribuyen dentro de ella.

El diseño no es un gran interruptor que gires una sola vez. Cambias display en los contenedores específicos que necesitan una distribución diferente, y todo lo que dejas solo se mantiene en flujo normal. Los capítulos de flexbox y posicionamiento continúan desde aquí.

display realmente controla dos cosas a la vez: cómo la caja en sí se sienta entre sus hermanos, y cómo la caja distribuye sus propios hijos. display: block y display: inline hablan principalmente del primero. display: flex y display: grid cambian el segundo: el contenedor aún participa en flujo normal como un bloque, pero dentro de él, los hijos se distribuyen por reglas flex o grid en lugar de flujo de bloque e inline.

Esto es por qué pasar a flexbox no desecha todo lo que sabes sobre flujo. Un contenedor flex aún es una caja de bloque en el flujo normal del padre; solo sus hijos cambian el modo de diseño. El flujo normal sigue siendo el predeterminado alrededor de él, y optas por flex o grid en los contenedores específicos que lo necesitan. El capítulo de posicionamiento cubre la otra forma de dejar el flujo, sacando una caja completamente en lugar de cambiar cómo se distribuyen los hijos.

Un valor display es realmente dos tipos a la vez: un tipo externo que dice cómo la caja participa en el diseño de su padre, y un tipo interno que dice cómo la caja distribuye sus propios hijos. display: block es bloque externo, flujo interno; display: flex es bloque externo, flex interno; display: inline-flex es inline externo, flex interno. Ese modelo de dos partes es por qué un contenedor flex aún se sienta en flujo normal como un bloque mientras sus hijos siguen reglas flex: has cambiado el tipo interno, no el externo.

Un valor más se merece un lugar aquí: display: flow-root. Da a una caja un flujo interno normal pero la fuerza a establecer un nuevo contexto de formato de bloque (un BFC: una región de diseño autónoma cuyo interior no interactúa con el exterior, así que floats dentro se contienen y los márgenes dentro no colapsan a través de su borde). Antes de que flow-root existiera, las personas desencadenaban un BFC con overflow: hidden o un truco clearfix para contener hijos flotantes; flow-root es la forma explícita, sin efectos secundarios para decir "contén esto". También detiene el colapso de margen padre-e-hijo descrito en el modelo de caja. Cuando mueves un contenedor a display: flex o display: grid en flexbox, estás asimismo estableciendo un nuevo contexto de formato, que es parte de por qué los márgenes se comportan más predeciblemente dentro de diseños modernos que dentro de los de la era float.

css
.media {
  display: flow-root;     /* contiene cualquier hijo flotante, sin truco clearfix */
}
.gallery {
  display: flex;          /* bloque externo en flujo normal, flex interno para hijos */
}
JunoCómo display cambia el diseño interno La misma propiedad display que cambia bloque e inline es también lo que convierte un contenedor en un flexbox o una cuadrícula para distribuir hijos. El diseño no es un interruptor que giras una sola vez; cambias display en los contenedores que lo necesitan y dejas el resto en flujo normal. Los capítulos de flexbox y posicionamiento continúan desde aquí.
JunoCómo display cambia el diseño internodisplay rige tanto cómo una caja se sienta entre sus hermanos como cómo distribuye sus propios hijos. display: flex y display: grid cambian el segundo, así que un contenedor flex es aún un bloque en flujo normal mientras sus hijos cambian a reglas flex. Eso es por qué aprender flexbox se basa en flujo en lugar de reemplazarlo.
JunoCómo display cambia el diseño interno Un valor display lleva un tipo externo, cómo la caja se une a su padre, y un tipo interno, cómo distribuye hijos, que es por qué un contenedor flex sigue siendo un bloque en flujo mientras sus hijos van flex. display: flow-root mantiene flujo interno normal pero inicia un nuevo contexto de formato de bloque, así que contiene floats y detiene el colapso de margen sin los viejos trucos overflow o clearfix. Los contenedores flex y grid establecen su propio contexto también, que es por qué los márgenes se comportan más predeciblemente dentro de ellos.