Galeria CSS Grid totalmente responsive al estilo Pinterest o Masonry

Podría enumerar un sin fin de posibilidades para ordenar y navegar entre varias imágenes, pero nos vamos a centrar en una de las más bonitas y complejas de lograr: Una galería CSS buscando un aspecto de Pinterest, o también llamado, Masonry. Un diseño donde se entremezcla las columnas y filas con diferentes tamaños. Pero… ¿es posible montarla sin usar Javascript o JQuery?

Gracias a Grid CSS es posible y casi automático. De una manera sencilla, nuestra galería usará las herramientas nativas del navegador con un aspecto responsive design. Nuestras fotos se entrelazarán respetando la anchura disponible adaptando el número de columnas a la anchura disponible.

¿Quieres tocarlo? Inténtalo por ti mismo

A continuación dejo un sencillo ejemplo para aplicarlo en tu próxima página web.

HTML

Esta parte es bastante fácil de montar. Solo necesitaremos un div que englobe nuestras imágenes, y cada imagen un enlace. De este modo podremos jugar para que cada imagen sea pulsable y nos lleve a otro lugar o accione algún código.

<div class="grid-gallery">
    <a class="grid-gallery__item" href="#">
        <img class="grid-gallery__image" src="mifoto.jpg">
    </a>
    <a class="grid-gallery__item" href="#">
        <img class="grid-gallery__image" src="mifoto2.jpg">
    </a>
    ...
</div>

CSS

Con un poco de Grid CSS le indicamos que cambie el número de columnas dependiendo de la resolución. A continuación, cada ciertos número de elementos usando :nth-child, que varíe la cantidad de filas y columnas que ocupará el elemento. Por supuesto cuantos más posibilidades planteemos en el CSS más aleatorio será.

.grid-gallery {
  display: grid;
  grid-auto-rows: 200px;
  grid-gap: 1rem;
  grid-auto-flow: row dense;
}

@media all and (min-width: 320px) {
  .grid-gallery {
    grid-template-columns: repeat(1, 1fr);
  }
}

@media all and (min-width: 768px) {
  .grid-gallery {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media all and (min-width: 1024px) {
  .grid-gallery {
    grid-template-columns: repeat(6, 1fr);
  }
}

.grid-gallery__item:nth-child(11n+1) {
  grid-column: span 1;
}

.grid-gallery__item:nth-child(11n+4) {
  grid-column: span 2;
  grid-row: span 1;
}

.grid-gallery__item:nth-child(11n+6) {
  grid-column: span 3;
  grid-row: span 1;
}

.grid-gallery__item:nth-child(11n+7) {
  grid-column: span 1;
  grid-row: span 2;
}

.grid-gallery__item:nth-child(11n+8) {
  grid-column: span 2;
  grid-row: span 2;
}

.grid-gallery__item:nth-child(11n+9) {
  grid-row: span 3;
}

.grid-gallery__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

¡¡ Alternativa !!, si trabajas con SASS te resultará más cómodo el siguiente fragmento.

// Variables
$image-size: 200px
$gap-size: 1rem
$breakpoints: ("small": 320px, "medium": 768px, "large": 1024px) !default

.grid-gallery
    display: grid
    grid-auto-rows: $image-size
    grid-gap: $gap-size 
    grid-auto-flow: row dense
    @media all and (min-width: map-get($breakpoints, 'small'))
        $num-columns: 1
        grid-template-columns: repeat($num-columns, 1fr)
    @media all and (min-width: map-get($breakpoints, 'medium'))
        $num-columns: 3
        grid-template-columns: repeat($num-columns, 1fr)
    @media all and (min-width: map-get($breakpoints, 'large'))
        $num-columns: 6
        grid-template-columns: repeat($num-columns, 1fr)
    &__item
        &:nth-child(11n+1)
            grid-column: span 1
        &:nth-child(11n+4)
            grid-column: span 2
            grid-row: span 1
        &:nth-child(11n+6)
            grid-column: span 3
            grid-row: span 1
        &:nth-child(11n+7)
            grid-column: span 1
            grid-row: span 2
        &:nth-child(11n+8)
            grid-column: span 2
            grid-row: span 2
        &:nth-child(11n+9)
            grid-row: span 3
    &__image
        width: 100%
        height: 100%
        object-fit: cover

Completo

Todo unido quedaría de la siguiente forma. Nota: tendrás que ir clonando los enlaces para ver el efecto con un mayor número de imágenes.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <style>
        .grid-gallery {
          display: grid;
          grid-auto-rows: 200px;
          grid-gap: 1rem;
          grid-auto-flow: row dense;
        }

        @media all and (min-width: 320px) {
          .grid-gallery {
            grid-template-columns: repeat(1, 1fr);
          }
        }

        @media all and (min-width: 768px) {
          .grid-gallery {
            grid-template-columns: repeat(3, 1fr);
          }
        }

        @media all and (min-width: 1024px) {
          .grid-gallery {
            grid-template-columns: repeat(6, 1fr);
          }
        }

        .grid-gallery__item:nth-child(11n+1) {
          grid-column: span 1;
        }

        .grid-gallery__item:nth-child(11n+4) {
          grid-column: span 2;
          grid-row: span 1;
        }

        .grid-gallery__item:nth-child(11n+6) {
          grid-column: span 3;
          grid-row: span 1;
        }

        .grid-gallery__item:nth-child(11n+7) {
          grid-column: span 1;
          grid-row: span 2;
        }

        .grid-gallery__item:nth-child(11n+8) {
          grid-column: span 2;
          grid-row: span 2;
        }

        .grid-gallery__item:nth-child(11n+9) {
          grid-row: span 3;
        }

        .grid-gallery__image {
          width: 100%;
          height: 100%;
          object-fit: cover;
        }
    </style>
</head>
<body>
    <div class="grid-gallery">
        <a class="grid-gallery__item" href="#">
            <img class="grid-gallery__image" src="https://source.unsplash.com/featured/500x400/?dog">
        </a>
        <a class="grid-gallery__item" href="#">
            <img class="grid-gallery__image" src="https://source.unsplash.com/featured/500x400/?woman">
        </a>
    </div>
</body>
</html>
Versión escritorio