# CSS Gap Decorations

> Com suporte total no Chrome e no Edge, as gap decorations do CSS já permitem estilizar os espaços de grid e flexbox com bastante controle.

URL: https://dpw.dev/css/css-gap-decorations/  
Publicado em: 2026-08-03  
Categoria: css  
Tags: layout, flexbox  
Autor: Tárcio Zemel

Por muito tempo, quem trabalha com desenvolvimento web teve que recorrer a hacks com bordas e pseudo-elementos para estilizar os espaços (gaps) entre os itens de layouts como grid e flexbox. Hoje, com as **CSS Gap Decorations** totalmente suportadas no Chrome e no Edge a partir da versão 149, é possível estilizar esses espaços de forma muito mais simples e com bastante controle.

> Artigo baseado em [Gap Decorations Are Now Available, Here's What's New](https://css-tricks.com/css-gap-decorations-now-available/).

A equipe da plataforma web do Edge, na Microsoft, liderou o design e a padronização do recurso, e a implementação já está sendo lançada em todos os navegadores baseados em Chromium.

Para mais contexto, vale conferir uma <a href="https://css-tricks.com/the-gap-strikes-back-now-stylable/" target="_blank" rel="noopener noreferrer">prévia inicial das gap decorations</a>, escrita por <a href="https://patrickbrosset.com/" target="_blank" rel="noopener noreferrer">Patrick Brosset</a>, e um <a href="https://developer.chrome.com/blog/gap-decorations-stable" target="_blank" rel="noopener noreferrer">mergulho completo</a> sobre o lançamento estável, escrito por <a href="https://www.linkedin.com/in/javier-contreras-t" target="_blank" rel="noopener noreferrer">Javier Contreras Tenorio</a>.

Este artigo apresenta o que mudou no recurso desde então.

## Recapitulando as gap decorations

As **gap decorations** estendem a já conhecida propriedade CSS <code>column-rule</code>, que já funcionava em <a href="https://developer.mozilla.org/docs/Web/CSS/Guides/Multicol_layout" target="_blank" rel="noopener noreferrer">layout multi-coluna</a>, e passam a funcionar também em layouts de grid e flexbox.

Além disso, agora também há suporte à propriedade <code>row-rule</code>, permitindo que as decorações apareçam nos dois eixos. E a sintaxe também foi estendida para oferecer muito mais controle sobre as decorações.

Patrick já fez um bom <a href="https://css-tricks.com/the-gap-strikes-back-now-stylable/" target="_blank" rel="noopener noreferrer">passo a passo</a> do recurso, mas, desde então, algumas coisas mudaram, como renomeações de propriedades para deixar tudo mais claro, além de novas propriedades, definidas a partir do feedback recebido de desenvolvedores web durante os testes iniciais.

Aqui está um resumo das mudanças:

| Antiga | Nova | O que essa mudança significa |
| --- | --- | --- |
| `row-rule-outset` / `column-rule-outset` | `row-rule-inset` / `column-rule-inset` | "Outset" virou "inset", e agora essas propriedades recolhem as linhas para dentro a partir das bordas da decoração. |
| Sem controle fino de onde `row-rule-inset` e `column-rule-inset` se aplicam | Novas propriedades longhand: `row-rule-inset-cap`, `row-rule-inset-junction`, `row-rule-inset-start`, `row-rule-inset-end`, e as equivalentes `column-rule-inset-cap`, `column-rule-inset-junction`, `column-rule-inset-start`, `column-rule-inset-end` | Agora é possível controlar as pontas externas (caps) e as interseções (junctions) de forma independente. Também dá para recolher o início e o fim das decorações de forma independente. |
| `gap-rule-paint-order` | `rule-overlap` | Essa propriedade foi renomeada para maior clareza. Ela controla como as decorações se sobrepõem onde as linhas de linha e coluna se cruzam. |
| N/A | `rule-visibility-items` | Essa nova propriedade controla se as linhas aparecem ao lado de áreas vazias dentro de um container. |

## Suporte dos navegadores

As gap decorations estão disponíveis no Chrome e no Edge a partir da versão 149, além de outros navegadores baseados em Chromium que correspondam a essas versões.

Outros motores de navegador têm se mostrado receptivos e engajados nos fóruns de padronização, então, com o tempo, esse recurso deve se tornar interoperável.

Para quem quiser usar o recurso agora, vale considerar:

- Se essas decorações forem tratadas como um progressive enhancement, ótimo! Basta começar a usar o recurso hoje mesmo, já que nada quebra em navegadores sem suporte.
- Se as gap decorations forem indispensáveis, há um <a href="https://github.com/microsoft/polyfills/pull/56" target="_blank" rel="noopener noreferrer">polyfill em desenvolvimento</a> para navegadores que ainda não têm suporte.

## Usando as gap decorations

Chega de teoria: é hora de expandir a <a href="https://microsoftedge.github.io/Demos/css-gap-decorations/personal-site.html" target="_blank" rel="noopener noreferrer">demonstração</a> que Patrick usou em seu artigo. Novas seções serão adicionadas, usando os recursos mais recentes das gap decorations ao longo do caminho.

<figure>
  <img src="/images/blog/css-gap-decorations/site-pessoal-sem-gap-decorations.webp" alt="Homepage de um site pessoal com fundo preto e texto branco, mostrando linhas brancas entre os posts do blog." />
  <figcaption>Antes (<a href="https://microsoftedge.github.io/Demos/css-gap-decorations/personal-site.html" target="_blank" rel="noopener noreferrer">ao vivo</a>, <a href="https://github.com/MicrosoftEdge/Demos/blob/main/css-gap-decorations/personal-site.html" target="_blank" rel="noopener noreferrer">código-fonte</a>)</figcaption>
</figure>

<figure>
  <img src="/images/blog/css-gap-decorations/css-gap-decorations.webp" alt="Homepage de um site pessoal com fundo preto e texto branco, mostrando linhas brancas entre os posts do blog." />
  <figcaption>Depois (<a href="https://microsoftedge.github.io/Demos/css-gap-decorations/personal-site-upgraded.html" target="_blank" rel="noopener noreferrer">ao vivo</a>, <a href="https://github.com/MicrosoftEdge/Demos/blob/main/css-gap-decorations/personal-site-upgraded.html" target="_blank" rel="noopener noreferrer">código-fonte</a>)</figcaption>
</figure>

Vamos começar com uma marcação HTML mínima:

```html
<body>
  <header>
    <h1>My personal site</h1>
    <p class="tagline">...</p>
  </header>

  <nav>
    <ul>
      <li><a href="#home">Home</a></li>
      <!-- etc. -->
    </ul>
  </nav>

  <section id="home" class="home">
    <div class="greeting">
      <p class="lead">...</p>
    </div>
    <div class="photo">
      <img src="cat.jpg" alt="A sleeping cat.">
    </div>
    <aside class="now">
      <h3>Currently</h3>
      <ul>
        <li>Lorem <span>— ipsum dolor sit amet</span></li>
        <!-- etc. -->
      </ul>
    </aside>
    <div class="note">
      <p>...</p>
    </div>
    <div class="photo">
      <img src="tree.jpg" alt="An old olive tree trunk.">
    </div>
  </section>

  <section id="blog" class="blog">
    <h2>Blog</h2>
    <div class="posts">
      <article class="post">
        <span class="date">June 2025</span>
        <h3>Lorem ipsum dolor</h3>
        <p>...</p>
      </article>
      <!-- rest of articles -->
    </div>
  </section>

  <section id="about" class="about">
    <h2>About</h2>
    <div class="bio">
      <img class="avatar" src="bike.jpg" alt="A bicycle leaning against a post.">
      <div class="text">
        <p>...</p>
        <!-- etc. -->
      </div>
    </div>
  </section>

  <section id="links" class="links">
    <h2>Elsewhere</h2>
    <ul>
      <li><a href="#">GitHub</a></li>
      <!-- etc. -->
    </ul>
  </section>

  <footer>
    <p>&copy; 2025 My personal site.</p>
  </footer>
</body>
```

E aqui está o CSS inicial. A página é um grande grid, com linhas de linha (row rules) atuando como divisores de seção. A área de navegação é um layout flexbox, com linhas de coluna tracejadas.

```css
body {
  display: grid;
  gap: 4rem;
  margin: 2rem;
  row-rule:
    1rem solid #efefef,
    repeat(2, 2px solid #efefef);
}

nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: 2rem;
  column-rule: 2px dashed #666;
}
```

O restante do artigo constrói a partir daqui.

### Passo 1: suportar qualquer número de seções com repeat(auto)

No CSS inicial, o elemento `body` usa `repeat(2, 2px solid #efefef)` porque o site de partida tinha três seções estáticas. Como novas seções estão sendo adicionadas, o ideal é que o site se adapte automaticamente caso mais seções sejam incluídas no futuro.

Por isso, o número fixo de repetições será trocado por um repetidor `auto`. Assim, a página pode crescer e as linhas divisórias de seção acompanham esse crescimento:

```css
body {
  /* ... */
  row-rule:
    1rem solid #efefef,
    repeat(auto, 2px solid #efefef);
}
```

![Um layout simples com quatro seções de largura total empilhadas verticalmente.](/images/blog/css-gap-decorations/layout-quatro-secoes-repeat-auto.webp)

### Passo 2: decorar os espaços do flexbox na seção inicial (home)

Para a seção inicial (home), teremos um container flexbox com quebra de linha (wrap), contendo texto e imagens. O elemento com classe `.home` define o layout flexbox, e os diversos elementos dentro dele usam diferentes valores de <a href="https://css-tricks.com/almanac/properties/f/flex-basis/" target="_blank" rel="noopener noreferrer"><code>flex-basis</code></a>:

```css
.home {
  display: flex;
  flex-wrap: wrap;
  gap: 3rem;
}

.home > * {
  flex: 1 1 12.5rem;
}

.home .greeting {
  flex-basis: 26.25rem;
}

.home .note {
  flex-basis: 22.5rem;
}
```

Aqui está a seção home, sem decorações:

![Dois cards de post com texto à direita e imagem à esquerda, empilhados verticalmente, onde o post de baixo é mais largo que o de cima.](/images/blog/css-gap-decorations/home-sem-decoracoes.webp)

Agora, para adicionar um pouco da mágica das gap decorations, usaremos as propriedades `row-rule` e <a href="https://css-tricks.com/almanac/properties/c/column-rule/" target="_blank" rel="noopener noreferrer"><code>column-rule</code></a>:

```css
.home {
  /* ... */
  row-rule: 2px solid #999;
  column-rule: 2px solid #999;
}
```

Aliás, como as linhas horizontais e verticais usam o mesmo valor, dá para condensá-las no novo shorthand `rule` e escrever uma única linha de código:

```css
.home {
  /* ... */
  rule: 2px solid #999;
}
```

O resultado é este:

![Dois cards de post com texto à direita e imagem à esquerda, empilhados verticalmente, onde o post de baixo é mais largo que o de cima. Linhas brancas separam as colunas e linhas.](/images/blog/css-gap-decorations/home-com-rule-basica.webp)

Por padrão, as linhas de coluna ocupam toda a altura de cada linha do flexbox. Como há um gap de `3rem`, as duas linhas do flexbox ficam separadas. O objetivo aqui é fazer as linhas de coluna se encontrarem com a linha de linha (row rule).

Para isso, será usada a propriedade `column-rule-inset` com o valor `overlap-join`. Esse valor une as linhas adjacentes nas junções, mantendo as pontas externas (os caps) niveladas em `0`.

```css
.home {
  /* ... */
  column-rule-inset: overlap-join;
}
```

![Dois cards de post com texto à direita e imagem à esquerda, empilhados verticalmente, onde o post de baixo é mais largo que o de cima. Linhas brancas separam as colunas e linhas e se unem perfeitamente.](/images/blog/css-gap-decorations/home-com-overlap-join.webp)

### Passo 3: decorar itens de grid que ocupam múltiplas colunas ou linhas na seção do blog

Para a seção Blog, será usado um grid, permitindo que posts específicos ocupem múltiplas colunas ou linhas para dar destaque.

```css
.posts {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 3rem;
}

.post.feature { grid-column: span 2; }

.post.tall { grid-row: span 2; }
```

Veja como fica a seção sem decorações:

![Um grid de blog com uma primeira linha de três artigos contendo título e resumo. A segunda linha mostra dois posts com imagem no topo, título e resumo. O post à direita ocupa também a linha seguinte, que tem mais dois posts apenas com título e resumo. A última linha tem um único post com título e resumo.](/images/blog/css-gap-decorations/blog-grid-sem-decoracoes.webp)

Assim como na seção home, vamos adicionar a mágica das gap decorations:

```css
.posts {
  /* ... */
  rule: 2px solid #999;
}
```

O que resulta nisto:

![Um grid de blog com uma série de oito posts ocupando diferentes colunas e linhas, com linhas brancas conectando as colunas e linhas.](/images/blog/css-gap-decorations/blog-grid-com-rule.webp)

Como as linhas que aparecem ao lado de células vazias do grid não ficam boas visualmente, elas serão removidas com a nova propriedade `rule-visibility-items`:

```css
.posts {
  /* ... */
  rule-visibility-items: around;
}
```

Com esse valor, as gap decorations só serão desenhadas quando pelo menos um dos lados do gap tiver conteúdo, então o espaço entre duas células vazias na última linha fica limpo, em vez de exibir uma linha solta no vazio:

![Um grid de blog com uma série de oito posts ocupando diferentes colunas e linhas, com linhas brancas conectando as colunas e linhas.](/images/blog/css-gap-decorations/blog-grid-rule-visibility-items.webp)

De forma parecida com o passo anterior, para deixar as junções entre as decorações desse grid mais organizadas, será usado novamente o valor `overlap-join` da propriedade `rule-inset`:

```css
.posts {
  /* ... */
  rule-inset: overlap-join;
}
```

E aqui está o resultado:

![Um grid de blog com uma série de oito posts ocupando diferentes colunas e linhas, com linhas brancas conectando as colunas e linhas.](/images/blog/css-gap-decorations/blog-grid-overlap-join.webp)

### Passo 4: recolher decorações na seção Sobre (About)

Para a seção Sobre, a ideia é ter uma foto circular lado a lado com o texto, separadas por uma linha. Mas também será explorada a nova possibilidade de reduzir o tamanho das gap decorations.

Primeiro, um container flexbox posiciona a foto e o texto da bio lado a lado:

```css
.bio {
  display: flex;
  align-items: center;
  gap: 2.5rem;
}
```

Isso gera o seguinte resultado, uma espécie de media card comum em diversos sites:

![Um componente de card com fundo preto e texto branco. Uma imagem circular está à esquerda e um bloco de texto está à direita.](/images/blog/css-gap-decorations/bio-sem-decoracoes.webp)

Agora, a gap decoration é aplicada:

```css
.bio {
  /* ... */
  column-rule: 2px solid #999;
}
```

O que resulta em:

![Um componente de card com fundo preto e texto branco. Uma imagem circular está à esquerda e um bloco de texto está à direita. Uma linha branca vertical separa os dois lados.](/images/blog/css-gap-decorations/bio-com-column-rule.webp)

Desta vez, porém, para dar um pouco mais de respiro, a propriedade `column-rule-inset` será usada para reduzir o tamanho da linha separadora:

```css
.bio {
  /* ... */
  column-rule-inset: 2.5rem;
}
```

E aqui está o resultado:

![Um componente de card com fundo preto e texto branco. Uma imagem circular está à esquerda e um bloco de texto está à direita. Uma linha branca vertical separa os dois lados e é mais curta que a altura total do card.](/images/blog/css-gap-decorations/bio-com-inset.webp)

### Passo 5: separar links

Para a seção Links, como há bastante itens, eles serão organizados em um grid.

```css
.links ul {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.5rem 2.5rem;
}
```

Assim:

![Um grid de quatro por três de links.](/images/blog/css-gap-decorations/grid-links-sem-decoracoes.webp)

Vamos adicionar gap decorations, desta vez com aparências diferentes para as linhas de linha e de coluna:

```css
.links ul {
  /* ... */
  row-rule: 1px solid #c9a96a;
  column-rule: 3px solid #6a707a;
}
```

![Um grid de quatro por três de links com linhas brancas separando as colunas e linhas.](/images/blog/css-gap-decorations/grid-links-com-rules.webp)

Observando com atenção, as linhas de coluna mais grossas aparecem atrás das linhas de linha mais finas. Para controlar isso e fazer as linhas de coluna aparecerem na frente, será usada a nova propriedade `rule-overlap`:

```css
.links ul {
  /* ... */
  rule-overlap: column-over-row;
}
```

Essa propriedade faz exatamente o que o nome sugere: permite escolher se as colunas devem ser pintadas sobre as linhas, ou as linhas sobre as colunas.

E o resultado é este:

![Um grid de quatro por três de links com linhas brancas separando as colunas e linhas, onde as linhas verticais são mais curtas que as células.](/images/blog/css-gap-decorations/grid-links-rule-overlap.webp)

Por fim, a intenção é deixar as linhas de coluna um pouco mais curtas que o grid, sem separá-las por linha. Para isso, entra em cena a propriedade `column-rule-inset-cap`, que controla as pontas das gap decorations que não são junções ou interseções:

```css
.links ul {
  /* ... */
  column-rule-inset-cap: 1.75rem;
}
```

E aqui está o resultado:

![Um grid de quatro por três de links com linhas brancas separando as colunas e linhas, onde as linhas verticais são mais curtas que as células.](/images/blog/css-gap-decorations/grid-links-inset-cap.webp)

### Passo 6: juntando tudo

E pronto: a página está finalizada. Confira o <a href="https://microsoftedge.github.io/Demos/css-gap-decorations/personal-site-upgraded.html" target="_blank" rel="noopener noreferrer">exemplo ao vivo</a> e o <a href="https://github.com/MicrosoftEdge/Demos/blob/main/css-gap-decorations/personal-site-upgraded.html" target="_blank" rel="noopener noreferrer">código-fonte</a>:

![O layout completo do site pessoal.](/images/blog/css-gap-decorations/css-gap-decorations.webp)

## Saiba mais

Vale a pena experimentar as gap decorations na prática. A forma mais rápida é pelo <a href="https://microsoftedge.github.io/Demos/css-gap-decorations/playground.html" target="_blank" rel="noopener noreferrer">playground interativo</a>, mas também há muitas <a href="https://github.com/MicrosoftEdge/Demos/blob/main/css-gap-decorations/README.md#demos" target="_blank" rel="noopener noreferrer">outras demonstrações</a>. É só brincar com cada propriedade e ver os gaps reagirem em tempo real.

Outra boa forma de aprender é visitar a <a href="https://github.com/mdn/content/issues/44435" target="_blank" rel="noopener noreferrer">documentação do MDN</a> (em desenvolvimento no momento da publicação deste artigo) para mais referências.

## Agradecimentos

As gap decorations do CSS existem graças a um grupo de pessoas que se importa profundamente com a web, nas equipes do Edge, do Chrome e no CSS Working Group. Agradecimentos especiais a <a href="https://www.linkedin.com/in/javier-contreras-t?utm_source=share_via&utm_content=profile&utm_medium=member_ios" target="_blank" rel="noopener noreferrer">Javier Contreras Tenorio</a>, <a href="https://bsky.app/profile/kevinbcmu.bsky.social" target="_blank" rel="noopener noreferrer">Kevin Babbitt</a>, <a href="https://www.linkedin.com/in/alison-maher-6255b2121?utm_source=share_via&utm_content=profile&utm_medium=member_ios" target="_blank" rel="noopener noreferrer">Alison Maher</a>, <a href="https://www.linkedin.com/in/ian-kilpatrick-9b68a373?utm_source=share_via&utm_content=profile&utm_medium=member_iOS" target="_blank" rel="noopener noreferrer">Ian Kilpatrick</a> e <a href="https://patrickbrosset.com" target="_blank" rel="noopener noreferrer">Patrick Brosset</a>.

---

Fonte: [dpw - desenvolvimento para web](https://dpw.dev/) (pt-BR).
Guia para agentes: https://dpw.dev/llms.txt
Índice completo: https://dpw.dev/sitemap-index.xml
Feed: https://dpw.dev/rss.xml
