🔮 AULA 9

CSS Moderno

⏱️ Duração: 55 minutos 🎯 Nível: Avançado 👨‍💻 Prática: Sim

Seu progresso nesta aula
0%
⬅️ Aula anterior: Animações CSS Próxima aula: Pré-processadores CSS ➡️

🎯 Objetivos de Aprendizado

Ao final desta aula, você será capaz de:

✨ A Evolução do CSS

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:

💡 Dica

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.

🎛️ Custom Properties (Variáveis CSS)

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);
}

Vantagens das Custom Properties

Demonstração: Temas com Custom Properties

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);
}

⚠️ Importante

Ao usar variáveis CSS, sempre forneça um valor de fallback para navegadores antigos:

color: var(--cor-texto, #333);

🧮 Funções CSS Modernas

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.

calc(): Cálculos Dinâmicos

A função calc() permite realizar cálculos misturando unidades diferentes.

width: calc(100% - 40px)
width: calc(50% - 20px)
width: calc(50% - 20px)
.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;
}

min(), max() e clamp(): Valores Responsivos

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);

💡 Caso de Uso

O clamp() é perfeito para tipografia responsiva e layouts fluidos, eliminando a necessidade de muitas media queries.

📏 Unidades Modernas

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

Exemplo: Unidade fr no Grid

1fr
1fr
1fr
/* 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 */
}

🔍 Seletores Modernos

Os seletores modernos do CSS simplificam significativamente a forma como visamos elementos, reduzindo a repetição e melhorando a legibilidade.

:is() e :where() - Agrupamento de Seletores

Este é um título h3

Este é um título h4

Este é um parágrafo normal.

  • Item de lista não ordenada
  • Outro item de lista
  1. Item de lista ordenada
  2. Outro item de lista ordenada
/* 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;
}

⚠️ Importante

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.

:has() - Seletor de "Pai"

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);
}

📐 Layout Avançado

Container Queries

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%;
    }
}

Aspect Ratio

A propriedade aspect-ratio permite manter uma proporção consistente em elementos, independentemente do seu tamanho.

16:9
/* 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

Subgrid permite que elementos filhos de um grid herdem a estrutura do grid pai, facilitando alinhamentos complexos.

Cabeçalho

Este é o conteúdo principal que pode ter diferentes tamanhos em diferentes cards.

Cabeçalho

Conteúdo com texto mais longo para demonstrar o alinhamento. Independentemente do tamanho do conteúdo, os botões ficarão alinhados.

Cabeçalho

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 */
}

⚠️ Nota de Compatibilidade

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.

🔎 Feature Queries (@supports)

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;
    }
}

💡 Melhor Prática

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.

✒️ Novos Pseudo-elementos e Pseudo-classes

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;
}

🛠️ Práticas Modernas de CSS

Além dos novos recursos, surgiram melhores práticas para escrever CSS eficiente e manutenível:

1. Progressive Enhancement (Aprimoramento Progressivo)

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;
    }
}

2. Escreva CSS Resiliente

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);
}

3. Evite Reset Completos de CSS

Prefira normalize.css ou pequenos resets específicos em vez de resets completos.

4. Encapsulamento com Escopo CSS

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);
}

✏️ Exercícios Práticos

Exercício 1: Sistema de Temas com Custom Properties

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.

Exercício 2: Layout Responsivo com Funções Modernas

Crie um layout de cards que:

  • Use clamp() para tamanhos de fonte responsivos sem media queries
  • Use calc() para espaçamentos proporcionais
  • Mantenha proporção fixa com aspect-ratio
  • Use min() ou max() para limites de largura

Dica: Tente combinar várias funções, como width: clamp(300px, calc(50% - 2rem), 600px);

Exercício 3: Simplificação com Seletores Modernos

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.

Desafio: Componente Adaptativo Avançado

Crie um componente de card que se adapte ao seu contêiner (não à viewport), utilizando recursos modernos:

  • Container Queries para layout adaptativo
  • Subgrid para alinhamento de elementos entre cards
  • @supports para fornecer fallbacks
  • Custom Properties para personalização

Dica: Lembre-se que Container Queries e Subgrid são recursos recentes. Use @supports para fornecer alternativas para navegadores sem suporte.

🔧 Ferramentas e Recursos

Verificação de Compatibilidade

  • Can I Use - Verificar suporte de recursos nos navegadores
  • BrowserStack - Teste em diferentes navegadores e dispositivos

Ferramentas Úteis

📝 Resumo

Pontos-chave desta aula

  • Custom Properties (variáveis CSS) permitem valores reutilizáveis e dinâmicos
  • Funções como calc(), min(), max() e clamp() possibilitam layouts responsivos sem media queries
  • Seletores avançados como :is(), :where() e :has() simplificam o código e permitem seleção mais precisa
  • Container Queries, Subgrid e Aspect Ratio oferecem controle de layout mais granular
  • Feature Queries (@supports) permitem uso seguro de recursos modernos com fallbacks
  • O CSS moderno facilita aprimoramento progressivo e código mais manutenível

🚀 Próximos Passos

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!

⬅️ Aula anterior: Animações CSS Próxima aula: Pré-processadores CSS ➡️