Anima alle dimensioni intrinseche

Funzionalità web: calc-size() interpolate-size

L'animazione di elementi con dimensioni dinamiche come block-size: auto o inline-size: max-content ha storicamente richiesto JavaScript o hack "max-height" fragili. La proprietà interpolate-size e la funzione calc-size() consentono al browser di interpolare in modo nativo tra lunghezze fisse e parole chiave di dimensionamento intrinseco.

Procedura di implementazione

  1. Attiva l'interpolazione delle parole chiave: applica interpolate-size: allow-keywords a un elemento principale (in genere :root) per attivare le transizioni per le proprietà utilizzando parole chiave intrinseche.
  2. Definisci la transizione: imposta un transition per la proprietà di dimensionamento (ad es. block-size, inline-size) sull'elemento di destinazione.
  3. Utilizza parole chiave intrinseche: modifica la proprietà di dimensionamento in una parola chiave intrinseca supportata (auto, min-content, max-content, fit-content o, per flex-basis, content) durante un'interazione (ad esempio :hover o una classe di stato).
  4. Esegui calcoli (facoltativo): utilizza calc-size() se devi eseguire calcoli matematici su una dimensione intrinseca (ad es. auto + 2rem). calc-size() supporta anche la parola chiave any per i calcoli indipendenti dalla base.

Esempio: pattern di espansione generico

Puoi applicare questo pattern a qualsiasi contenitore (come una sezione "Mostra altro" o un menu di navigazione) per passare da un'altezza limitata alle dimensioni naturali dell'elemento.

/* Opt-in globally for all children */
:root {
  /* MANDATORY: Transitions to intrinsic keywords are disabled by default for compatibility */
  interpolate-size: allow-keywords;
}

.expandable-container {
  /* 1. Define a fixed initial size (or 0) and hide overflow */
  block-size: 100px;
  overflow: hidden;
  
  /* 2. Transition the sizing property */
  transition: block-size 0.4s ease-out;
}

.expandable-container.is-expanded {
  /* 3. Smoothly animate to the intrinsic natural height */
  block-size: auto;
}

Esempio: dimensione inline intrinseca calcolata

.badge {
  inline-size: 40px;
  overflow: hidden;
  white-space: nowrap;
  transition: inline-size 0.3s ease;
}

.badge:hover {
  /* calc-size(basis, calculation) */
  /* 'size' refers to the evaluated basis (max-content in this case) */
  inline-size: calc-size(max-content, size + 20px);
}

Esempio: transizione da Intrinsic a Fixed

Puoi anche animare nella direzione opposta, partendo da una dimensione naturale e comprimendo fino a una lunghezza specifica. Questo è utile per i componenti "ignorabili".

.collapsible-alert {
  /* 1. Start with the natural content height */
  block-size: auto;
  overflow: hidden;
  transition: block-size 0.5s ease-in-out, opacity 0.5s ease;
}

.collapsible-alert.is-dismissed {
  /* 2. Smoothly collapse to zero */
  block-size: 0;
  opacity: 0;
  pointer-events: none;
}

/* MANDATORY Copy-Paste Safety: Disable sizing animations for sensitive users */
@media (prefers-reduced-motion: reduce) {
  .expandable-container,
  .badge,
  .collapsible-alert {
    transition: none !important;
  }
}
// MANDATORY Accessibility Synchronization: Ensure elements collapsed to zero dimensions are removed from the assistive technology tree, and sync aria-expanded states on triggers.
const alertElement = document.querySelector('.collapsible-alert');
alertElement.addEventListener('transitionend', (e) => {
  if (e.propertyName === 'block-size' && alertElement.classList.contains('is-dismissed')) {
    alertElement.hidden = true;
  }
});

// Example trigger syncer
const triggerBtn = document.querySelector('.accordion-trigger');
triggerBtn?.addEventListener('click', () => {
  const isExpanded = triggerBtn.getAttribute('aria-expanded') === 'true';
  triggerBtn.setAttribute('aria-expanded', !isExpanded);
});

Limitazioni principali

  • Limitazione da parola chiave a parola chiave: non puoi creare un'animazione tra due parole chiave diverse direttamente (ad es. da min-content a max-content). Un'estremità della transizione deve essere una lunghezza o una percentuale fissa (ad es. da 0 a auto).
  • Sintassi di calc-size: all'interno di calc-size(), non puoi combinare parole chiave intrinseche diverse nella stessa espressione. Il primo argomento (la base) definisce ciò che rappresenta size.
  • Requisito di attivazione: le transizioni alle parole chiave intrinseche sono disattivate per impostazione predefinita (numeric-only) per mantenere la compatibilità con le versioni precedenti. Devi applicare interpolate-size: allow-keywords all'elemento o a un predecessore. calc-size() agisce come un override per proprietà, attivando automaticamente l'interpolazione ogni volta che viene utilizzato.

Strategie di riserva

interpolate-size e calc-size() sono potenziamenti progressivi. I browser che non le supportano eseguiranno un salto istantaneo alle dimensioni target.

  • Riduzione controllata: per le transizioni block-size: auto semplici, i browser standard cambiano semplicemente le dimensioni all'istante, il che è funzionale ma meno rifinito.
  • Valori di riserva manuali per le parole chiave: quando utilizzi calc-size(), fornisci sempre un valore di riserva standard per le parole chiave per i browser meno recenti, poiché questi ultimi ignorano l'intera dichiarazione calc-size().
.card {
  block-size: auto; /* Fallback for older browsers */
  block-size: calc-size(auto, size); /* Modern browsers use this */
  transition: block-size 0.3s ease;
}