# O futuro do CSS: 10 recursos de olho no Interop 2027

> Funções nativas, corner-shape, reading-flow, gap decorations e mais: 10 recursos que podem chegar a todos os navegadores com o Interop 2027.

URL: https://dpw.dev/css/futuro-do-css-interop-2027/  
Publicado em: 2026-11-02  
Categoria: css  
Tags: boas-praticas, html  
Autor: Tárcio Zemel

O **futuro do CSS** está sendo decidido agora: os navegadores escolhem quais recursos priorizar no Interop 2027, e os que entram costumam chegar a todos eles em menos de um ano.

Aqui estão 10 candidatos (funções nativas, cantos chanfrados, ordem de tabulação que segue o layout, linhas entre células de grid e mais), com dicas que já dá para usar hoje.

> Artigo baseado em [The Future of CSS](https://www.joshwcomeau.com/css/interop-2027/).

Nos últimos anos, todos os grandes fabricantes de navegadores (Google, Apple, Microsoft e Mozilla, junto com a Igalia e a Bocoup) vêm trabalhando juntos no <a href="https://github.com/web-platform-tests/interop/blob/main/README.md" target="_blank" rel="noopener noreferrer">Interop</a>, um projeto para melhorar o suporte das tecnologias web em todos os navegadores.

O esforço tem dado *muito* certo: quando uma área de foco entra no Interop, ela costuma chegar perto de 100% de suporte em todos os grandes navegadores em até um ano. ✨

O CSS Subgrid é um bom exemplo. Subgrid é uma extensão poderosíssima do CSS Grid, que permite <a href="https://www.joshwcomeau.com/css/subgrid/" target="_blank" rel="noopener noreferrer">layouts totalmente novos</a>.

O Firefox o implementou lá em 2019, mas os outros navegadores passaram anos sem se mexer. Ele entrou no Interop 2023 e, no fim daquele ano, estava amplamente disponível em todos os navegadores modernos:

![Gráfico do CSS Subgrid passando de 12% dos testes aprovados em janeiro de 2023 para 91% no fim do ano. O Safari foi de 72% a 100%, o Chrome e o Edge de 12% a 100%, e o Firefox de 63% a 91%.](/images/blog/futuro-do-css-interop-2027/grafico-subgrid-interop-2023.webp)

*O eixo Y mostra a porcentagem de testes de subgrid aprovados em cada navegador. A linha preta, "Interop", mostra os testes aprovados em *todos* os navegadores. <a href="https://wpt.fyi/interop-2023?feature=interop-2022-subgrid" target="_blank" rel="noopener noreferrer">Veja os dados no wpt.fyi</a>.*

Com o fim de 2026 chegando, o Interop 2027 está sendo planejado, e a equipe da Mozilla criou um <a href="https://interop-rank.fxdx.dev/" target="_blank" rel="noopener noreferrer">sistema de ranking</a> para a comunidade votar nos recursos mais desejados. A ideia é usar esses dados para decidir o que entra no Interop do ano que vem!

Este post percorre os 10 recursos em que o autor, Josh W. Comeau, votou, como uma prévia de como o CSS pode ficar no próximo ano. No caminho, aparecem também algumas dicas e truques que já dá para usar hoje!

## 1. Funções em CSS

*Suporte em outubro de 2026: Chrome 155 e Edge 154. Ainda não disponível no Firefox 157 nem no Safari 27. Mais detalhes no <a href="https://caniuse.com/wf-function" target="_blank" rel="noopener noreferrer">caniuse</a>.*

Uma das ideias mais empolgantes é a <a href="https://github.com/web-platform-tests/interop/issues/1357" target="_blank" rel="noopener noreferrer">proposta de adicionar funções ao CSS</a>:

```css
/* Define uma função: */
@function --gradient-to-transparent(--color, --direction: bottom) {
  result: linear-gradient(
    to var(--direction),
    var(--color),
    transparent
  );
}

/* Chama a função: */
.elem {
  background: --gradient-to-transparent(red);
}

/* …o que produz: */
.elem {
  background: linear-gradient(
    to bottom,
    red,
    transparent
  );
}
```

Para quem conhece JavaScript, isso deve parecer bem familiar. Funções novas são definidas com `@function`, e o valor retornado é indicado com `result`.

Dá para fazer *muita* coisa legal com isso. O caso de uso que mais interessa ao autor é converter coordenadas polares em cartesianas, um conceito que aparece o tempo todo no curso dele, <a href="https://whimsy.joshwcomeau.com/" target="_blank" rel="noopener noreferrer">Whimsical Animations</a>:

```css
@function --translate-polar(--angle, --distance) {
  result: translate(
    calc(cos(var(--angle)) * var(--distance)),
    calc(sin(var(--angle)) * var(--distance))
  );
}

/* Move este elemento 100px num ângulo de 45°: */
.particle {
  transform: --translate-polar(45deg, 100px);
}
```

Parece coisa de ficção científica, mas já está implementado nos navegadores baseados em Chromium. Se entrar no Interop 2027, as chances de ficar amplamente disponível em pouco tempo são muito boas!

## 2. Chanfros e squircles com `corner-shape`

*Suporte em outubro de 2026: Chrome 155 e Edge 154. Ainda não disponível no Firefox 157 nem no Safari 27. Mais detalhes no <a href="https://caniuse.com/wf-corner-shape" target="_blank" rel="noopener noreferrer">caniuse</a>.*

No CSS, a propriedade `border-radius` arredonda as bordas dos nós do DOM e cria retângulos arredondados. Na prática, ela acrescenta um quarto de círculo em cada canto, ligando os quatro lados retos.

A propriedade `corner-shape` explora *outras formas* de ligar esses quatro lados. Ela traz algumas opções novas:

```html
<style>
  .box {
    border-radius: 16px;

    &.squircle {
      corner-shape: squircle;
    }
    &.bevel {
      corner-shape: bevel;
    }
    &.notch {
      corner-shape: notch;
    }
    &.scoop {
      corner-shape: scoop;
    }
  }
</style>

<div class="wrapper">
  <div class="box">Redondo (padrão)</div>
  <div class="box squircle">Squircle</div>
  <div class="box bevel">Bevel</div>
  <div class="box notch">Notch</div>
  <div class="box scoop">Scoop</div>
</div>
```

> **Demonstração interativa:** cinco caixas com border-radius de 16px e os valores round, squircle, bevel, notch e scoop de corner-shape. Disponível na versão HTML desta página.

![Cinco caixas, cada uma com um formato de canto: round, squircle, bevel, notch e scoop. Round é o padrão; squircle é um canto arredondado mais suave e um pouco mais anguloso; bevel é um corte diagonal de 45 graus; notch é um recorte quadrado; e scoop é um recorte circular.](/images/blog/futuro-do-css-interop-2027/opcoes-corner-shape.webp)

*O resultado em navegadores com suporte a corner-shape.*

> **Ferramenta:** [Playground de corner-shape](https://dpw.dev/ferramentas/playground-corner-shape/): Teste cada valor de corner-shape com raios diferentes e copie o CSS com fallback.

Quando o autor ouviu falar dessa propriedade pela primeira vez, o que mais o empolgou foi o `squircle`. Para quem não conhece, squircles são um algoritmo alternativo para gerar cantos arredondados usando superelipses. A Apple os usa há anos porque eles produzem bordas mais suaves e delicadas.

Depois de brincar um tempo com `corner-shape`, porém, o valor que ele mais passou a usar foi `corner-shape: bevel`. Ele é ótimo para criar interfaces com cara de videogame ou ficção científica. Esta é uma prévia de um projeto paralelo do autor, com *muito* `corner-shape: bevel`:

![Captura de tela de uma interface monocromática com várias caixas cinza sobrepostas, todas com um canto chanfrado em 45 graus.](/images/blog/futuro-do-css-interop-2027/interface-cantos-chanfrados.webp)

Tecnicamente, já dava para fazer algo assim com `clip-path` ou máscaras. Mas, diferente desses recursos, o `corner-shape` *muda o formato da border-box*. Isso significa que bordas, outlines e box-shadows acompanham corretamente o novo formato dos cantos!

E, mesmo sem suporte no Firefox e no Safari (em outubro de 2026), já é razoável começar a usar a propriedade hoje. Ela é um caso perfeito de melhoria progressiva!

## 3. Possibilidades infinitas com `border-shape`

*Suporte em outubro de 2026: Chrome 155 e Edge 154. Ainda não disponível no Firefox 157 nem no Safari 27. Mais detalhes no <a href="https://caniuse.com/wf-border-shape" target="_blank" rel="noopener noreferrer">caniuse</a>.*

Além do `corner-shape`, existe uma proposta separada para a <a href="https://github.com/web-platform-tests/interop/issues/1371" target="_blank" rel="noopener noreferrer">`border-shape`</a>, que é basicamente uma versão de mais baixo nível, em que *a própria borda é desenhada à mão.*

O autor tratou dessa propriedade a fundo numa <a href="https://www.joshwcomeau.com/email/2026-09-14-new-css-features/" target="_blank" rel="noopener noreferrer">edição recente da newsletter dele</a>, então aqui vai só um resumo: a `border-shape` permite criar qualquer formato de borda com linhas retas, arcos e curvas de Bézier. Aqui no blog, o post <a href="/css/css-border-shape/" target="_blank">A nova propriedade CSS border-shape</a> também mostra vários exemplos.

Ela foi usada para desenhar este card, com um grande recorte circular no topo:

![Captura de tela de um card verde na vertical com uma moeda dourada flutuando. O card tem cantos em estilo squircle e um grande recorte circular no topo, que acompanha a borda de baixo da moeda.](/images/blog/futuro-do-css-interop-2027/card-recorte-circular.webp)

Assim como o `corner-shape`, essa propriedade muda a border-box real do elemento, então bordas, outlines e sombras acompanham o formato. No card acima, o formato foi desenhado primeiro, e depois vieram uma borda branca e um outline preto para chegar ao efeito final!

Dá até para animar entre formatos de borda diferentes, como neste vídeo:

<video autoplay loop muted playsinline width="1000" height="528">
  <source src="/images/blog/futuro-do-css-interop-2027/border-shape-animado.webm" type="video/webm" />
</video>

Há mais detalhes sobre essa propriedade na <a href="https://www.joshwcomeau.com/email/2026-09-14-new-css-features/" target="_blank" rel="noopener noreferrer">edição da newsletter sobre o assunto</a>.

## 4. Anchored Container Queries

*Suporte em outubro de 2026: Chrome 155 e Edge 154. Ainda não disponível no Firefox 157 nem no Safari 27. Mais detalhes no <a href="https://caniuse.com/wf-container-anchor-position-queries" target="_blank" rel="noopener noreferrer">caniuse</a>.*

O autor publicou há pouco um <a href="https://www.joshwcomeau.com/css/anchor-positioning/" target="_blank" rel="noopener noreferrer">post sobre Anchor Positioning</a>, um dos recursos de CSS moderno mais empolgantes (que foi priorizado no Interop 2026 e hoje está amplamente disponível!).

A API de Anchor Positioning permite ancorar um elemento em outro. Por exemplo, um tooltip flutuante pode ser ancorado no elemento que o aciona, e assim, não importa onde esse elemento esteja na página, o tooltip sempre fica ligado a ele.

Quem já tentou resolver esse problema na mão sabe que ele é surpreendentemente difícil. O tooltip pode, por exemplo, precisar flutuar acima da âncora, mas e se a âncora estiver perto do topo do viewport?

> **Demonstração interativa:** o mesmo tooltip acima de um botão: num quadro ele cabe, no outro o botão está colado no topo e o tooltip é cortado. Disponível na versão HTML desta página.

A primeira versão da API de Anchor Positioning já trazia *quase* tudo o que é preciso para resolver isso com CSS. Ela permite definir posições *de fallback*: se o elemento-alvo não couber acima da âncora, ele pode ir sozinho para baixo.

**Só faltava saber se o elemento-alvo tinha mudado de lado.** Não havia como saber, em CSS, se ele estava acima ou abaixo da âncora, ou seja, se usava a posição padrão ou a de fallback. Nos tooltips, isso é um problema, porque normalmente se quer uma setinha apontando para a âncora.

O "Level 2" da API de Anchor Positioning traz um novo tipo de container query, que verifica se o elemento-alvo está usando uma posição de fallback. Dá para saber mais no <a href="https://www.joshwcomeau.com/css/anchor-positioning/#flipped-carets-with-anchored-container-queries-3" target="_blank" rel="noopener noreferrer">post do autor sobre Anchor Positioning</a> ou na <a href="https://github.com/web-platform-tests/interop/issues/1363" target="_blank" rel="noopener noreferrer">proposta para o Interop 2027</a>.

## 5. A função CSS `inherit()`

O autor admite que nunca tinha ouvido falar <a href="https://github.com/web-platform-tests/interop/issues/1453" target="_blank" rel="noopener noreferrer">desta proposta</a> e, até onde ele sabe, ela não está implementada em nenhum navegador. Ela nem aparece no caniuse, então não há o quadrinho de suporte desta vez!

Mesmo assim, bastou ver a proposta para ela virar uma necessidade. 😂

A palavra-chave `inherit` do CSS repassa um valor do elemento pai, mesmo quando a propriedade normalmente não é herdada:

```html
<style>
  main {
    border: 3px dashed red;
  }
  p {
    border: inherit;
  }
</style>

<main>
  <p>
    Este parágrafo herda a borda vermelha tracejada!
  </p>
</main>
```

> **Demonstração interativa:** um parágrafo que herda a borda vermelha tracejada do elemento pai com border: inherit. Disponível na versão HTML desta página.

É um truque útil para reaproveitar valores, mas muitas vezes ele não funciona *exatamente* como se quer. Um exemplo são raios de borda aninhados:

```html
<style>
  main {
    border: 2px solid red;
    border-radius: 16px;
  }
  p {
    border: inherit;
    border-radius: inherit;
  }
</style>

<main>
  <p>
    Este parágrafo herda a borda vermelha tracejada!
  </p>
</main>
```

> **Demonstração interativa:** borda arredondada aninhada: o parágrafo herda o mesmo raio de 16px do pai e o canto interno fica largo demais. Disponível na versão HTML desta página.

Para os raios aninhados ficarem certos, o raio de dentro precisa ser menor. Ou seja, o que se quer não é *exatamente* o valor herdado, e sim uma transformação dele.

> **Ferramenta:** [Calculadora de raios aninhados](https://dpw.dev/ferramentas/raios-aninhados/): Calcule o raio interno certo a partir do raio externo e do espaço entre as caixas.

É aí que entra a função `inherit()` proposta. Ela pega o valor herdado e permite modificá-lo com `calc()`:

```css
p {
  border-radius: calc(inherit() - 4px);
}
```

Como o recurso ainda está bem no começo, seria um pouco surpreendente vê-lo entrar no Interop 2027. Mas tomara que ele chegue um dia! Parece útil demais. 😄

## 6. Scroll-triggered animations

*Suporte em outubro de 2026: Chrome 155 e Edge 154. Ainda não disponível no Firefox 157 nem no Safari 27. Mais detalhes no <a href="https://caniuse.com/wf-container-anchor-position-queries" target="_blank" rel="noopener noreferrer">caniuse</a>.*

No <a href="https://www.joshwcomeau.com/animation/scroll-driven-animations/" target="_blank" rel="noopener noreferrer">post do autor sobre scroll-driven animations</a>, a rolagem avança e volta uma animação de keyframes. Dá para usar isso, por exemplo, para um elemento aparecer aos poucos enquanto atravessa o viewport:

> **Demonstração interativa:** caixa rolável em que um card vai de transparente a opaco conforme sobe da borda de baixo até o meio, acompanhando a rolagem. Disponível na versão HTML desta página.

As scroll-driven animations <a href="https://wpt.fyi/interop-2026?feature=interop-2026-scroll-driven-animations" target="_blank" rel="noopener noreferrer">fizeram parte do Interop 2026</a> e hoje funcionam em todos os navegadores. Além das animações *conduzidas* pela rolagem, porém, existe uma proposta separada de <a href="https://github.com/web-platform-tests/interop/issues/1433" target="_blank" rel="noopener noreferrer">animações *disparadas* pela rolagem</a> (scroll-triggered).

Aqui no blog, o post <a href="/css/scroll-driven-animations-direcoes-opostas/" target="_blank">Como usar scroll-driven animations em direções opostas</a> mostra outro uso das primeiras.

Nas scroll-triggered animations, a ideia é disparar uma animação de keyframes quando o usuário rola até um ponto específico, como um sensor de presença que é acionado. A partir daí, a animação roda normalmente, pela duração definida.

Hoje dá para implementar animações disparadas pela rolagem com a API `IntersectionObserver` do JavaScript, mas é meio trabalhoso. Vai ser ótimo poder usar CSS para os dois tipos de animação, já que cada um tem seus próprios casos de uso.

Há mais sobre scroll-triggered animations neste <a href="https://developer.chrome.com/blog/scroll-triggered-animations" target="_blank" rel="noopener noreferrer">ótimo artigo do Bramus</a>.

## 7. CSS `reading-flow` e `reading-order`

*Suporte em outubro de 2026: Chrome 155 e Edge 154. Ainda não disponível no Firefox 157 nem no Safari 27. Mais detalhes no <a href="https://caniuse.com/wf-reading-flow" target="_blank" rel="noopener noreferrer">caniuse</a>.*

O autor está trabalhando num **projeto ultrassecreto** com um layout dinâmico baseado em grid. Os itens ficam organizados de um jeito bem diferente no desktop e no mobile:

![Imagem borrada com uma lista de itens à esquerda, um grande botão vermelho no meio e alguns painéis extras à direita.](/images/blog/futuro-do-css-interop-2027/layout-desktop.webp)

*Layout no desktop*

![Imagem borrada com uma única coluna estreita: um grande botão vermelho, depois uma lista de itens e, por fim, alguns painéis de configuração.](/images/blog/futuro-do-css-interop-2027/layout-mobile.webp)

*Layout no mobile*

Essa é uma das grandes vantagens do CSS responsivo, mas ela tem um efeito colateral chato: a ordem de tabulação sempre segue a *ordem do DOM*, e não a ordem visual.

Então, quem navega entre os elementos com tecnologias assistivas sempre encontra a mesma ordem, mesmo que o layout mude radicalmente conforme o tamanho da tela.

No desktop, o primeiro item visual é a lista de sons à esquerda; no mobile, é o grande botão vermelho. O elemento que vier primeiro no DOM recebe o foco primeiro, e isso vai estar errado para uma parte dos usuários, sempre.

Felizmente, a nova propriedade `reading-flow` resolve esse problema, e há uma <a href="https://github.com/web-platform-tests/interop/issues/1349" target="_blank" rel="noopener noreferrer">proposta para o Interop 2027</a>.

A ideia básica é indicar que a ordem de tabulação deve seguir uma das várias ordens visuais possíveis:

```css
.grid {
  display: grid;
  reading-flow: grid-rows;
}
```

Há valores tanto para CSS Grid quanto para Flexbox e, quando é preciso ainda mais controle, a propriedade `reading-order` permite criar uma ordem personalizada, mais ou menos como o `tabIndex` do HTML.

Quem defende essa propriedade é Rachel Andrew, uma das grandes referências do autor. Há mais sobre ela no <a href="https://developer.chrome.com/blog/reading-flow" target="_blank" rel="noopener noreferrer">post da Rachel sobre *reading-flow*</a>.

## 8. Animações de tamanhos por palavra-chave com `interpolate-size` e `calc-size()`

*Suporte em outubro de 2026: Chrome 155 e Edge 154. Ainda não disponível no Firefox 157 nem no Safari 27. Mais detalhes no <a href="https://caniuse.com/wf-interpolate-size" target="_blank" rel="noopener noreferrer">caniuse</a>.*

Um problema antigo da web é não conseguir animar entre valores de palavra-chave como `auto`. A propriedade `interpolate-size` resolve isso, e existe uma <a href="https://github.com/web-platform-tests/interop/issues/1373" target="_blank" rel="noopener noreferrer">proposta para o Interop 2027</a> que a inclui, junto com a função relacionada `calc-size()`.

O caso de uso mais comum é animar entre `height: 0` e `height: auto`, para criar interfaces recolhíveis do tipo acordeão:

```html
<style>
  html {
    interpolate-size: allow-keywords;
  }

  @supports (
    interpolate-size: allow-keywords
  ) {
    details {
      overflow: hidden;

      &::details-content {
        height: 0;
        transition:
          height 300ms,
          content-visibility 300ms;
        transition-behavior: allow-discrete;
      }
      &:open::details-content {
        height: auto;
      }
    }
  }
</style>

<details>
  <summary>Clique para mostrar/esconder!</summary>
  <p>Este é o conteúdo escondido, que anima ao aparecer e ao sumir. 😄</p>
</details>
```

> **Demonstração interativa:** um details que anima a altura de 0 até auto ao abrir e ao fechar. Disponível na versão HTML desta página.

Para quem lê num navegador sem suporte a `interpolate-size`, a gravação abaixo mostra como fica nos navegadores com suporte:

<video autoplay loop muted playsinline width="634" height="238">
  <source src="/images/blog/futuro-do-css-interop-2027/details-animado.webm" type="video/webm" />
</video>

O exemplo é, sim, meio complexo, porque depende de outros recursos de CSS pouco conhecidos (mas bem suportados), como `transition-behavior`. O ponto principal é que `interpolate-size: allow-keywords` torna esse tipo de transição possível.

A proposta está em discussão há um bom tempo e existe no Chrome desde 2024, então tomara que entre no Interop 2027!

Mesmo sem estar em todos os navegadores, já dá para usá-la hoje como melhoria progressiva. Só é importante deixar a `transition` dentro de um `@supports`, senão os navegadores sem suporte ganham um pequeno atraso.

## 9. CSS gap decorations

*Suporte em outubro de 2026: Chrome 155 e Edge 154. Ainda não disponível no Firefox 157 nem no Safari 27. Mais detalhes no <a href="https://caniuse.com/wf-gap-decorations" target="_blank" rel="noopener noreferrer">caniuse</a>.*

Uma das coisas que tornam o layout de CSS Grid único é que os filhos da grid são posicionados em linhas e colunas definidas inteiramente no CSS. Em todos os outros modos de layout, os elementos são posicionados a partir de outros elementos! No layout de tabela, por exemplo, cada célula tem um `<td>` ou `<th>` correspondente.

O CSS Grid tem muitas vantagens, mas uma das desvantagens é que não é tão fácil pôr bordas entre as células. Se uma célula está vazia, não existe elemento para receber um `border: 1px solid`!

A <a href="https://github.com/web-platform-tests/interop/issues/1374" target="_blank" rel="noopener noreferrer">proposta de gap decorations</a> traz um novo conjunto de propriedades CSS que permite usar uma sintaxe parecida com a de `border` na própria grid. Veja:

```html
<style>
  .grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(3, 1fr);
    gap: 1px;
    border: 1px solid red;
    /* 👇 O recurso novo 👇 */
    rule: 1px solid red;
  }
</style>

<div class="grid">
  <div class="child">1</div>
  <div class="child">2</div>
</div>
```

> **Demonstração interativa:** grade 3x3 com só dois filhos e linhas vermelhas entre todas as linhas e colunas, desenhadas pela propriedade rule. Disponível na versão HTML desta página.

Para quem lê num navegador sem suporte à propriedade `rule`, a imagem abaixo mostra como fica nos navegadores com suporte:

![Grade 3 por 3 com bordas vermelhas entre todas as linhas e colunas. As duas primeiras células têm um elemento cor de pêssego; as outras estão vazias.](/images/blog/futuro-do-css-interop-2027/grid-com-rule.webp)

Assim como `border`, a propriedade `rule` é um atalho (shorthand) que define a largura, a cor e o estilo (tracejado, pontilhado, sólido) da linha. Também dá para usar `row-rule` e `column-rule` quando a ideia é desenhar linhas só entre as linhas ou só entre as colunas.

O post <a href="/css/css-gap-decorations/" target="_blank">CSS Gap Decorations</a> detalha o recurso.

**O contorno clássico**

Enquanto os navegadores não suportam gap decorations, como pôr linhas entre as células de uma grid?

O autor usa o mesmo contorno há muitos anos. Ele fica assim:

```html
<style>
  .grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(3, 1fr);
    gap: 1px;
    padding: 1px;
    background-color: red;
  }
  .empty.child {
    background-color: white;
  }
</style>

<div class="grid">
  <div class="child">1</div>
  <div class="child">2</div>
  <div class="empty child"></div>
  <div class="empty child"></div>
  <div class="empty child"></div>
  <div class="empty child"></div>
  <div class="empty child"></div>
  <div class="empty child"></div>
  <div class="empty child"></div>
</div>
```

> **Demonstração interativa:** a mesma grade 3x3 com fundo vermelho aparecendo pelo gap de 1px e sete elementos vazios tapando as células. Disponível na versão HTML desta página.

A ideia básica é dar à grid um `background-color` da cor da borda desejada e um `gap` de 1px, para o fundo aparecer entre as células.

Infelizmente, isso exige vários nós vazios no DOM para preencher cada célula da grid. Também só funciona quando o fundo da página é de uma cor sólida. E está longe da flexibilidade da futura propriedade `rule`: não dá, por exemplo, para deixar um espaço entre a borda externa da grid e as linhas internas.

Essa é só uma das muitas técnicas exploradas no curso completo de CSS do autor, <a href="https://css-for-js.dev/" target="_blank" rel="noopener noreferrer">**CSS for JavaScript Developers**</a>.

## 10. Scroll state container queries

*Suporte em outubro de 2026: Chrome 155 e Edge 154. Ainda não disponível no Firefox 157 nem no Safari 27. Mais detalhes no <a href="https://caniuse.com/wf-container-scroll-state-queries" target="_blank" rel="noopener noreferrer">caniuse</a>.*

Quem trabalha com `position: sticky` provavelmente já quis saber se o elemento está "grudado" ou não. Por exemplo, para mudar a cor de fundo de um cabeçalho sticky quando ele gruda no topo do viewport.

Esta <a href="https://github.com/web-platform-tests/interop/issues/1364" target="_blank" rel="noopener noreferrer">proposta</a> é a implementação de um novo tipo de container query, que passa a valer quando um elemento com `position: sticky` sai da posição normal no fluxo e fica preso ao viewport. Veja:

```html
<style>
  header {
    position: sticky;
    top: 0;
    container-type: scroll-state;
  }

  @container scroll-state(stuck: top) {
    .header-content {
      background: var(--gray-300);
      border-bottom:
        1px solid var(--gray-500);
    }
  }
</style>

<header>
  <div class="header-content">
    Exemplo de cabeçalho sticky
  </div>
</header>
<p>
  👇 Role para baixo 👇
</p>
```

> **Demonstração interativa:** caixa rolável com um cabeçalho sticky que ganha fundo cinza e borda inferior quando gruda no topo. Disponível na versão HTML desta página.

Para quem lê num navegador sem suporte a esse recurso, a gravação abaixo mostra como fica:

<video autoplay loop muted playsinline width="628" height="366">
  <source src="/images/blog/futuro-do-css-interop-2027/cabecalho-sticky-scroll-state.webm" type="video/webm" />
</video>

Curiosamente, essa nova API não serve *só* para posicionamento sticky: ela permite consultar todo tipo de estado ligado à rolagem. Dá para saber, por exemplo, se um contêiner rolável está no topo ou no fim, o que ajuda a mostrar aqueles gradientes que indicam que ainda há conteúdo para rolar:

```html
<style>
  .container {
    height: 100%;
    container-type: scroll-state size;
    overflow: auto;

    &::before {
      top: 0;
      background: linear-gradient(
        to bottom,
        black,
        transparent
      );
      opacity: 0;

      @container scroll-state(scrollable: top) {
        opacity: 1;
      }
    }
    &::after {
      bottom: 0;
      background: linear-gradient(
        to top,
        black,
        transparent
      );
      opacity: 0;

      @container scroll-state(scrollable: bottom) {
        opacity: 1;
      }
    }

    /* Estilos compartilhados */
    &::before, &::after {
      content: '';
      position: absolute;
      left: 0;
      right: 0;
      height: 50px;
      pointer-events: none;
      transition: opacity 300ms;
    }
  }
</style>

<div class="container">
  <ul>
    <li>Um</li>
    <li>Dois</li>
    <li>Três</li>
    <li>Quatro</li>
    <li>Cinco</li>
    <li>Seis</li>
    <li>Sete</li>
    <li>Oito</li>
    <li>Nove</li>
    <li>Dez</li>
    <li>Onze</li>
    <li>Doze</li>
    <li>Treze</li>
    <li>Quatorze</li>
    <li>Quinze</li>
    <li>Dezesseis</li>
    <li>Dezessete</li>
    <li>Dezoito</li>
    <li>Dezenove</li>
    <li>Vinte</li>
    <li>Vinte e um</li>
    <li>Vinte e dois</li>
    <li>Vinte e três</li>
    <li>Vinte e quatro</li>
    <li>Vinte e cinco</li>
  </ul>
</div>
```

> **Demonstração interativa:** lista rolável de 25 itens com gradientes no topo e na base que só aparecem quando ainda há conteúdo para rolar naquela direção. Disponível na versão HTML desta página.

Se ainda dá para rolar para cima, `scrollable: top` vale, e o pseudo-elemento aparece flutuando sobre o topo do conteúdo. Com a rolagem toda para cima, `scrollable: top` deixa de valer, e o gradiente some.

Em navegadores com suporte, o resultado é este:

<video autoplay loop muted playsinline width="434" height="534">
  <source src="/images/blog/futuro-do-css-interop-2027/gradientes-scroll-state.webm" type="video/webm" />
</video>

## Conclusão

O Interop entra no sétimo ano, e é inegável que o projeto tem sido um sucesso enorme para a web. Que bom que ele continua crescendo!

O momento é meio estranho para quem desenvolve para a web, e muita gente se pergunta se ainda precisa se importar com esse tipo de coisa. Se o trabalho todo vai ser delegado a LLMs, ainda vale acompanhar os recursos de CSS mais recentes?

**Para o autor, isso nunca foi tão importante.** Não dá para esperar que LLMs usem recursos modernos de CSS quando boa parte dos dados de treinamento deles tem anos. A maioria dos recursos deste post já pode ser usada hoje como melhoria progressiva e, se a história servir de guia, muitos vão estar amplamente disponíveis em breve.

Para criar as melhores experiências possíveis para o usuário, será preciso orientar os agentes a aproveitar os recursos modernos da web, e isso exige conhecê-los! O autor tratou disso numa <a href="https://www.joshwcomeau.com/email/wham-launch-005-elephant-2-p/" target="_blank" rel="noopener noreferrer">edição da newsletter</a> no começo do ano: conhecimento técnico profundo continua valendo *muito* na era dos agentes.

Por fim, vale muito <a href="https://interop-rank.fxdx.dev/" target="_blank" rel="noopener noreferrer">ranquear as suas próprias escolhas</a>! A lista tem várias propostas ótimas, incluindo APIs de JavaScript empolgantes, como a Temporal, que não fazia sentido incluir num post sobre CSS.

**Inspiração**

A ideia deste post veio de Declan Chidlow, que também <a href="https://vale.rocks/micros/20261011-0700" target="_blank" rel="noopener noreferrer">publicou as escolhas dele para o Interop 2027</a>. Na verdade, <a href="https://www.sarasoueidan.com/blog/interop-2027-rankings/" target="_blank" rel="noopener noreferrer">muita</a> <a href="https://ohhelloana.blog/my-interop-2027/" target="_blank" rel="noopener noreferrer">gente</a> <a href="https://tylersticka.com/journal/interop-2027-rank/" target="_blank" rel="noopener noreferrer">já</a> <a href="https://pawelgrzybek.com/my-interop-2027-picks/" target="_blank" rel="noopener noreferrer">compartilhou</a> o próprio ranking!

## Perguntas frequentes

### Por que `corner-shape: bevel` não muda nada no meu elemento?

Provavelmente porque falta um `border-radius`. O MDN avisa que, [sem `border-radius` ou com o raio resolvido em `0`, o `corner-shape` não tem efeito](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/corner-shape): o raio define o tamanho do canto, e o `corner-shape` só define o formato. Outro detalhe: fundo, borda, outline e sombra seguem o novo canto, mas o conteúdo continua posicionado na caixa original, então um texto encostado no canto pode sair pelo recorte. Um `padding` generoso evita isso.

### Com `reading-flow`, ainda preciso escrever o HTML na ordem certa?

Precisa. Segundo o MDN, [a ordem do código-fonte deve continuar expressando uma ordem de leitura que faça sentido](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/reading-flow), e o `reading-flow` serve para os casos em que o layout muda a ordem visual, como a grid que se reorganiza no mobile. Ele afeta tanto a navegação por Tab quanto a ordem em que o conteúdo é lido em voz alta. E, dentro de um contêiner com `reading-flow`, valores positivos de `tabindex` são ignorados.

## Teste seus conhecimentos

**Pergunta 1.** Um card tem `border` e `box-shadow`, e a ideia é chanfrar os cantos em 45 graus. Qual abordagem faz a borda e a sombra acompanharem o chanfro?

- Um `clip-path: polygon()` recortando os cantos
  O `clip-path` recorta o que já foi pintado: a borda some no corte e a sombra, que fica fora da caixa, é cortada junto.
- `border-radius` com `corner-shape: bevel` **(correta)**
  O `corner-shape` muda o formato da própria border-box, então borda, outline e sombra seguem o canto novo.
- Uma `mask-image` com gradientes nos cantos
  A máscara também esconde o que foi pintado, sem mudar a caixa. Borda e sombra não contornam o chanfro.

A resposta é `corner-shape: bevel`, junto com um `border-radius`. Diferente de `clip-path` e máscaras, ele altera o formato da border-box, e por isso bordas, outlines e box-shadows acompanham o canto.

**Pergunta 2.** Por que o post recomenda deixar a `transition` de `height` do acordeão dentro de `@supports (interpolate-size: allow-keywords)`?

- Porque `transition` não é reconhecida sem `interpolate-size`
  A `transition` funciona em qualquer navegador. O que falta sem suporte é a interpolação até `auto`.
- Porque `interpolate-size` só é ativada dentro de um `@supports`
  A propriedade vale onde for declarada, como no `html` do exemplo. O `@supports` só testa se ela existe.
- Porque, sem suporte, a transição só acrescenta um pequeno atraso **(correta)**
  Sem `interpolate-size`, a altura não anima até `auto`: ela salta, e a transição só faz o salto demorar.

Sem suporte, a transição só atrasa a abertura. O navegador não interpola até `auto`, então a altura muda de uma vez, e uma `transition` ativa só acrescenta uma espera. Com o `@supports`, quem não tem o recurso recebe o acordeão nativo, sem atraso.

**Pergunta 3.** Uma grid põe a lista na primeira coluna no desktop e o botão primeiro no mobile, só com CSS. Sem `reading-flow`, em que ordem o Tab percorre os itens?

- Na ordem do DOM, igual nos dois layouts **(correta)**
  A ordem de tabulação segue o DOM. Mudar a posição visual com grid não muda a navegação por teclado.
- Na ordem visual de cada layout
  É o que o `reading-flow` passa a permitir. Sem ele, a ordem visual não interfere no foco.
- Na ordem visual só onde houver `grid-template-areas`
  Nenhuma forma de posicionar itens na grid muda a ordem de foco. Ela vem sempre do DOM.

Na ordem do DOM. A tabulação ignora o layout, então um dos dois layouts sempre terá uma ordem de foco que não bate com o que se vê. O `reading-flow: grid-rows` faz o foco seguir a ordem visual da grid.

**Pergunta 4.** Um card deve fazer uma animação de 600ms quando chega ao meio da tela, na mesma velocidade, rolando devagar ou rápido. Que tipo de animação é essa?

- Scroll-driven, com `animation-timeline: view()`
  Numa scroll-driven animation, o progresso acompanha a rolagem: rolar devagar deixa a animação devagar, e voltar a rolagem volta a animação.
- Scroll-triggered, disparada num ponto da rolagem **(correta)**
  A rolagem só dispara a animação, como um sensor de presença. Depois, ela roda pela duração definida.
- Uma transição comum, sem nenhum recurso de rolagem
  Uma transição precisa de uma mudança de estado. Sem algo que detecte a posição do card, ela nunca começa.

É uma scroll-triggered animation. Ela é disparada quando o usuário chega a um ponto da rolagem e roda pela duração normal. Hoje isso se faz com `IntersectionObserver`; a proposta traz o recurso para o CSS.

---

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
