wandres.dev
GRID O FLEX · El árbol de decisión

El árbol de decisión Grid o Flex

Cinco preguntas en orden que resuelven la elección en menos de un minuto, con el porqué de cada bifurcación y los casos en los que las dos respuestas son válidas.

⏱ 16 min

Con los dos criterios anteriores —coordenadas compartidas y dirección del dimensionado— ya tienes todo lo necesario para decidir sin discutir. Lo que falta es un orden: las preguntas no valen lo mismo, y hacerlas en la secuencia correcta resuelve la mayoría de los casos en la primera o la segunda. Este árbol no es una regla de estilo, es una destilación de qué restricciones puede expresar cada módulo.

🎯 Al terminar esta lección sabrás
  • Aplicar en orden las cinco preguntas que determinan el módulo correcto.
  • Justificar cada bifurcación con la capacidad del algoritmo, no con una preferencia.
  • Reconocer los tres casos en los que las dos respuestas son igual de válidas.
  • Detectar cuándo la pregunta correcta no era Grid o Flex sino “esto no es un layout”.

El árbol

flowchart TB
A[Tengo que colocar un conjunto de elementos] --> B{Hay una estructura de pistas compartida entre filas}
B -->|Si| G[Grid]
B -->|No| C{Necesito solapar elementos en la misma celda}
C -->|Si| G
C -->|No| D{El tamano de cada pieza lo decide su contenido}
D -->|Si| F[Flex]
D -->|No| E{Es una sola fila o una sola columna}
E -->|Si| F
E -->|No| G
style G fill:#89b4fa,color:#11111b
style F fill:#a6e3a1,color:#11111b
style A fill:#cba6f7,color:#11111b

Las preguntas están ordenadas por poder discriminante. La primera resuelve galerías, tablas de precios, calendarios y plantillas de página. La segunda captura un caso que Flexbox sencillamente no sabe hacer. La tercera y la cuarta reparten el resto.

Por qué cada bifurcación está donde está

Pistas compartidas. Es la primera porque es la única restricción que Flexbox no puede expresar de ninguna manera. Si el borde derecho de la tercera tarjeta de la primera fila tiene que coincidir con el de la tercera de la segunda fila, no hay valor de flex-basis que lo garantice cuando el contenido cambie. Con Grid es la definición misma de columna.

Solapamiento. En Grid, dos elementos pueden ocupar la misma celda:

.heroe {
  display: grid;
  grid-template-areas: "capa";
  place-items: center;
}
.heroe > * {
  grid-area: capa;   /* todos en la misma celda, se apilan */
}

Ese patrón —imagen de fondo, degradado y texto en la misma celda, alineados sin position: absolute— es exclusivo de Grid, y es la razón por la que Grid aparece en componentes minúsculos que no tienen nada de rejilla. Un elemento absolutamente posicionado no participa en el layout de sus hermanos; un elemento en la misma celda de grid sí, y por eso la celda crece hasta contener al mayor de los dos, cosa que con position: absolute no ocurre.

Tamaño decidido por el contenido. Aquí entra todo lo que es una lista de longitud variable: etiquetas, migas de pan, botones de una barra, iconos con texto. flex: 0 0 auto describe exactamente “mide lo que midas” y flex-wrap se encarga del resto.

Fila o columna suelta. El desempate final. Si has llegado hasta aquí es que no hay pistas ni solapamiento y los tamaños son fijos; una fila con display: flex es más corta de escribir y más fácil de leer que una rejilla de una sola fila. Si en cambio hay filas y columnas, aunque sean fijas, Grid las nombra mejor.

⚠️
La pregunta cero que casi nadie hace

Antes de entrar en el árbol comprueba que hay un layout. Un párrafo con una imagen flotante, un texto largo, una lista de definiciones o un formulario apilado no necesitan ningún contenedor de layout: el flujo normal ya los coloca, y añadir display: flex los saca del flujo de bloque, mata el colapso de márgenes y convierte a los hijos en ítems flex con reglas de dimensionado distintas. La respuesta correcta a “¿Grid o Flex?” a veces es “ninguno”.

Los tres empates legítimos

Hay tres situaciones en las que las dos respuestas funcionan igual de bien y elegir es cuestión de coherencia con el resto del proyecto, no de corrección.

La barra de navegación con logo a la izquierda y acciones a la derecha se escribe igual de bien con display: flex; justify-content: space-between que con grid-template-columns: auto 1fr auto. La versión de grid gana en cuanto aparece un tercer bloque centrado que debe estar centrado respecto al contenedor y no respecto al hueco. La de flex gana si el número de bloques es variable.

El centrado de una sola cosa funciona con los dos: display: grid; place-items: center y display: flex; align-items: center; justify-content: center producen el mismo resultado. La versión de grid es más corta y no tiene sorpresas cuando el hijo es más grande que el contenedor.

El apilado con separación uniforme —el clásico stack vertical— se puede hacer con display: flex; flex-direction: column; gap: 1rem o con display: grid; gap: 1rem. Grid tiene una ventaja sutil: sus hijos no reciben flex-shrink, así que un elemento con altura intrínseca no se comprime inesperadamente cuando el contenedor tiene altura limitada.

Cuándo el árbol falla

El árbol asume que el contenedor es de tamaño conocido para el motor, y eso es cierto casi siempre. Falla en un caso concreto: cuando el mismo componente tiene que comportarse de forma distinta según el espacio que le toque, y ese espacio no lo sabes al escribirlo. Ahí la respuesta no está en el árbol sino en un nivel superior de la decisión: dejar que el layout reaccione al contenedor, que es lo que hacen los layouts intrínsecos y las container queries.

Dicho de otro modo: el árbol elige el módulo, no la estrategia de adaptación. Son dos decisiones independientes y se toman por separado.

Los módulos de layout son lenguajes de restricciones, no de resultados

La razón de que este árbol funcione es que Grid y Flexbox no son dos formas de dibujar cajas: son dos lenguajes con expresividad distinta, y elegir es elegir en cuál de los dos se puede escribir la restricción que el diseño impone. Cuando una restricción es expresable, el motor la mantiene por ti para siempre: la mantiene cuando el usuario aumenta el tamaño de letra, cuando llega una traducción larga, cuando el contenedor cambia de ancho, cuando alguien inserta un elemento más. Cuando no es expresable, la mantienes tú, a mano, en cada revisión, y la única forma de saber que se ha roto es que alguien la mire. Por eso la pregunta útil nunca es “¿cuál queda mejor?” sino “¿cuál de los dos sabe decir lo que el diseño exige?”. Es exactamente el mismo criterio que aplicas al elegir un tipo en un lenguaje de programación: prefieres el que hace imposible el estado inválido, no el que te deja llegar al estado válido con más comodidad.

⚔️ Somete diez componentes al árbol
  1. Toma diez componentes de un proyecto real y pásalos por el árbol sin mirar su implementación actual.
  2. Anota los que el árbol resuelve en la primera pregunta: deberían ser la mitad largos.
  3. Busca al menos un caso donde la respuesta sea “no es un layout” y elimina el contenedor sobrante.
  4. Implementa el patrón de solapamiento en la misma celda y compáralo con la versión de position: absolute: fíjate en qué pasa con la altura del contenedor.
  5. Para cada empate que encuentres, escribe una frase que justifique tu elección; si no puedes escribirla, es que el empate era real y da igual.