Liberando o poder das consultas de contêiner do CSS: lições da equipe da Netflix

Jeremy Weeks
Jeremy Weeks
Stefan Heymanns
Stefan Heymanns

As consultas de contêiner revolucionaram a forma como os desenvolvedores abordam o design responsivo, e a equipe da Netflix já vivenciou em primeira mão o impacto profundo que elas podem ter na simplificação do desenvolvimento, melhorando a flexibilidade e a performance. Esta postagem detalha os principais benefícios do uso de consultas de contêiner, comparando-as com métodos mais antigos, principalmente aqueles que dependem do JavaScript para controle de layout. Ele inclui exemplos de código para ilustrar cada ponto, mostrando como as consultas de contêiner podem facilitar muito a vida de desenvolvedores.

1. Design de componentes simplificado, "de baixo para cima" em vez de "de cima para baixo"

Uma das mudanças mais significativas que a equipe da Netflix passou foi a transição de uma abordagem de design "de cima para baixo" para uma "de baixo para cima". Antes das consultas de contêineres, os contêineres pais precisavam estar totalmente cientes dos requisitos de layout dos filhos. Com as consultas de contêiner, essa lógica é invertida, permitindo que os componentes filhos controlem o layout com base no tamanho do próprio contêiner. Isso simplifica o papel do elemento pai e reduz a quantidade de lógica de layout no código.

Exemplo: consultas de contêiner x consultas de mídia e JavaScript

Antes (é necessário usar JavaScript):

/* Layout with media queries */
.card {
    width: 100%;
}

@media (min-width: 600px) {
    .card {
        width: 50%;
    }
}

@media (min-width: 900px) {
    .card {
        width: 33.33%;
    }
}
// JavaScript to detect parent container size
const container = document.querySelector('.container');
const card = document.querySelector('.card');

function adjustLayout() {
    if (window.innerWidth >= 900) {
        card.style.width = '33.33%';
    } else if (window.innerWidth >= 600) {
        card.style.width = '50%';
    } else {
        card.style.width = '100%';
    }
}

window.addEventListener('resize', adjustLayout);
adjustLayout();

Depois:

/* Container Query */
.container {
    container-type: inline-size;
}

.card {
    width: 100%;
}

@container (min-width: 600px) {
    .card {
        width: 50%;
    }
}

@container (min-width: 900px) {
    .card {
        width: 33.33%;
    }
}

Este exemplo mostra como o contêiner pai não precisa mais gerenciar o layout filho. A regra @container permite que o .card reaja ao tamanho do contêiner imediato, simplificando a lógica de layout e eliminando a necessidade de JavaScript por completo.

2. Responsividade sem consultas de mídia complexas

A equipe da Netflix descobriu como as consultas de contêiner simplificam a responsividade, principalmente para o design mobile-first. Em vez de escrever consultas de mídia complexas, você pode criar componentes reutilizáveis que se ajustam com base no tamanho do contêiner, permitindo layouts dinâmicos em vários tamanhos de tela e dispositivos. Isso é particularmente útil para apps como a Netflix, em que o tráfego de dispositivos móveis é dominante.

Exemplo: responsividade do componente com consultas de contêiner

Antes:

/* Desktop versus Mobile
this only works if.sidebar is directly contained by a viewport-width element */
.sidebar {
    width: 300px;
}

@media (max-width: 768px) {
    .sidebar {
        width: 100%;
    }
}

Depois:

/* Responsive sidebar based on container,
.sidebar can be placed in any element of any width */
.container {
    container-type: inline-size;
}

.sidebar {
    width: 100%;
}

@container (min-width: 768px) {
    .sidebar {
        width: 300px;
    }
}

Em vez de depender de consultas de mídia baseadas na viewport, o .sidebar agora responde ao tamanho do contêiner, permitindo que ele se adapte de forma mais natural a layouts dinâmicos sem precisar saber o tamanho da viewport ou do contêiner pai.

3. Redução da dependência do JavaScript para gerenciamento de layout

Antes das consultas de contêiner, muitas equipes, incluindo a Netflix, precisavam usar JavaScript para layouts dinâmicos. Ao consultar o tamanho da janela, o JavaScript acionava mudanças de layout, aumentando a complexidade e o potencial de bugs. As consultas de contêiner eliminam essa necessidade, permitindo que o CSS gerencie a responsividade do layout com base no tamanho do contêiner.

Exemplo: como remover a lógica de layout baseada em JavaScript

Antes:

const cardContainer = document.querySelector('.card-container');
const cards = cardContainer.children;

function adjustLayout() {
    if (cardContainer.offsetWidth > 900) {
        cards.forEach(card => card.style.width = '33.33%');
    } else if (cardContainer.offsetWidth > 600) {
        cards.forEach(card => card.style.width = '50%');
    } else {
        cards.forEach(card => card.style.width = '100%');
    }
}

window.addEventListener('resize', adjustLayout);
adjustLayout();

Depois:

.card-container {
    container-type: inline-size;
}

.card {
    width: 100%;
}

@container (min-width: 600px) {
    .card {
        width: 50%;
    }
}

@container (min-width: 900px) {
    .card {
        width: 33.33%;
    }
}

Essa abordagem não apenas reduz a quantidade de JavaScript necessária, mas também melhora o desempenho evitando cálculos de execução.

4. Menos código, menos bugs

A equipe da Netflix descobriu que o uso de consultas de contêiner levou a menos linhas de código e menos bugs relacionados ao layout. Ao mover a lógica de layout do JavaScript para o CSS e eliminar a necessidade de consultas de mídia complexas, os desenvolvedores podem escrever um código mais manutenção.

Exemplo: reduzir o código de layout

A equipe da Netflix observou que, depois de adotar as consultas de contêiner, eles notaram uma redução significativa no código CSS, de até 30% para determinados componentes. Ao mesmo tempo, a equipe conseguiu simplificar muitas consultas de mídia complexas e, às vezes, propensas a conflitos ao remover a lógica que controlava os componentes filhos, alcançando um maior grau de separação de preocupações. Essa redução não apenas acelera o desenvolvimento, mas também minimiza possíveis pontos de falha, resultando em menos bugs.

Antes:

/* Before with complex media queries */
.card {
    width: 100%;
}

@media (min-width: 600px) {
    .card {
        width: 50%;
    }
}

@media (min-width: 900px) {
    .card {
        width: 33.33%;
    }
}

Depois

.container {
    container-type: inline-size;
}

.card {
    width: 100%;
}

@container (min-width: 600px) {
    .card {
        width: 50%;
    }
}

@container (min-width: 900px) {
    .card {
        width: 33.33%;
    }
}

5. Experiência de desenvolvimento melhorada

bq. "Isso facilitou muito minha vida"

Talvez um dos benefícios mais subestimados das consultas de contêiner seja a experiência aprimorada para desenvolvedores. Ao fazer com que o CSS se comporte de uma maneira mais intuitiva e focada em componentes, os desenvolvedores podem se concentrar na criação de componentes flexíveis e reutilizáveis sem se preocupar com a forma como eles vão se comportar em todos os cenários de layout possíveis.

Como disse um dos membros da equipe da Netflix, "É assim que o CSS deveria funcionar desde o início".

6. Fallback de polyfill

Embora as consultas de contêiner estejam disponíveis em todos os principais navegadores, há preocupação com versões anteriores de navegadores que ainda estão em uso. Uma alternativa é muito importante. A equipe da Netflix usa esse polyfill JavaScript criado por colaboradores da comunidade da Web. A implementação é simples com a detecção de recursos:

if (! CSS.supports("container-type:size")) {
  /*use polyfill from
  https://www.npmjs.com/package/container-query-polyfill */
 }

Conclusão

As consultas de contêiner representam um grande avanço no CSS, facilitando a criação de componentes flexíveis e responsivos que podem ser reutilizados em diferentes partes de um site. Ao reduzir a dependência do JavaScript para layout, eliminar consultas de mídia complexas e acelerar o desenvolvimento, eles oferecem vantagens significativas em desempenho e manutenção. Atualmente, a maioria dos casos de uso está nas páginas Tudum da Netflix, com planos potenciais de usar consultas de contêiner em outras partes da Netflix. A equipe da Netflix considera as consultas de contêiner uma ferramenta de primeira classe na caixa de ferramentas do desenvolvedor, e o uso delas vai aumentar à medida que mais desenvolvedores adotarem a flexibilidade e o poder que elas oferecem. Seja para adaptar componentes existentes ou projetar outros completamente novos, as consultas de contêiner oferecem um caminho mais simples e limpo para o design responsivo.

Se você ainda não fez isso, experimente as consultas de contêiner. Elas provavelmente simplificam seu fluxo de trabalho de maneiras inesperadas.