A capacidade de consultar o tamanho in-line de um elemento pai e os valores da unidade de consulta do contêiner alcançaram recentemente suporte estável em todos os mecanismos de navegador modernos.
No entanto, a especificação de contenção inclui mais do que apenas consultas de tamanho. também permite consultar os valores de estilo de um elemento pai. No Chromium 111, você poderá aplicar contenção de estilo a valores de propriedades personalizadas e consultar um elemento pai para o valor de uma propriedade personalizada.
Isso significa que temos um controle ainda mais lógico de estilos no CSS e permite uma melhor separação entre a lógica e a camada de dados de um aplicativo e seus estilos.
A especificação de nível 3 do módulo de contenção de CSS, que abrange consultas de tamanho e estilo, permite que todos os estilos sejam consultados de um pai, incluindo pares de propriedade e valor, como font-weight: 800
. No entanto, ao lançar esse recurso, as consultas de estilo funcionam apenas com valores de propriedade personalizada de CSS. Isso ainda é muito útil para combinar estilos e separar dados do design. Vamos dar uma olhada em como você usa consultas de estilo com propriedades personalizadas de CSS:
Primeiros passos com consultas de estilo
Digamos que temos o seguinte HTML:
<ul class="card-list">
<li class="card-container">
<div class="card">
...
</div>
</li>
</ul>
Para usar consultas de estilo, primeiro você precisa configurar um elemento de contêiner. Isso exige uma abordagem um pouco diferente, dependendo se você está consultando um pai direto ou indireto.
Como consultar pais diretos
Ao contrário das consultas de estilo, não é necessário aplicar contenção usando a propriedade container-type
ou container
em .card-container
para que .card
possa consultar os estilos do pai direto. No entanto, precisamos aplicar os estilos (nesse caso, valores de propriedades personalizadas) a um contêiner (neste caso, .card-container
) ou a qualquer elemento que contenha o elemento que estamos estilizando no DOM. Não é possível aplicar os estilos que estamos consultando no elemento direto para o qual estamos estilizando usando essa consulta, porque isso pode causar loops infinitos.
Para consultar diretamente um pai, escreva:
/* styling .card based on the value of --theme on .card-container */
@container style(--theme: warm) {
.card {
background-color: wheat;
border-color: brown;
...
}
}
Você deve ter notado que a consulta de estilo envolve a consulta com style()
. Isso serve para diferenciar os valores de tamanho dos estilos. Por exemplo, é possível escrever uma consulta para a largura do contêiner como @container (min-width: 200px) { … }
. Isso aplicaria estilos se o contêiner pai tiver pelo menos 200 px de largura. No entanto, min-width
também pode ser uma propriedade CSS, e é possível consultar o valor CSS de min-width
usando consultas de estilo. É por isso que você usaria o wrapper style()
para esclarecer a diferença: @container style(min-width: 200px) { … }
.
Aplicar estilo a famílias não diretas
Se você quiser consultar estilos de qualquer elemento que não seja pai direto, vai precisar atribuir um container-name
a esse elemento. Por exemplo, podemos aplicar estilos a .card
com base nos estilos de .card-list
, fornecendo a .card-list
um container-name
e referenciando-o na consulta de estilo.
/* styling .card based on the value of --moreGlobalVar on .card-list */
@container cards style(--moreGlobalVar: value) {
.card {
...
}
}
Geralmente, é uma prática recomendada dar nomes aos contêineres para deixar claro o que você está consultando e liberar a capacidade de acessá-los com mais facilidade. Isso é útil, por exemplo, quando você quer definir o estilo dos elementos diretamente na .card
. Sem um contêiner nomeado em .card-container
, não é possível consultá-lo diretamente.
Mas tudo isso faz muito mais sentido na prática. Vamos analisar alguns exemplos:
Defina o estilo de consultas em ação
As consultas de estilo são especialmente úteis quando você tem um componente reutilizável com diversas variações ou quando não tem controle sobre todos os estilos, mas precisa aplicar mudanças em alguns casos. Este exemplo mostra um conjunto de cards de produtos que compartilham o mesmo componente de card. Alguns cards de produtos têm detalhes/observações adicionais, como "Novo" ou "Pouco estoque", acionados por uma propriedade personalizada chamada --detail
. Além disso, se um produto estiver em "Estoque baixo", ele receberá um plano de fundo de borda vermelho profundo. Esse tipo de informação provavelmente é renderizado pelo servidor e pode ser aplicado aos cards por estilos inline, como neste exemplo:
<div class="product-list">
<div class="product-card-container" style="--detail: new">
<div class="product-card">
<div class="media">
<img .../>
<div class="comment-block"></div>
</div>
</div>
<div class="meta">
...
</div>
</div>
<div class="product-card-container" style="--detail: low-stock">
...
</div>
<div class="product-card-container">
...
</div>
...
</div>
Com esses dados estruturados, você pode transmitir valores para --detail
e usar esta propriedade personalizada do CSS para aplicar os estilos:
@container style(--detail: new) {
.comment-block {
display: block;
}
.comment-block::after {
content: 'New';
border: 1px solid currentColor;
background: white;
...
}
}
@container style(--detail: low-stock) {
.comment-block {
display: block;
}
.comment-block::after {
content: 'Low Stock';
border: 1px solid currentColor;
background: white;
...
}
.media-img {
border: 2px solid brickred;
}
}
O código acima permite aplicar um ícone para --detail: low-stock
e --detail: new
, mas você pode ter notado alguma redundância no bloco de código. No momento, não há como consultar apenas a presença de --detail
com @container style(--detail)
, o que permitiria um melhor compartilhamento de estilos e menos repetição. Esse recurso está em discussão no grupo de trabalho.
Cards do clima
O exemplo anterior usou uma única propriedade personalizada com vários valores possíveis para aplicar estilos. Mas você também pode misturá-lo usando e consultando várias propriedades personalizadas. Veja este exemplo de card meteorológico:
Para estilizar os gradientes e ícones do plano de fundo desses cards, procure características climáticas, como "nublado", "chuvoso" ou "ensolarado":
@container style(--sunny: true) {
.weather-card {
background: linear-gradient(-30deg, yellow, orange);
}
.weather-card:after {
content: url(<data-uri-for-demo-brevity>);
background: gold;
}
}
Dessa forma, é possível estilizar cada card com base nas características únicas deles. No entanto, também é possível definir o estilo para combinações de característica (propriedade personalizada) usando o combinador and
da mesma forma que para consultas de mídia. Por exemplo, um dia nublado e ensolarado tem esta aparência:
@container style(--sunny: true) and style(--cloudy: true) {
.weather-card {
background: linear-gradient(24deg, pink, violet);
}
.weather-card:after {
content: url(<data-uri-for-demo-brevity>);
background: violet;
}
}
Separação de dados do design
Em ambas as demonstrações, há um benefício estrutural de separar a camada de dados (DOM que seria renderizado na página) dos estilos aplicados. Os estilos são escritos como possíveis variantes que residem no estilo do componente, enquanto um endpoint poderia enviar os dados que seria usado para definir o estilo do componente. É possível usar um único valor, como no primeiro caso, atualizando o valor --detail
, ou várias variáveis, como no segundo caso, definindo --rainy
, --cloudy
ou --sunny
. O melhor de tudo é que também é possível combinar esses valores. Verificar --sunny
e --cloudy
pode mostrar um estilo parcialmente nublado.
A atualização de valores de propriedades personalizadas por JavaScript pode ser feita facilmente, seja durante a configuração do modelo DOM (ou seja, durante a criação do componente em um framework) ou atualizada a qualquer momento usando <parentElem>.style.setProperty('--myProperty’, <value>)
. I
Confira uma demonstração que, em algumas linhas de código, atualiza o --theme
de um botão e aplica estilos usando consultas de estilo e essa propriedade personalizada (--theme
):
Defina o estilo do cartão usando consultas de estilo. O JavaScript usado para atualizar os valores da propriedade personalizada é:
const themePicker = document.querySelector('#theme-picker')
const btnParent = document.querySelector('.btn-section');
themePicker.addEventListener('input', (e) => {
btnParent.style.setProperty('--theme', e.target.value);
})
Os recursos detalhados neste artigo são apenas o começo. As consultas de contêiner vão ajudar você a criar interfaces dinâmicas e responsivas. Quanto às consultas de estilo especificamente, ainda há alguns problemas em aberto. Uma delas é a implementação de consultas de estilo para estilos CSS além das propriedades personalizadas. Isso já faz parte do nível de especificação atual, mas ainda não foi implementado em nenhum navegador. A avaliação do contexto booleano será adicionada ao nível atual da especificação quando o problema pendente for resolvido, enquanto a consulta de intervalo está planejada para o próximo nível da especificação.