Bem-vindo(a) ao @Container Queries CSS
Tags: braziliandevs, css, frontend, design
Published: 2021-08-26 16:57:21

> Image cover by https://hermes.digitalinnovation.one

## O que é

Recentemente, o Google Chrome adicionou o recurso CSS *@container query*. A novidade é semelhante as *@media queries*, que são usadas para auxiliar a construção de sites responsivos.

O recurso foi proposto por [Miriam Suzanne](https://github.com/mirisuzanne), contribuidora do projeto SASS e especialista convidada no projeto W3C, com base em uma proposta do [David Baron](https://github.com/dbaron).

------

## Para que serve

A novidade permitirá que os desenvolvedores apliquem estilizações em um elemento de acordo com o tamanho do elemento pai e não apenas do *viewport* como ocorre com *@media query*.

A vantagem da novidade é escrever elementos modulares com base em suas dimensões sem a necessidade de JavaScript. Junto com o recurso, o CSS receberá duas novas propriedades.

**Novas propriedades CSS**

<dl>
  <dt><b>container-name</b></dt>
  <dd>É ser usada para identificar o <i>container</i>. Assim, será possível isolar as regras de cada elemento.</dd>

  <dt><b>container-type</b></dt>
  <dd>É usada para definir o tipo de <i>container</i>. Atualmente, há três valores possíveis.</dd>
</dl>

**Valores da propriedade `container-type`**

<dl>
  <dt><b>block-size</b></dt>
  <dd>Estabelece um <i>container</i> para uma consulta dimensional no eixo vertical do próprio container (altura).</dd>

  <dt><b>inline-size</b></dt>
  <dd>Estabelece um <i>container</i> para uma consulta dimensional no eixo horizontal do próprio container (largura).</dd>

  <dt><b>size</b></dt>
  <dd>Estabelece um <i>container</i> para uma consulta dimensional nos eixos vertical e horizontal do próprio container.</dd>
</dl>

> **Atenção!** A depender do valor da propriedade `writing-mode`, a opção `inline-size` poderá utilizar o eixo vertical; e a opção `block-size`, o eixo horizontal para consulta dimensional.

------

## Como usar

> Alguns trechos de CSS, JavaScript e HTML foram suprimidos, pois o foco é apenas na novidade.

Para adicionar suporte aos *containers*, é preciso criar um elemento pai que deverá receber a propriedade `container-type`.

```css
.music {
  container-name: musics;
  container-type: inline-size;
  flex: 1 1 calc(50% - 1rem);
}
```

A propriedade `container-name` é importante para tornar o elemento o mais modular possível. Com ele, é possível informar regras específicas para cada elemento, no entanto, o uso da propriedade é opcional.

Após declarar um *@container*, crie as regras para definir as customizações dele. Criá-las é simples, a sintaxe é semelhante à das *media rules* e aceita múltiplas condições e regras.

```css
@container [<container-name>] [(<feature-name>: <feature-value>)] [and (<feature-name>: <feature-value>)] {
  /* Code Here */
}
```

Segue exemplo:

```css
/**
 * Se a largura máxima do container 
 * (div.music) for menor que 570px...
 */
@container musics (max-width: 570px) {
  .card {
    contain: content;
    grid-template-areas: "media media"
      "heading heading"
      "content content"
      "footer footer";
    height: auto;
    padding: 0 0 1rem 0;
  }

  .card .card-media,
  .card .card-media > img {
    width: 100%;
  }

  .card .card-heading,
  .card .card-content,
  .card .card-footer {
    padding: 0 1rem;
  }

  .card .card-content {
    height: 0px;
    opacity: 0;
    transition: all 1s;
  }

  .card .card-content.active {
    height: 80px;
    opacity: 1;
  }
}
```

No HTML, foi adicionada a seguinte estrutura:

```html
<!--
- Elemento PAI, que deverá
- receber a propriedade `container-type`
-->
<div class="music">

  <!--
  - Estrutura do card da música
  -->
  <div class="card" id="carta_1">
    <div class="wave"></div>
    
    <!--
    - Capa do álbum
    -->
    <div class="card-media">
      <img src="https://source.unsplash.com/random/185x185" />
    </div>

    <!--
    - Nome da música do artista
    -->
    <div class="card-heading">
      <h1>Carta Nº 1</h1>
      <h2>SID Mc</h2>
    </div>

    <!--
    - Letra da música
    -->
    <div class="card-content">
      Eu vi escorrer na pia a alegria avermelhada ♫<br>
      Eu vi escorrer na pia a agonia acumulada ♪
    </div>

    <div class="card-footer">
      <button type="button">ORDER NOW</button>
    </div>
  </div>
</div>
```

------

## Demonstração

{% glitch poised-reflective-fabrosaurus app %}

## Demonstração em vídeo

{% youtube _WB6ZRiuhhk %}

------

## Comparação com *@media query*

A consulta de dispositivo (ou *media query*) surgiu para facilitar a criação de sites responsivos. Com ele, é possível configurar diversas regras de estilização de acordo com o tamanho do *viewport* (área visível da tela). É legal e funciona corretamente.

No entanto, ainda há limitações. As estilizações com *@media query* são aplicadas somente quando o usuário altera o tamanho da janela (maximizando, redimensionando ou alterando a orientação), por exemplo.

![Media Query](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/unmnp286htccakjofw08.png)

O sistema de *@container* foi proposto para remover essa limitação. Ele permite que as estilizações sejam feitas de acordo com o tamanho do elemento pai independente das dimensões da *viewport*.

![Container Query](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/usmp31easx4sl2yrvown.png)

------

## Compatibilidade

Até o momento (24 ago 2021), o recurso está disponível apenas para o Chrome 92 ou superior.

Para habilitar e testá-lo, basta acessar a página `chrome://flags`, pesquisar por *Container Queries*, habilitar o recurso e reiniciar o navegador.

![Habilitando Container Query](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lmpunww1amb9cq0zumfb.png)

## Polyfill

Como alternativa, pode utilizar a API `ResizeObserver` ou o projeto [cqfill](https://github.com/jsxtools/cqfill/) com o PostCSS.
 
**Demonstração com CQFill**

{% codepen https://codepen.io/jonneal/pen/WNRPBQg default-tab=result %}

## Conclusão

É isso! Conforme o Google for liberando novidades, irei postar e atualizar aqui. Qualquer dúvida, só falar.