Calcular com tamanhos intrínsecos

Recursos da Web: calc-size() interpolate-size

calc-size() é uma função CSS para realizar operações matemáticas em palavras-chave de dimensionamento intrínseco, como auto, min-content e fit-content. OBRIGATÓRIO: use calc-size() somente quando precisar modificar um tamanho intrínseco com um cálculo ou uma restrição. Para animações simples baseadas em palavras-chave (por exemplo, de 0 para auto), use interpolate-size: allow-keywords.

Etapas de implementação

  1. Identificar a base intrínseca: determine qual palavra-chave intrínseca (auto, min-content etc.) deve formar a base do seu cálculo.
  2. Defina restrições: use funções matemáticas de CSS, como clamp(), min() ou max(), no segundo argumento para aplicar restrições de design ao tamanho intrínseco.
  3. OBRIGATÓRIO: forneça um substituto: sempre declare uma palavra-chave ou um comprimento de dimensionamento padrão imediatamente antes da propriedade usando calc-size() para garantir que o layout permaneça funcional em navegadores não compatíveis.
  4. Aplicar propriedades lógicas: use propriedades lógicas como inline-size ou block-size para garantir que os cálculos respeitem o modo de escrita do documento.
  5. Opcional: aprimoramento progressivo: envolva a lógica de layout ou as animações complexas em um bloco @supports (inline-size: calc-size(auto, size + 0px)) para oferecer recursos avançados apenas a navegadores compatíveis.

Sintaxe básica

/* calc-size(<calc-size-basis>, <calc-sum>) — mathematical operations on intrinsic sizing keywords */
.element {
  /* MANDATORY: Always provide a fallback for browsers that do not support calc-size() */
  inline-size: min-content;
  
  /* DO: Use calc-size to modify an intrinsic basis with a calculation or function */
  inline-size: calc-size(min-content, size + 2rem);
}

Argumentos de base válidos (<calc-size-basis>)

O primeiro argumento define o tamanho "base" para o cálculo.

Palavras-chave padrão:

  • auto: o dimensionamento padrão do elemento.
  • min-content: o menor tamanho que o elemento pode ter sem transbordar.
  • max-content: o tamanho que o elemento leva para ajustar todo o conteúdo em uma linha.
  • fit-content: equivalente a clamp(min-content, auto, max-content).
  • content: só é válido quando calc-size() é usado na propriedade flex-basis.

Argumentos especiais:

  • any: uma base genérica usada quando o tipo intrínseco específico é desconhecido ou ao aninhar cálculos.
  • calc-size() aninhada: permite cálculos condicionais ou em várias etapas.
  • <calc-sum>: um comprimento, uma porcentagem ou uma expressão matemática específica (por exemplo, 100px ou 20%). Quando um valor fixo é usado como base, a palavra-chave size ainda fica disponível (mas apenas no segundo argumento) e representa o valor resolvido dessa base.

OBRIGATÓRIO: a palavra-chave size não é válida no primeiro argumento (<calc-size-basis>). É uma variável local que existe apenas para se referir à base no segundo argumento (<calc-sum>).

Argumentos de cálculo válidos (<calc-sum>)

O segundo argumento é a expressão matemática.

  • Normalmente, ele usa a palavra-chave size para se referir ao valor da base.
  • Embora a palavra-chave size seja tecnicamente opcional, omiti-la significa que o cálculo será resolvido para um valor fixo, ignorando totalmente a base.
  • Ela pode incluir operadores matemáticos padrão (+, -, *, /).
  • Pode incluir funções matemáticas de CSS, como clamp(), min(), max() e round().
  • OBRIGATÓRIO: o calc-size() só permite um único valor de tamanho intrínseco (a base) em cada cálculo. Não é possível misturar palavras-chave de dimensionamento intrínseco na mesma chamada calc-size().

Casos de uso

Como animar para e de tamanhos intrínsecos

Por padrão, os navegadores não podem interpolar entre um comprimento (por exemplo, 0px) e uma palavra-chave intrínseca (por exemplo, auto). Envolver a palavra-chave em calc-size() a torna um valor interpolável.

Como escolher a ferramenta certa para animações

  • OBRIGATÓRIO: use interpolate-size: allow-keywords: para animações simples de ou para tamanhos intrínsecos (por exemplo, height: 0 para height: auto) sem modificações matemáticas. Essa é a abordagem necessária para a interpolação simples de palavras-chave e, idealmente, deve ser aplicada globalmente usando :root.

    :root {
      /* Best practice: Enable keyword interpolation globally */
      interpolate-size: allow-keywords;
    }
    
    .item {
      height: 0;
      transition: height 0.3s ease;
    }
    
    .item.open {
      /* Simple interpolation from 0 to auto now works without calc-size() */
      height: auto;
    }
    
  • Use calc-size(): SOMENTE quando você precisar realizar cálculos matemáticos em um tamanho intrínseco durante uma transição (por exemplo, adicionar padding ou fixar o tamanho).

.accordion-content {
  display: block;
  overflow: hidden;
  /* MANDATORY: Fallback value for closed state */
  block-size: 0;
  transition: block-size 0.3s ease-out;
}

.accordion-content.open {
  /* MANDATORY: Fallback value for open state */
  block-size: auto;

  /* 
    DO: Use calc-size(auto, ...) to enable animation from 0 to the element's 
    intrinsic size while doing a calculation (in this case, adding a space of 2rem).
  */
  block-size: calc-size(auto, size + 2rem);
}

OBRIGATÓRIO: não é possível fazer a interpolação entre duas palavras-chave de dimensionamento intrínseco diretamente. Uma extremidade da transição precisa ser um comprimento ou uma porcentagem.

Respeito às preferências de movimento do usuário

Animações que mudam o tamanho de grandes áreas de layout podem ser particularmente perturbadoras para usuários com distúrbios vestibulares. OBRIGATÓRIO: sempre respeite as preferências de movimento do usuário usando a consulta de mídia prefers-reduced-motion para simplificar ou minimizar animações não essenciais. As estratégias comuns incluem desativar totalmente o movimento, reduzir a duração ou substituir as mudanças de layout por transições sutis de opacidade.

.accordion-content {
  opacity: 0;
  transition: block-size 0.3s ease, opacity 0.3s ease;
}

.accordion-content.open {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .accordion-content {
    /* 
       EXAMPLE: Replacing disruptive layout animations with a subtle fade-in.
       Setting the block-size instantly and transitioning opacity 
       provides a clear state change without large-scale motion.
    */
    transition: opacity 1.5s ease;
  }

  .accordion-content.open {
    /* Jump the size instantly */
    block-size: auto;
  }
}

Como aplicar restrições a tamanhos intrínsecos

Você pode usar calc-size() com qualquer função matemática de CSS, como min(), max(), clamp() ou round(), para garantir que o tamanho intrínseco de um elemento permaneça dentro dos limites do design.

.dynamic-container {
  /* MANDATORY: Always provide a fallback for browsers that do not support calc-size() */
  inline-size: fit-content;

  /* 
    DO: Establish a dynamic size based on content, while:
    1. Enforcing boundaries using CSS math functions (min, clamp, etc.)
    2. Modifying the intrinsic size with fixed or relative offsets
  */
  inline-size: calc-size(fit-content, min(size + var(--extra-space), var(--max-allowed)));
}

Considerações importantes

  • Armadilhas de porcentagem: as porcentagens dentro de <calc-sum> são resolvidas em relação ao tamanho do contêiner, não à palavra-chave size. Por exemplo, calc-size(auto, size + 10%) adiciona 10% da largura do elemento pai à largura auto do elemento, o que pode levar a resultados inesperados ou estouros.
  • Requisito de cálculos: OBRIGATÓRIO: use interpolate-size: allow-keywords em vez de calc-size() para animações simples (por exemplo, de 0 para auto). Use calc-size() somente quando o layout exigir ajustes matemáticos dinâmicos na base intrínseca.
  • Observação sobre performance: animar propriedades do modelo de caixa, como inline-size ou block-size, aciona novos cálculos de layout, o que pode ser caro. Use animações calc-size() principalmente para elementos essenciais ao layout em que as alternativas não relacionadas ao layout são insuficientes.

Estratégias de fallback

calc-size() e interpolate-size são aprimoramentos progressivos. Em navegadores que não oferecem suporte a elas, as propriedades serão ignoradas e o layout continuará funcional, mas as animações para palavras-chave intrínsecas vão pular em vez de fazer a transição. Sempre forneça uma palavra-chave ou um comprimento padrão como substituto.

.element {
  /* Fallback for browsers that don't support calc-size() */
  inline-size: fit-content; 
  /* Modern browsers will override the fallback */
  inline-size: calc-size(fit-content, size + 2rem);
}

Alternativas de animação e transição

Em navegadores sem suporte para calc-size() ou interpolate-size, as transições que envolvem palavras-chave de dimensionamento intrínseco não serão interpoladas.

  • Degradação suave: o substituto padrão é um "salto instantâneo" entre estados (por exemplo, de 0 para auto). Isso geralmente é aceitável, já que o layout permanece funcional.
  • Experiência aprimorada: use @supports para aplicar uma lógica de layout complexa ou um estilo adicional que só faz sentido quando animações intrínsecas suaves são possíveis.
  • Evite medições baseadas em JS: embora seja possível usar JavaScript para medir elementos e animar as dimensões manualmente, isso geralmente é desnecessário e pode causar problemas de layout. O uso do "salto instantâneo" nativo é o substituto recomendado para aplicativos da Web modernos.

Para animações, a experiência de fallback será um salto instantâneo para o tamanho final. Para detectar o suporte em CSS ou JavaScript:

/* CSS Feature Detection */
@supports (inline-size: calc-size(auto, size + 0px)) {
  .element {
    /* Apply advanced logic only when supported */
  }
}
/* JavaScript Feature Detection */
if (CSS.supports('inline-size', 'calc-size(auto, size + 0px)')) {
  // Apply advanced sizing or animations
}