Mit der Eigenschaft interpolate-size
oder der Funktion calc-size()
können Sie fließende Übergänge und Animationen von Längen zu Keywords für die intrinsische Größenanpassung und zurück ermöglichen.
Veröffentlicht: 17. September 2024
Einführung
Eine häufig angeforderte CSS-Funktion ist die Möglichkeit, zu height: auto
zu animieren. Eine leichte Abweichung dieser Anfrage besteht darin, die Eigenschaft width
anstelle von height
oder zu einer der anderen systeminternen Größen zu wechseln, die durch Keywords wie min-content
, max-content
und fit-content
dargestellt werden.
In der folgenden Demo wäre es beispielsweise schön, wenn die Labels beim Bewegen des Mauszeigers auf die Symbole reibungslos auf ihre natürliche Breite animiert würden.
Hier ist das verwendete CSS:
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 */
}
}
Obwohl eine transition
für die Umstellung der width
-Eigenschaft deklariert und width: auto
auf :hover
deklariert ist, erfolgt keine reibungslose Umstellung. Stattdessen ist die Veränderung abrupt.
Mit interpolate-size
von und zu Keywords für die intrinsische Größenanpassung animieren
Mit der CSS-Eigenschaft interpolate-size
können Sie festlegen, ob Animationen und Übergänge von CSS-internen Größen-Keywords zulässig sein sollen.
Der Standardwert ist numeric-only
, wodurch keine Interpolation aktiviert wird. Wenn Sie die Eigenschaft auf allow-keywords
festlegen, aktivieren Sie Interpolationen von Längen zu CSS-internen Größen-Keywords, wenn der Browser diese Keywords animieren kann.
Gemäß Spezifikation:
numeric-only
: Ein<intrinsic-size-keyword>
kann nicht interpoliert werden.allow-keywords
: Zwei Werte können interpoliert werden, wenn einer von ihnen ein<intrinsic-size-keyword>
und der andere ein<length-percentage>
ist. […]
Da die interpolate-size
-Eigenschaft übernommen wird, können Sie sie für :root
deklarieren, um den Übergang zu und von Keywords für die intrinsische Größenanpassung für das gesamte Dokument zu ermöglichen. Dies ist der empfohlene Ansatz.
/* Opt-in the whole page to interpolate sizes to/from keywords */
:root {
interpolate-size: allow-keywords; /* 👈 */
}
In der folgenden Demo wird diese Regel dem Code hinzugefügt. Die Animationen zu und von width: auto
funktionieren daher einwandfrei (in Browsern, die diese Funktion unterstützen):
Reichweite der Einwilligung einschränken, indem Sie die Auswahl eingrenzen
Wenn Sie die allow-keywords
-Einwilligung auf einen untergeordneten Knoten Ihres Dokuments beschränken möchten, passen Sie die Auswahl von :root
auf das Element an, auf das Sie das Targeting vornehmen möchten. Wenn das <header>
-Element Ihrer Seite beispielsweise nicht mit diesen Übergängen kompatibel ist, können Sie die Aktivierung auf das <main>
-Element und seine untergeordneten Elemente beschränken. Gehen Sie dazu so vor:
main { /* 👈 Scope the opt-in to only <main> and its descendants */
interpolate-size: allow-keywords;
}
Warum ist es nicht möglich, Animationen für die Größenanpassung von Keywords standardmäßig zuzulassen?
Häufig wird uns gesagt, dass Browser standardmäßig Übergänge und Animationen von Keywords für die benutzerdefinierte Textgröße zu Längen zulassen sollten.
Die Option zum Aktivieren dieses Verhaltens wurde bei der Entwicklung der Funktion erforscht. Die Arbeitsgruppe hat festgestellt, dass eine Aktivierung standardmäßig nicht abwärtskompatibel ist, da viele Stylesheets davon ausgehen, dass Keywords mit unveränderlicher Größe (wie auto
oder min-content
) nicht animiert werden können. Weitere Informationen finden Sie in diesem Kommentar zum entsprechenden Problem der CSS-Arbeitsgruppe.
Daher ist die Property optional. Dank der Vererbungseigenschaft ist die Aktivierung eines gesamten Dokuments lediglich eine interpolate-size: allow-sizes
-Erklärung für :root
, wie bereits beschrieben.
Mit calc-size()
von und zu Keywords für die intrinsische Größenanpassung animieren
Eine weitere Möglichkeit, die Interpolation zwischen und von Keywords für die intrinsische Größenanpassung zu aktivieren, ist die Verwendung der calc-size()
-Funktion. So können mathematische Berechnungen auf intrinsische Größen auf sichere und klar definierte Weise angewendet werden.
Die Funktion akzeptiert zwei Argumente:
- Eine Berechnungsgrundlage, die ein
<intrinsic-size-keyword>
-Wert, aber auch ein verschachteltescalc-size()
-Element sein kann. - Eine Berechnung vom Typ „calc-size“, mit der Sie Berechnungen anhand der Basis „calc-size“ durchführen können. Verwenden Sie das Schlüsselwort
size
, um auf die Basis für die Berechnung der Größe zu verweisen.
Hier einige Beispiele:
width: calc-size(auto, size); // = the auto width, unaltered
width: calc-size(min-content, size); // = the min-content width, unaltered
Wenn wir der ursprünglichen Demo calc-size()
hinzufügen, sieht der Code so aus:
nav a {
width: 80px;
overflow-x: clip;
transition: width 0.35s ease;
&:hover,
&:focus-visible {
width: calc-size(max-content, size); /* 👈 */
}
}
Visuell ist das Ergebnis genau das gleiche wie bei der Verwendung von interpolate-size
. In diesem Fall sollten Sie interpolate-size
verwenden.
calc-size()
eignet sich jedoch hervorragend für Berechnungen, was mit interpolate-size
nicht möglich ist:
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
Wenn Sie beispielsweise möchten, dass alle Absätze auf einer Seite auf das nächste Vielfache von 50px
skaliert werden, können Sie Folgendes verwenden:
p {
width: calc-size(fit-content, round(up, size, 50px));
height: calc-size(auto, round(up, size, 50px));
}
Mit calc-size()
können Sie auch zwischen zwei calc-size()
s interpolieren, wenn beide Basen der Berechnungsgröße identisch sind. Auch das ist mit interpolate-size
nicht möglich.
#element {
width: min-content; /* 👈 */
transition: width 0.35s ease;
&:hover {
width: calc-size(min-content, size + 10px); /* 👈 */
}
}
Warum ist <intrinsic-size-keyword>
in calc()
nicht zulässig?
Eine häufig gestellte Frage zu calc-size()
ist, warum die CSS Working Group die calc()
-Funktion nicht so angepasst hat, dass sie Keywords zur benutzerdefinierten Größenänderung unterstützt.
Ein Grund dafür ist, dass Sie bei Berechnungen keine Keywords zur benutzerdefinierten Größenanpassung kombinieren dürfen. Sie könnten beispielsweise versucht sein, calc(max-content - min-content)
zu schreiben, was zwar gültig aussieht, in Wirklichkeit aber nicht ist. calc-size()
erzwingt die Korrektheit, da sie im Gegensatz zu calc()
nur eine einzelne <intrinsic-size-keyword>
als erstes Argument akzeptiert.
Ein weiterer Grund ist die Kontextsensitivität. Einige Layoutalgorithmen haben ein spezielles Verhalten für bestimmte Keywords zur benutzerdefinierten Größenanpassung. calc-size()
ist explizit als intrinsische Größe definiert, nicht als <length>
. So können diese Algorithmen calc-size(<intrinsic-size-keyword>, …)
als <intrinsic-size-keyword>
behandeln und das spezielle Verhalten für dieses Keyword beibehalten.
Welchen Ansatz verwenden?
In den meisten Fällen müssen Sie interpolate-size: allow-keywords
auf :root
deklarieren. Dies ist die einfachste Möglichkeit, Animationen zu und von Keywords mit unveränderlicher Größe zu aktivieren, da es sich im Wesentlichen um einen einzeiler handelt.
/* Opt-in the whole page to animating to/from intrinsic sizing keywords */
:root {
interpolate-size: allow-keywords; /* 👈 */
}
Dieser Code ist eine gute progressive Verbesserung, da Browser, die ihn nicht unterstützen, keine Übergänge verwenden.
Wenn Sie eine genauere Kontrolle über Dinge benötigen, z. B. Berechnungen, oder ein Verhalten verwenden möchten, das nur calc-size()
ausführen kann, können Sie auf calc-size()
zurückgreifen.
#specific-element {
width: 50px;
&:hover {
width: calc-size(fit-content, size + 1em); /* 👈 Only calc-size() can do this */
}
}
Wenn Sie calc-size()
in Ihrem Code verwenden, müssen Sie jedoch Fallbacks für Browser einschließen, die calc-size()
nicht unterstützen. Beispielsweise können Sie zusätzliche Größendeklarationen hinzufügen oder auf die Featureerkennung mit @supports
zurückgreifen.
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. */
Weitere Demos
Hier sind einige weitere Demos, in denen interpolate-size: allow-keywords
zu ihrem Vorteil genutzt wird.
Benachrichtigungen
Die folgende Demo ist eine Fork von dieser @starting-style
Demo. Der Code wurde angepasst, damit Elemente mit unterschiedlichen Höhen hinzugefügt werden können.
Dazu wird die Keyword-Interpolation für die gesamte Seite aktiviert und die height
in jedem .item
-Element auf auto
festgelegt. Andernfalls ist der Code genau derselbe wie vor der Fork.
:root {
interpolate-size: allow-keywords; /* 👈 */
}
.item {
height: auto; /* 👈 */
@starting-style {
height: 0px;
}
}
<details>
-Element animieren
Ein typischer Anwendungsfall für diese Art der Interpolation ist die Animation eines Offenlegungs-Widgets oder eines ausschließlichen Akkordeons beim Öffnen. In HTML verwenden Sie dazu das Element <details>
.
Mit interpolate-size: allow-keywords
können Sie ziemlich weit kommen:
@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 */
}
}
}
Wie Sie sehen, wird die Animation jedoch nur ausgeführt, wenn das Offenlegungs-Widget geöffnet wird. Um diesem Wunsch gerecht zu werden, arbeitet Chrome an dem Pseudo ::details-content
, das im Laufe des Jahres in Chrome verfügbar sein wird und in einem späteren Post behandelt wird. Wenn Sie interpolate-size: allow-keywords
und ::details-content
kombinieren, können Sie eine Animation in beide Richtungen erhalten: