Ao final desta aula, você será capaz de:
O CSS evoluiu dramaticamente nos últimos anos, passando de uma linguagem de estilo simples para uma ferramenta poderosa e versátil. Os recursos modernos do CSS transformaram a forma como desenvolvemos interfaces, permitindo soluções mais elegantes, manutenção simplificada e funcionalidades anteriormente possíveis apenas com JavaScript.
Nesta aula, vamos explorar os recursos mais recentes do CSS que estão mudando a forma como escrevemos estilos:
O CSS moderno permite resolver problemas complexos de design com código limpo e simples, mas mantenha sempre em mente a compatibilidade com navegadores. Use recursos como @supports para fornecer fallbacks quando necessário.
As variáveis CSS, ou Custom Properties, permitem armazenar e reutilizar valores em todo o seu código. Diferentemente das variáveis de pré-processadores (como Sass), elas são nativas do navegador, parte do DOM e podem ser manipuladas com JavaScript.
/* Definindo variáveis CSS */
:root {
--cor-principal: #6d28d9;
--cor-secundaria: #7c3aed;
--espacamento-base: 1rem;
--borda-radius: 8px;
}
/* Usando variáveis CSS */
.botao {
background-color: var(--cor-principal);
padding: var(--espacamento-base);
border-radius: var(--borda-radius);
}
.destaque {
color: var(--cor-secundaria);
margin-bottom: calc(var(--espacamento-base) * 2);
}
Este é um painel com cores definidas por variáveis.
/* Definindo tema claro (padrão) */
:root {
--cor-principal: #6d28d9;
--cor-secundaria: #7c3aed;
--cor-texto: #333;
--cor-fundo: #f9fafb;
}
/* Tema escuro */
.tema-escuro {
--cor-principal: #9333ea;
--cor-secundaria: #a855f7;
--cor-texto: #f9fafb;
--cor-fundo: #111827;
}
/* Elementos usando variáveis */
.painel {
background-color: var(--cor-fundo);
color: var(--cor-texto);
}
.botao {
background-color: var(--cor-principal);
}
Ao usar variáveis CSS, sempre forneça um valor de fallback para navegadores antigos:
color: var(--cor-texto, #333);
O CSS moderno inclui poderosas funções matemáticas e lógicas que permitem criar layouts mais dinâmicos e responsivos sem depender de JavaScript.
A função calc()
permite realizar cálculos misturando unidades diferentes.
.container {
width: 80%;
max-width: 600px;
}
.item {
/* Calcula a largura total menos margens */
width: calc(100% - 40px);
}
.item-half {
/* Item com metade da largura menos margens */
width: calc(50% - 20px);
margin-right: 10px;
}
Estas funções permitem definir valores mínimos, máximos ou valores que se ajustam dentro de um intervalo.
Este texto usa font-size: clamp(1rem, 2vw + 0.5rem, 2rem)
para tamanho responsivo que nunca fica muito pequeno ou muito grande.
/* min(): escolhe o menor dos valores */
width: min(300px, 100%); /* Será 100% até 300px, depois será 300px */
/* max(): escolhe o maior dos valores */
width: max(50%, 500px); /* Será 500px até que 50% seja maior */
/* clamp(): mantém um valor entre mínimo e máximo */
font-size: clamp(1rem, 2vw + 0.5rem, 2rem);
width: clamp(300px, 80%, 1000px);
O clamp()
é perfeito para tipografia responsiva e layouts fluidos, eliminando a necessidade de muitas media queries.
Além das unidades tradicionais como px, em, rem e %, o CSS moderno introduz novas unidades que facilitam layouts responsivos.
Unidade | Descrição | Caso de Uso |
---|---|---|
fr |
Fração do espaço disponível (apenas em Grid) | Layouts de grade flexíveis |
ch |
Largura do caractere "0" da fonte atual | Largura de texto e colunas |
vw/vh |
1% da largura/altura da viewport | Elementos responsivos à viewport |
vmin/vmax |
1% do menor/maior valor entre largura e altura da viewport | Responsividade proporcional |
/* Grade com três colunas iguais */
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 1rem;
}
/* Layout com áreas de tamanhos diferentes */
.grid-avancado {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
/* A coluna do meio tem o dobro do tamanho */
}
Os seletores modernos do CSS simplificam significativamente a forma como visamos elementos, reduzindo a repetição e melhorando a legibilidade.
Este é um parágrafo normal.
/* Sem :is() - repetitivo */
header h1, header h2, header h3,
nav h1, nav h2, nav h3,
main h1, main h2, main h3 {
color: blue;
}
/* Com :is() - simplificado */
:is(header, nav, main) :is(h1, h2, h3) {
color: blue;
}
/* :where() funciona de maneira similar, mas com especificidade zero */
:where(ul, ol) li {
margin-bottom: 0.5rem;
}
A principal diferença entre :is()
e :where()
está na especificidade. O :is()
assume a especificidade do seu argumento mais específico, enquanto :where()
tem especificidade zero.
O seletor :has()
permite selecionar elementos com base em seus filhos ou conteúdo - algo que era impossível antes no CSS.
/* Seleciona parágrafos que contêm imagens */
p:has(img) {
display: flex;
align-items: center;
}
/* Estiliza cards diferentes se tiverem botões ou não */
.card:has(.btn) {
padding-bottom: 3rem;
}
/* Estiliza listas apenas se tiverem mais de 3 itens */
ul:has(li:nth-child(3)):has(li:nth-child(4)) {
display: grid;
grid-template-columns: repeat(2, 1fr);
}
Enquanto Media Queries são baseadas na viewport (janela do navegador), Container Queries permitem aplicar estilos com base no tamanho do elemento pai, possibilitando componentes realmente reutilizáveis.
/* Primeiro definimos o container */
.card-container {
container-type: inline-size;
container-name: card;
}
/* Então aplicamos estilos baseados no tamanho do container */
@container card (min-width: 400px) {
.card {
display: flex;
}
.card-image {
width: 40%;
}
.card-content {
width: 60%;
}
}
A propriedade aspect-ratio
permite manter uma proporção consistente em elementos, independentemente do seu tamanho.
/* Um elemento sempre com proporção 16:9 */
.video-container {
width: 100%;
aspect-ratio: 16/9;
background-color: #000;
}
/* Proporção 1:1 para imagens de perfil */
.avatar {
width: 100%;
max-width: 200px;
aspect-ratio: 1/1;
object-fit: cover;
border-radius: 50%;
}
Subgrid permite que elementos filhos de um grid herdem a estrutura do grid pai, facilitando alinhamentos complexos.
Este é o conteúdo principal que pode ter diferentes tamanhos em diferentes cards.
Conteúdo com texto mais longo para demonstrar o alinhamento. Independentemente do tamanho do conteúdo, os botões ficarão alinhados.
Texto curto.
/* Grid pai */
.grid-parent {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 1rem;
}
/* Grid filho usando subgrid */
.grid-child {
display: grid;
grid-template-rows: subgrid;
grid-row: span 3; /* Ocupa 3 linhas do grid pai */
}
Subgrid e Container Queries são recursos muito recentes e podem não ter suporte em todos os navegadores. Sempre verifique a compatibilidade e forneça fallbacks quando necessário.
As Feature Queries permitem aplicar estilos com base na compatibilidade do navegador, possibilitando aprimoramentos progressivos e fallbacks elegantes.
Este elemento usa backdrop-filter quando suportado, ou um fundo opaco quando não suportado.
/* Verificando suporte para backdrop-filter */
@supports (backdrop-filter: blur(10px)) {
.modal {
background-color: rgba(255, 255, 255, 0.7);
backdrop-filter: blur(10px);
}
}
/* Alternativa para navegadores sem suporte */
@supports not (backdrop-filter: blur(10px)) {
.modal {
background-color: rgba(255, 255, 255, 0.95);
}
}
/* Verificação de múltiplos recursos com operadores lógicos */
@supports (display: grid) and (gap: 1rem) {
.container {
display: grid;
gap: 1rem;
}
}
Use @supports para aprimoramento progressivo: primeiro forneça uma solução básica que funcione em todos os lugares, depois aprimore para navegadores modernos com @supports.
O CSS moderno introduziu diversos novos pseudo-seletores que permitem acesso a elementos específicos ou estados que antes eram impossíveis de selecionar.
Seletor | Descrição | Exemplo de Uso |
---|---|---|
::marker |
Seleciona o marcador de um item de lista | Personalizar o estilo de marcadores de listas |
:focus-visible |
Aplica estilos apenas quando o foco é relevante para o usuário | Melhorar a acessibilidade sem comprometer a estética |
:focus-within |
Seleciona um elemento quando ele ou qualquer descendente tem foco | Destacar formulários ou grupos quando um campo está ativo |
:empty |
Seleciona elementos sem filhos | Esconder contêineres vazios ou mostrar mensagem alternativa |
/* Personalizar marcadores de lista */
li::marker {
color: var(--cor-principal);
font-weight: bold;
}
/* Estilizar quando o campo ou qualquer elemento dentro dele tem foco */
.form-group:focus-within {
background-color: #f0f0f0;
}
/* Usar :focus-visible apenas para acessibilidade por teclado */
button:focus {
/* Estilo mínimo para todos os focos */
outline: none;
}
button:focus-visible {
/* Contorno mais visível apenas para navegação por teclado */
outline: 2px solid var(--cor-principal);
outline-offset: 2px;
}
Além dos novos recursos, surgiram melhores práticas para escrever CSS eficiente e manutenível:
Comece com uma base funcional para todos os navegadores e adicione camadas de aprimoramento para navegadores modernos.
/* Base para todos os navegadores */
.grid {
display: block;
}
/* Aprimoramento para navegadores com suporte a grid */
@supports (display: grid) {
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 1rem;
}
}
Use valores de fallback e CSS com "autolimpeza" que funciona mesmo quando algumas partes não são suportadas.
/* Fornecendo um fallback antes do valor moderno */
.elemento {
/* Fallback para navegadores antigos */
width: 90%;
/* Versão moderna que será usada quando suportada */
width: clamp(300px, 90%, 1200px);
/* Fallback para cor */
background-color: #6d28d9;
/* Variável com fallback */
background-color: var(--cor-principal, #6d28d9);
}
Prefira normalize.css ou pequenos resets específicos em vez de resets completos.
Use custom properties, nomes de classe com prefixo ou soluções como CSS Modules para isolar estilos.
/* Organização com namespaces */
.componente-card__header { }
.componente-card__body { }
.componente-card__footer { }
/* Escopo com variáveis específicas do componente */
.componente {
--componente-espacamento: 1rem;
--componente-cor: blue;
padding: var(--componente-espacamento);
color: var(--componente-cor);
}
Crie um sistema de temas claro/escuro utilizando Custom Properties e JavaScript para alternar entre eles. Defina variáveis para cores, fontes e espaçamentos.
Dica: Defina suas variáveis no :root e crie uma classe .tema-escuro que substitui essas variáveis.
Crie um layout de cards que:
Dica: Tente combinar várias funções, como width: clamp(300px, calc(50% - 2rem), 600px);
Refatore o seguinte CSS usando seletores modernos como :is(), :where() e :has() para reduzir a repetição:
header h1, header h2, header h3 { font-family: 'Georgia', serif; }
main h1, main h2, main h3 { font-family: 'Georgia', serif; }
footer h1, footer h2, footer h3 { font-family: 'Georgia', serif; }
.card button:hover, .card a:hover, .card .link:hover { color: blue; }
article img + p, article video + p, article figure + p { font-style: italic; }
Dica: Use :is() para agrupar tanto seletores de elementos quanto contextos semelhantes.
Crie um componente de card que se adapte ao seu contêiner (não à viewport), utilizando recursos modernos:
Dica: Lembre-se que Container Queries e Subgrid são recursos recentes. Use @supports para fornecer alternativas para navegadores sem suporte.
Agora que você conhece os recursos modernos do CSS, continue explorando:
Na próxima aula, exploraremos pré-processadores CSS, que complementam os recursos nativos do CSS moderno com funcionalidades adicionais!