Utilizza la proprietà interpolate-size
o la funzione calc-size()
per attivare transizioni e animazioni fluide dalle lunghezze alle parole chiave di dimensionamento intrinseco e viceversa.
Data di pubblicazione: 17 settembre 2024
Introduzione
Una funzionalità CSS spesso richiesta è la possibilità di animare height: auto
. Una leggera variazione di questa richiesta consiste nel passare alla proprietà width
anziché a height
oppure a una delle altre dimensioni intrinseche rappresentate da parole chiave come min-content
, max-content
e fit-content
.
Ad esempio, nella demo seguente sarebbe bello se le etichette si animassero gradualmente fino alla loro larghezza naturale quando si passa il mouse sopra le icone.
Il CSS utilizzato è il seguente:
nav a {
width: 80px;
overflow-x: clip;
transition: width 0.35s ease; /* 👈 Transition the width */
&:hover,
&:focus-visible {
width: max-content; /* 👈 Doesn't work with transitions */
}
}
Anche se viene dichiarato un transition
per eseguire la transizione della proprietà width
e width: auto
è dichiarato in :hover
, non viene eseguita alcuna transizione fluida. Invece, il cambiamento è brusco.
Creare animazioni da e verso le parole chiave per le dimensioni intrinseche con interpolate-size
La proprietà interpolate-size
CSS ti consente di controllare se le animazioni e le transizioni delle parole chiave di dimensionamento intrinseco CSS devono essere consentite o meno.
Il valore predefinito è numeric-only
, che non attiva l'interpolazione. Se imposti la proprietà su allow-keywords
, attivi le interpolazioni dalle lunghezze alle parole chiave di dimensionamento intrinseco CSS nei casi in cui il browser possa animare queste parole chiave.
numeric-only
: un<intrinsic-size-keyword>
non può essere interpolato.allow-keywords
: è possibile interpolare due valori se uno è<intrinsic-size-keyword>
e l'altro è<length-percentage>
. […]
Poiché la proprietà interpolate-size
è una proprietà ereditata, puoi dichiararla in :root
per attivare la transizione alle e dalle parole chiave di dimensionamento intrinseco per l'intero documento. Questo è l'approccio consigliato.
/* Opt-in the whole page to interpolate sizes to/from keywords */
:root {
interpolate-size: allow-keywords; /* 👈 */
}
Nella demo seguente, questa regola viene aggiunta al codice. Di conseguenza, le animazioni da e verso width: auto
funzionano correttamente (nei browser con supporto):
Limita la copertura dell'attivazione restringendo il selettore
Se vuoi limitare l'attivazione di allow-keywords
solo a un sottoalbero del documento, modifica il selettore da allow-keywords
all'elemento che vuoi scegliere come target.:root
Ad esempio, se il <header>
della tua pagina non è compatibile con questo tipo di transizioni, puoi limitare l'attivazione solo all'elemento <main>
e ai suoi discendenti come segue:
main { /* 👈 Scope the opt-in to only <main> and its descendants */
interpolate-size: allow-keywords;
}
Perché non consentire l'animazione verso e dalle parole chiave per le dimensioni per impostazione predefinita?
Un feedback comune su questo meccanismo di attivazione è che i browser dovrebbero consentire solo le transizioni e le animazioni dalle parole chiave di dimensioni intrinseche alle lunghezze per impostazione predefinita.
L'opzione per attivare questo comportamento è stata studiata durante lo sviluppo della funzionalità. Il gruppo di lavoro ha scoperto che l'attivazione di questa opzione per impostazione predefinita non è compatibile con le versioni precedenti perché molti fogli di stile presuppongono che le parole chiave di dimensionamento intrinseco (ad es. auto
o min-content
) non possano essere animate. Puoi trovare i dettagli in questo commento sul problema pertinente del gruppo di lavoro CSS.
Pertanto, la proprietà è attiva. Grazie alla sua caratteristica di ereditarietà, l'attivazione di un intero documento è semplicemente una dichiarazione interpolate-size: allow-sizes
su :root
, come descritto in precedenza.
Esegui l'animazione verso e da parole chiave per le dimensioni intrinseche con calc-size()
Un altro modo per attivare l'interpolazione verso e dalle parole chiave di dimensionamento intrinseco è utilizzare la funzione calc-size()
. Consente di eseguire operazioni matematiche sulle dimensioni intrinseche in modo sicuro e ben definito.
La funzione accetta due argomenti, nell'ordine:
- Un criterio di base per le dimensioni del calcolo, che può essere un
<intrinsic-size-keyword>
, ma anche uncalc-size()
nidificato. - Un calcolo delle dimensioni calcolate, che ti consente di eseguire calcoli utilizzando la base delle dimensioni calcolate. Per fare riferimento alla base di calcolo delle dimensioni, utilizza la parola chiave
size
.
Ecco alcuni esempi:
width: calc-size(auto, size); // = the auto width, unaltered
width: calc-size(min-content, size); // = the min-content width, unaltered
Se aggiungi calc-size()
alla demo originale, il codice avrà il seguente aspetto:
nav a {
width: 80px;
overflow-x: clip;
transition: width 0.35s ease;
&:hover,
&:focus-visible {
width: calc-size(max-content, size); /* 👈 */
}
}
Visivamente, il risultato è esattamente lo stesso che si ottiene utilizzando interpolate-size
. Pertanto, in questo caso specifico devi utilizzare interpolate-size
.
La vera forza di calc-size()
è la sua capacità di eseguire calcoli, cosa che non è possibile con interpolate-size
:
width: calc-size(auto, size - 10px); // = The auto width minus 10 pixels
width: calc-size(min-content, size + 1rem); // = The min-content width plus 1rem
width: calc-size(max-content, size * .5); // = Half the max-content width
Ad esempio, se vuoi che tutti i paragrafi di una pagina abbiano le dimensioni del multiplo più vicino di 50px
, puoi utilizzare quanto segue:
p {
width: calc-size(fit-content, round(up, size, 50px));
height: calc-size(auto, round(up, size, 50px));
}
calc-size()
consente inoltre di eseguire l'interpolazione tra due calc-size()
quando entrambe le basi di calcolo delle dimensioni sono identiche. Anche questo è un risultato che non può essere ottenuto con interpolate-size
.
#element {
width: min-content; /* 👈 */
transition: width 0.35s ease;
&:hover {
width: calc-size(min-content, size + 10px); /* 👈 */
}
}
Perché non consentire <intrinsic-size-keyword>
in calc()
?
Una domanda che viene spesso posta in merito a calc-size()
è perché il gruppo di lavoro CSS non ha modificato la funzione calc-size()
per supportare le parole chiave di dimensionamento intrinseco.calc()
Uno dei motivi è che non puoi combinare le parole chiave di dimensionamento intrinseco durante i calcoli. Ad esempio, potresti essere tentato di scrivere calc(max-content - min-content)
, che sembra valido, ma in realtà non lo è. calc-size()
applica la correttezza perché, a differenza di calc()
, accetta un solo <intrinsic-size-keyword>
come primo argomento.
Un altro motivo è la consapevolezza del contesto. Alcuni algoritmi di layout hanno un comportamento speciale per parole chiave di dimensionamento intrinseco specifiche. calc-size()
è definito esplicitamente per rappresentare una dimensione intrinseca, non un <length>
. Grazie a questo, questi algoritmi sono in grado di trattare calc-size(<intrinsic-size-keyword>, …)
come <intrinsic-size-keyword>
, mantenendo il suo comportamento speciale per quella parola chiave.
Quale approccio utilizzare?
Nella maggior parte dei casi, dichiara interpolate-size: allow-keywords
su :root
. È il modo più semplice per attivare l'animazione verso e dalle parole chiave di dimensionamento intrinseco, in quanto si tratta essenzialmente di un comando composto da una sola riga.
/* Opt-in the whole page to animating to/from intrinsic sizing keywords */
:root {
interpolate-size: allow-keywords; /* 👈 */
}
Questo frammento di codice è un buon miglioramento progressivo, in quanto i browser che non lo supportano torneranno a non utilizzare le transizioni.
Quando hai bisogno di un controllo più granulare, ad esempio per eseguire calcoli, o vuoi utilizzare un comportamento che solo calc-size()
può eseguire, puoi ricorrere all'utilizzo di calc-size()
.
#specific-element {
width: 50px;
&:hover {
width: calc-size(fit-content, size + 1em); /* 👈 Only calc-size() can do this */
}
}
Tuttavia, l'utilizzo di calc-size()
nel codice richiede l'inclusione di soluzioni di riserva per i browser che non supportano calc-size()
. Ad esempio, aggiungendo dichiarazioni di dimensioni aggiuntive o tornando al rilevamento delle funzionalità utilizzando @supports
.
width: fit-content;
width: calc-size(fit-content, size + 1em);
/* 👆 Browsers with no calc-size() support will ignore this second declaration,
and therefore fall back to the one on the line before it. */
Altre demo
Ecco altre demo che sfruttano interpolate-size: allow-keywords
a proprio vantaggio.
Notifiche
La seguente demo è un fork di questa demo @starting-style
. Il codice è stato modificato per consentire l'aggiunta di elementi con altezze diverse.
Per farlo, l'intera pagina attiva l'interpolazione delle parole chiave per le dimensioni e height
su ogni elemento .item
è impostato su auto
. In caso contrario, il codice è esattamente lo stesso di prima del fork.
:root {
interpolate-size: allow-keywords; /* 👈 */
}
.item {
height: auto; /* 👈 */
@starting-style {
height: 0px;
}
}
Animare l'elemento <details>
Un caso d'uso tipico in cui è consigliabile utilizzare questo tipo di interpolazione è l'animazione di un widget di informativa o di una fisarmonica esclusiva durante l'apertura. In HTML, utilizzi l'elemento <details>
per questo scopo.
Con interpolate-size: allow-keywords
puoi ottenere risultati sorprendenti:
@supports (interpolate-size: allow-keywords) {
:root {
interpolate-size: allow-keywords;
}
details {
transition: height 0.5s ease;
height: 2.5rem;
&[open] {
height: auto;
overflow: clip; /* Clip off contents while animating */
}
}
}
Come puoi vedere, però, l'animazione viene eseguita solo quando si apre il widget dell'informativa. Per risolvere il problema, in Chrome stiamo lavorando allo pseudo ::details-content
che verrà rilasciato entro la fine dell'anno (e che verrà trattato in un post futuro). Combinando interpolate-size: allow-keywords
e ::details-content
, puoi ottenere un'animazione in entrambe le direzioni: