Exemplos práticos de layouts com CSS Grid

Construa layouts de página inteira, dashboards e galerias de imagens usando CSS Grid.

Até agora, você explorou as propriedades individuais do CSS Grid. Agora é a hora de combinar todo esse conhecimento para construir layouts completos e responsivos, que são a razão de ser do Grid.

Vamos criar alguns layouts comuns que você encontrará em quase todo site, usando o CSS Grid de forma eficiente.

Exemplo 1: Layout de Página Clássico (Cabeçalho, Sidebar, Conteúdo, Rodapé)

Este é um dos layouts mais fundamentais na web. Com CSS Grid e grid-template-areas, ele se torna incrivelmente fácil de criar e manter.

<!DOCTYPE html>
<html lang="pt-BR">
<head>
  <meta charset="UTF-8">
  <title>Layout de Página Clássico com Grid</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      margin: 0;
      min-height: 100vh; /* Garante que o body ocupe a altura total da viewport */
      display: grid; /* Transforma o body em um contêiner grid */
      grid-template-columns: 1fr; /* Por padrão, uma única coluna */
      grid-template-rows: auto 1fr auto; /* Cabeçalho auto, conteúdo flexível, rodapé auto */
      grid-template-areas:
        "header"
        "main"
        "footer";
    }

    .header, .sidebar, .main-content, .footer {
      padding: 20px;
      border: 1px solid #ccc;
      display: flex;
      justify-content: center;
      align-items: center;
      font-weight: bold;
      color: white;
    }

    .header {
      background-color: #333;
      grid-area: header;
    }

    .sidebar {
      background-color: #555;
      grid-area: sidebar; /* Nomeamos, mas ainda não usamos no layout padrão */
    }

    .main-content {
      background-color: #777;
      grid-area: main;
    }

    .footer {
      background-color: #333;
      grid-area: footer;
    }

    /* Layout para telas maiores (desktop) */
    @media (min-width: 768px) {
      body {
        grid-template-columns: 200px 1fr; /* Sidebar de 200px, conteúdo flexível */
        grid-template-rows: auto 1fr auto;
        grid-template-areas:
          "header header"
          "sidebar main"
          "footer footer";
      }
    }
  </style>
</head>
<body>
  <header class="header">Cabeçalho</header>
  <aside class="sidebar">Barra Lateral</aside>
  <main class="main-content">Conteúdo Principal</main>
  <footer class="footer">Rodapé</footer>
</body>
</html>

Análise:

  • O body é o Contêiner Grid, ocupando 100% da altura da viewport (min-height: 100vh;).
  • Mobile-first: Por padrão (telas pequenas), o layout é de uma única coluna, com os elementos empilhados.
  • @media (min-width: 768px): Para telas maiores, redefinimos grid-template-columns para ter uma barra lateral e o conteúdo, e grid-template-areas para posicionar os elementos de forma diferente.
  • grid-template-rows: auto 1fr auto; garante que o cabeçalho e rodapé tenham altura automática e o conteúdo principal ocupe todo o espaço vertical restante.

Exemplo 2: Galeria de Imagens Responsiva

Uma galeria de imagens que se adapta ao número de colunas conforme o tamanho da tela, usando repeat() com auto-fit e minmax().

<!DOCTYPE html>
<html lang="pt-BR">
<head>
  <meta charset="UTF-8">
  <title>Galeria de Imagens com Grid</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      margin: 20px;
      background-color: #f4f4f4;
    }

    .gallery-container {
      display: grid;
      /* Colunas que se ajustam: mínimo de 250px, máximo de 1fr */
      grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
      gap: 15px;
      padding: 15px;
      background-color: white;
      border-radius: 8px;
      box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    }

    .gallery-item {
      background-color: #e0e0e0;
      border: 1px solid #ccc;
      border-radius: 4px;
      overflow: hidden; /* Garante que a imagem não transborde */
      text-align: center;
    }

    .gallery-item img {
      width: 100%;
      height: 200px; /* Altura fixa para as imagens */
      object-fit: cover; /* Garante que a imagem cubra a área sem distorcer */
      display: block; /* Remove espaço extra abaixo da imagem */
    }

    .gallery-item p {
      padding: 10px;
      margin: 0;
      color: #333;
      font-size: 0.9em;
    }
  </style>
</head>
<body>
  <h1>Minha Galeria de Fotos</h1>
  <div class="gallery-container">
    <div class="gallery-item">
      <img src="https://via.placeholder.com/400x200/FF5733/FFFFFF?text=Foto+1" alt="Foto 1">
      <p>Descrição da Foto 1</p>
    </div>
    <div class="gallery-item">
      <img src="https://via.placeholder.com/400x200/33FF57/FFFFFF?text=Foto+2" alt="Foto 2">
      <p>Descrição da Foto 2</p>
    </div>
    <div class="gallery-item">
      <img src="https://via.placeholder.com/400x200/3357FF/FFFFFF?text=Foto+3" alt="Foto 3">
      <p>Descrição da Foto 3</p>
    </div>
    <div class="gallery-item">
      <img src="https://via.placeholder.com/400x200/FF33FF/FFFFFF?text=Foto+4" alt="Foto 4">
      <p>Descrição da Foto 4</p>
    </div>
    <div class="gallery-item">
      <img src="https://via.placeholder.com/400x200/FFFF33/000000?text=Foto+5" alt="Foto 5">
      <p>Descrição da Foto 5</p>
    </div>
    <div class="gallery-item">
      <img src="https://via.placeholder.com/400x200/33FFFF/FFFFFF?text=Foto+6" alt="Foto 6">
      <p>Descrição da Foto 6</p>
    </div>
    <div class="gallery-item">
      <img src="https://via.placeholder.com/400x200/FF3333/FFFFFF?text=Foto+7" alt="Foto 7">
      <p>Descrição da Foto 7</p>
    </div>
    <div class="gallery-item">
      <img src="https://via.placeholder.com/400x200/33FF33/FFFFFF?text=Foto+8" alt="Foto 8">
      <p>Descrição da Foto 8</p>
    </div>
  </div>
</body>
</html>

Análise:

  • grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); é a chave aqui. Ele diz: "Crie o máximo de colunas que couberem, onde cada coluna tem no mínimo 250px e no máximo 1 fração do espaço disponível."
  • gap: 15px; mantém um espaçamento consistente entre as imagens.
  • Redimensione a janela do navegador para ver como o número de colunas se ajusta automaticamente.

Exemplo 3: Dashboard com Widgets de Tamanhos Variados

Um layout de dashboard onde alguns widgets ocupam mais espaço que outros, usando grid-column e grid-row para posicionamento explícito.

<!DOCTYPE html>
<html lang="pt-BR">
<head>
  <meta charset="UTF-8">
  <title>Dashboard com Grid</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      margin: 20px;
      background-color: #f4f4f4;
    }

    .dashboard-container {
      display: grid;
      grid-template-columns: repeat(4, 1fr); /* 4 colunas de largura igual */
      grid-template-rows: repeat(3, 150px); /* 3 linhas de 150px de altura */
      gap: 20px;
      padding: 20px;
      background-color: white;
      border-radius: 8px;
      box-shadow: 0 2px 4px rgba(0,0,0,0.1);
      max-width: 1200px;
      margin: 0 auto;
    }

    .widget {
      background-color: #add8e6; /* Light Blue */
      border: 1px solid #87ceeb; /* Sky Blue */
      border-radius: 8px;
      padding: 15px;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      font-weight: bold;
      color: #333;
      box-shadow: 0 1px 2px rgba(0,0,0,0.05);
    }

    /* Widgets de tamanhos variados */
    .widget-large {
      grid-column: span 2; /* Ocupa 2 colunas */
      grid-row: span 2;    /* Ocupa 2 linhas */
      background-color: #90ee90; /* Light Green */
      border-color: #32cd32; /* Lime Green */
    }

    .widget-wide {
      grid-column: span 3; /* Ocupa 3 colunas */
      background-color: #ffb6c1; /* Light Pink */
      border-color: #ff69b4; /* Hot Pink */
    }

    .widget-tall {
      grid-row: span 2;    /* Ocupa 2 linhas */
      background-color: #ffd700; /* Gold */
      border-color: #daa520; /* Goldenrod */
    }
  </style>
</head>
<body>
  <h1>Meu Dashboard</h1>
  <div class="dashboard-container">
    <div class="widget widget-large">Widget Grande (2x2)</div>
    <div class="widget">Widget Pequeno</div>
    <div class="widget">Widget Pequeno</div>
    <div class="widget-wide">Widget Largo (1x3)</div>
    <div class="widget">Widget Pequeno</div>
    <div class="widget-tall">Widget Alto (2x1)</div>
    <div class="widget">Widget Pequeno</div>
    <div class="widget">Widget Pequeno</div>
  </div>
</body>
</html>

Análise:

  • Definimos um grid base de 4 colunas e 3 linhas.
  • Usamos grid-column: span X; e grid-row: span Y; nos widgets para fazê-los ocupar múltiplas células.
  • O Grid se encarrega de organizar os widgets restantes nos espaços vazios.

Exemplo 4: Layout de Blog com Destaque

Um layout de blog onde o primeiro post é um destaque que ocupa mais espaço, e os outros posts se organizam em um grid.

<!DOCTYPE html>
<html lang="pt-BR">
<head>
  <meta charset="UTF-8">
  <title>Layout de Blog com Grid</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      margin: 20px;
      background-color: #f4f4f4;
    }

    .blog-container {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); /* Colunas flexíveis */
      grid-auto-rows: minmax(250px, auto); /* Altura mínima para as linhas */
      gap: 20px;
      padding: 20px;
      background-color: white;
      border-radius: 8px;
      box-shadow: 0 2px 4px rgba(0,0,0,0.1);
      max-width: 1200px;
      margin: 0 auto;
    }

    .blog-post {
      background-color: #f0f8ff; /* Alice Blue */
      border: 1px solid #b0e0e6; /* Powder Blue */
      border-radius: 8px;
      padding: 20px;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      box-shadow: 0 1px 2px rgba(0,0,0,0.05);
    }

    .blog-post h3 {
      margin-top: 0;
      color: #333;
    }

    .blog-post p {
      color: #666;
      flex-grow: 1; /* Faz o parágrafo ocupar o espaço restante */
    }

    .blog-post a {
      display: inline-block;
      background-color: #007bff;
      color: white;
      padding: 8px 15px;
      border-radius: 5px;
      text-decoration: none;
      align-self: flex-start; /* Alinha o botão à esquerda */
    }

    /* Post de destaque */
    .featured-post {
      grid-column: 1 / -1; /* Ocupa todas as colunas */
      grid-row: span 2;    /* Ocupa 2 linhas */
      background-color: #ffe4e1; /* Misty Rose */
      border-color: #ff6347; /* Tomato */
      display: grid; /* Transforma o post de destaque em um grid interno */
      grid-template-columns: 1fr 2fr; /* Imagem e conteúdo */
      gap: 20px;
      align-items: center;
    }

    .featured-post img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      border-radius: 5px;
    }

    .featured-post .content {
      display: flex;
      flex-direction: column;
      justify-content: center;
    }

    /* Responsividade para o post de destaque */
    @media (max-width: 768px) {
      .featured-post {
        grid-template-columns: 1fr; /* Em telas menores, imagem e texto empilham */
        grid-row: auto; /* Não ocupa 2 linhas, apenas o necessário */
      }
      .featured-post img {
        height: 200px; /* Altura fixa para a imagem em mobile */
      }
    }
  </style>
</head>
<body>
  <h1>Últimas do Blog</h1>
  <div class="blog-container">
    <div class="blog-post featured-post">
      <img src="https://via.placeholder.com/600x400/8A2BE2/FFFFFF?text=Post+Destaque" alt="Post Destaque">
      <div class="content">
        <h3>Título do Post de Destaque</h3>
        <p>Este é o nosso post mais importante, ocupando um espaço privilegiado no layout. Ele é responsivo e se adapta a diferentes tamanhos de tela.</p>
        <a href="#">Leia Mais</a>
      </div>
    </div>
    <div class="blog-post">
      <h3>Post Comum 1</h3>
      <p>Um artigo interessante sobre as novidades do desenvolvimento web.</p>
      <a href="#">Leia Mais</a>
    </div>
    <div class="blog-post">
      <h3>Post Comum 2</h3>
      <p>Dicas e truques para otimizar seu código CSS.</p>
      <a href="#">Leia Mais</a>
    </div>
    <div class="blog-post">
      <h3>Post Comum 3</h3>
      <p>Entrevista com um desenvolvedor front-end experiente.</p>
      <a href="#">Leia Mais</a>
    </div>
    <div class="blog-post">
      <h3>Post Comum 4</h3>
      <p>Como criar componentes reutilizáveis com JavaScript.</p>
      <a href="#">Leia Mais</a>
    </div>
  </div>
</body>
</html>

Análise:

  • grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); cria um grid de posts flexível.
  • grid-auto-rows: minmax(250px, auto); garante que as linhas tenham uma altura mínima, mas se ajustem ao conteúdo.
  • .featured-post usa grid-column: 1 / -1; para ocupar todas as colunas e grid-row: span 2; para ocupar duas linhas.
  • O post de destaque é, por si só, um Contêiner Grid (display: grid;) com duas colunas (1fr 2fr), demonstrando como você pode aninhar grids.
  • Media query para o post de destaque: em telas menores, ele volta a ser uma única coluna, com a imagem e o texto empilhados.

Conclusão

Estes exemplos demonstram a versatilidade e o poder do CSS Grid. Com ele, você pode criar desde layouts de página inteira complexos até componentes responsivos, com um código muito mais limpo e fácil de manter do que com métodos antigos. A chave é entender as propriedades do Contêiner Grid e dos Itens Grid, e como elas interagem para construir a estrutura desejada.