CSS Grid solución a los problemas de float y flexbox

Compartir esta publicación

Antes de pasar a explicar qué es y para qué sirve CSS Grid explicaré cuál es el estado actual de las herramientas de las que disponemos al desarrollar un layout para nuestra web.

Supongamos que queremos maquetar el siguiente layout:

css grid layout

Deberíamos usar un html con cada sección necesaria, como el siguiente:


<body>
<nav>Navbar</nav>
<main class="container">
    <section class="left">Section</section>
    <section class="center">Section</section>
    <section class="right">Section</section>
</main>
<footer>Footer</footer>
</body>

Usando este html pasaremos a añadir los estilos usando float, flexbox y CSS Grid.

Float

Al usar float nos encontramos ante unos de los principales problemas de la maquetación de layouts, ya que la propiedad float no está diseñada para maquetar layouts, pese a utilizarse para eso. Como se menciona en la especificación de float, el uso de float se limita a especificar que un elemento flotará a la derecha o a la izquierda del contenedor y el resto del contenido de este flotará a su alrededor. Sin embargo, el uso de floats para posicionar elementos en nuestro layout puede dar lugar a una serie de extraños bugs que requiren de «hacks» para solucionarlos, como se menciona en este post sobre floats. Para lograr el siguiente layout, deberíamos usar un css como este (solamente he añadido el css necesario, en el enlace anterior aparece el código completo):


.container {
  text-align: center; /* necesario para la class .center */
}
.container:after {
  content: "";
  display: table;
  clear: both;
}
.left {
  float: left;
}
.center {
  margin: 0 auto;
  display: inline-block;
}
.right {
  float: right;
}

Solamente observando el css resultante, podemos ver cómo necesitamos aplicar «parches» para centrar la clase .center y usar clearfix hack para evitar que la clase .container pierda su tamaño al tener sus hijos como elementos flotantes.

Para hacer frente a todos estos hacks necesarios a la hora de maquetar, surgió flexbox, que aporta una significativa mejora respecto a float.

Flexbox

Flexbox permite maquetar layouts que se adaptan al tamaño de pantalla y que nos libran de las desventajas de usar float, como por ejemplo el ajuste de nuestros elementos en ciertas medidas de pantalla. A pesar de esto, una de las desventajas de flexbox es que solamente nos permite organizar nuestros elementos en horizontal o en vertical, pero no ambos a la vez, lo que limita enormemente nuestras posibilidades. Para lograr el siguiente layout deberíamos usar un css como este:


.container {
  display: flex;
  justify-content: space-between;
}
.left {
  background-color: #dc4d4d;
}
.center {
  background-color: yellow;
}
.right {
  background-color: #e8a2af;
}

En el código anterior vemos cómo ya no es necesario especificar nada en nuestras tres columnas, simplemente modificamos las propiedades de la clase .container y podemos colocar nuestros elementos cómodamente. A pesar de no apreciarse en este ejemplo, y como se ha mencionado anteriormente, flexbox funciona muy bien en una sola dirección ya sea vertical o horizontal, pero si queremos trabajar en un layout posicionando elemento en ambas direcciones nos enfrentamos a otro de los problemas comunes, no solamente en flexbox sino también usando floats.

Uso de tags innecesarios

Otro inconveniente a la hora de usar tanto flexbox como float es el hecho de tener que agrupar nuestros elementos en cajas, ya que necesitamos que un grupo concreto de elementos se posicione conjuntamente en una misma zona. En el caso de flexbox, suponiendo que estamos trabajando en un layout horizontal deberíamos agrupar todos los elementos que queramos posicionar verticalemente en un nuevo tag padre, que contendrá todos los elementos a posicionar verticalmente y especificar allí la direción vertical. Hacer esto nos obliga a añadir tags de html innecesarios y que no aportan ningún valor semántico.


<body>
<nav></nav>
<main class="container">
    <section class="left"></section>
    <section class="center"></section>
    <section class="right"></section>
    <div class="container container--vertical">
        <section class="first"></section>
        <section class="second"></section>
        ...
    </div>
</main>
<footer></footer>
</body>

En el ejemplo anterior podemos ver cómo necesitamos añadir un nuevo <div> para encapsular los elementos que queremos posicionar verticalmente y pese a ser un solo elemento extra, esto a gran escala nos puede llevar a tener cientos de tags sin ningún valor semántico, por lo que tendríamos un html complejo y sin semántica.

  Buenas Practicas con Vue

Solución: CSS Grid

Para solucionar los problemas al usar float o flexbox aparece  css grid, que no nos fuerza a usar «hacks» para lograr el comportamiento esperado de nuestro css y nos ofrece la posibilidad de maquetar un layout en ambas direcciones sin la necesidad de añadir elementos extras e innecesarios para lograrlo. Otra de las ventajas de usar grid, y quizás una de las más importantes, es el hecho de que consigue separar nuestro html del css, ya no necesitamos modificar o adaptar nuestro html para que se comporte bien con nuestro css, con grid conseguimos que html sea simplemente lo que debe ser, markup.

CSS Grid

Dado que la mayoría de navegadores dan soporte a CSS Grid, se ha convertido en una opción a tener cada vez más en cuenta y muy posiblemente reemplace a flexbox, quien es su más reciente competidor.

Los principales conceptos de CSS Grid son muy parecidos a flexbox: tenemos un container que engloba una serie de elementos sobre los que se aplican las propiedades de grid.

Empezaremos a aplicar la propiedad display: grid a nuestro .container, lo que indicará que nuestro contenedor es un grid, pero al no especificar nada más simplemente apilará los divs uno encima de otro.


.container {
  display: grid;
}

layout navbar

link a fiddle

grid-template-columns y grid-template-rows

Ahora pasaremos a especificar la forma de nuestro layout. Dado que queremos 3 columnas y una sola fila, usaremos las propiedades grid-template-columnsy grid-template-rows, a las que pasamos el valor que queremos para cada una de nuestras filas o columnas.


.container {
  display: grid;
  grid-template-columns: 33.33% 33.33% 33.33%;
  grid-template-rows: 100%;
}

navbar layout

link a fiddle

grid-column y grid-row

Seguiremos posicionando los elementos: para ello podemos usar las propiedades grid-column y grid-row. Asignando el inicio y final de esta, por ejemplo grid-column-start y grid-column-end podemos definir en qué línea empiezan y acaban nuestras columnas y rows. Esto nos otorga muchísima flexibilidad a la hora de maquetar layouts, y a su vez es una herramienta muy sencilla de usar. En la siguiente imagen veremos cómo se distribuyen las líneas, empezando por el 1 (la mayoría de navegadores muestran un grid si inspeccionamos un elemento con display grid, lo que ayuda a diferenciar estas líneas):

  El principio No te repitas ( DRY )

5

Image source


.container {
  ...
  grid-template-rows: 100px 100px; /* Usamos 100px como tamaño de las rows ya que es nuestro height fixo para secciones */
}
.left {
  grid-column-start: 1;
  grid-column-end: 3;
  /* también se puede resumir como grid-column: 1/3 */
}

css grid

link a fiddle

repeat(), fr y grid-gap

Ahora pasaremos a maquetar layouts más elaborados. Para empezar, usaremos la unidad fr abreviación de fraction que toma el valor asignado del total de espacio disponible del contenedor. Esta unidad es muy útil ya que nos ahorra cálculos innecesarios. También usaremos la función repeat() que acepta como primer parámetro el número de veces a repetir y como segundo parámetro un valor. Usar esta función nos ahorrará repetir las columnas o filas como por ejemplo grid-template-rows: 1fr 1fr 1fr …. Por último, usaremos la propiedad grid-gap, que es la abreviación de grid-row-gapy grid-column-gap, por este orden, podemos asignar un valor general para ambos o uno específico a cada uno.


.container {
  ...
  grid-template-column: repeat(3, 1fr);
  grid-template-row: repeat(3, auto);
  grid-gap: 8px;
}

css grid layout web

grid-template-areas

Añadido esto, pasaremos a usar una de las propiedas más útiles e innovadoras de css grid, la propiedad grid-template-areas. Esta, nos permite definir un «esquema» en el que poder definir qué elemento queremos en cada celda de nuestro grid. A cada uno de los elementos le asignaremos una propiedad grid-area, que será el nombre del área que queramos usar. Hemos definido que tenemos 3 columnas y 3 filas, por lo que nuestro template será así:


.container {
  ...
  grid-template-areas:
    "f f f"
    "s s s"
    "t t t";
}
.left {
  ...
  grid-area: f
}
.center {
  ...
  grid-area: s
}
.right {
  ...
  grid-area: t
}

navbar css grid

Poder maquetar nuestro layout, a parte de ser muy rápido e intuitivo, nos permite modificar completamente la estructura del html sin tener que tocar nada de este, lo que se conoce como source order independence. Imaginemos que queremos cambiar el layout para mobile:


@media screen and (max-width: 640px) {
  .container {
    ...
    grid-template-areas:
      "t t t"
      "s s s"
      "f f f";
  }
}

Simplemente con este cambio en nuestro css hemos modificado completamente todo nuestro layout, algo imposible de hacer sin CSS Grid.

Esta increible propiedad nos permite modificar nuestros layouts muy rápidamente, dando pie a que podamos elaborar simples mockups muy rápido y podamos ir moviendo los diferentes elementos de nuestro layout para ver cómo nos gusta más.


.container {
  ...
  grid-template-areas:
    "t . f"
    "t s s"
    "t s s";
}
.section {
  // height: 100px;
}

navbar layout web css grid

Añado un enlace a codepen en el que poder modificar la propiedad grid-template-areas y así poder ver cómo cambia el layout.

  Filtrando datos con react-query

Cuándo usar CSS Grid

Como ya hemos dicho, flexbox opta por un approach basado en contenedores de una sola dirección mientras que CSS Grid opta por un layout bidireccional. A raíz de esto, flexbox se adapta mejor para el uso de componentes, ya que la mayoría de contenido de un componente suele ser en una sola dirección ya que suele ser contenido a pequeña escala, mientras que si requerimos un layout más complejo, con varías direcciones, si que usaríamos CSS Grid.

También es necesario tener en cuenta el soporte a navegadores de ambos, ya que si queremos dar soporte a navegadores de IE deberíamos optar por flexbox, ya que al tener mayor uso tiene polyfills adaptados para IE.

Suscríbete a nuestro newsletter para estar al día de CSS Grid!

Si este artículo sobre CSS Grid te gustó, te puede interesar:

Simular respuestas del servidor con Nodejs

Modulos Webpack

Principio de responsabilidad única

Por qué Kotlin ?

Patrón MVP en iOS

Arquitectura de microservicios 

F-bound en Scala: traits genéricos con higher-kinded types

Scala Generics I : Clases genéricas y Type bounds

Scala Generics II: covarianza y contravarianza 

Scala Generics III: generalized type constraints

Author

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Suscríbete a nuestro boletín de noticias

Recibe actualizaciones de los últimos descubrimientos tecnológicos

¿Tienes un proyecto desafiante?

Podemos trabajar juntos

apiumhub software development projects barcelona
Secured By miniOrange