Ich weiß, das ist etwas, das Chris schon ewig wollte, also ist es keine Überraschung, dass er bereits einen fantastischen Beitrag nur einen Tag nach Bekanntwerden der Nachricht geschrieben hat. Tatsächlich habe ich zum ersten Mal durch seinen Beitrag davon erfahren und konnte keine Ankündigung finden. Deshalb dachte ich, ich fasse ein paar Notizen zusammen, da es sich um eine bedeutende Entwicklung handelt.
Die Nachricht: Der Übergang zu auto ist jetzt Realität! Nun, es wird Realität werden. Chrome Canary hat kürzlich die Unterstützung dafür eingeführt, und das ist der einzige Ort, an dem Sie es im Moment finden können. Und selbst dann wissen wir nicht, ob die Implementierung in Chrome Canary seinen Weg in die Syntax findet, wenn die Funktion offiziell wird.
Das Problem
Hier ist die Situation. Sie haben ein Element. Sie haben es markiert, Inhalte hineingepackt und ihm viele Stile zugewiesen. Wissen Sie, wie hoch es ist? Natürlich nicht! Sicher, wir können JavaScript bitten, das Element für uns zu bewerten, aber was CSS betrifft, sind die berechneten Abmessungen des Elements unbekannt.
Das macht es schwierig, zum Beispiel dieses Element von height: 0 auf height: beliebig zu animieren. Wir müssen wissen, was "beliebig" ist, und das können wir nur tun, indem wir dem Element eine feste Höhe zuweisen. So haben wir Zahlen, von denen wir von einer Höhe von Null auf diese spezifische Höhe übergehen können.
.panel {
height: 0;
transition: height 0.25s ease-in;
&.expanded {
height: 300px;
}
}
Aber was passiert, wenn sich dieses Element im Laufe der Zeit ändert? Vielleicht ändert sich die Schriftart, wir fügen Polsterung hinzu, es werden mehr Inhalte eingefügt ... alles, was die Abmessungen verändert. Wir müssen wahrscheinlich diese height: 300px auf die neue feste Höhe aktualisieren, die am besten funktioniert. Deshalb wird JavaScript oft verwendet, um Dinge zu schalten, die sich vergrößern und verkleinern, sowie für andere Workarounds.
Ich spreche hier von der height-Eigenschaft, aber wir sprechen auch von ihrem logischen Äquivalent, block-size, sowie von width und inline-size. Oder von jeder Richtung, wenn wir das schon sagen.
Übergang zu auto
Das ist das Ziel, oder? Wir neigen dazu, zu height: auto zu greifen, wenn die Höhenabmessung unbekannt ist. Von dort aus lassen wir JavaScript berechnen, was das ergibt, und kümmern uns um den Rest.
Die aktuelle Chrome-Implementierung verwendet CSS calc-size() für die Hauptarbeit. Sie erkennt das Schlüsselwort auto und berechnet, wie der Name schon sagt, diese Zahl. Mit anderen Worten, wir können dies anstelle des Ansatzes mit fester Höhe tun.
.panel {
height: 0;
transition: height 0.25s ease-in;
&.expanded {
height: calc-size(auto);
}
}
Das ist im Grunde alles! Natürlich ist calc-size() zu komplexeren Ausdrücken fähig, aber die Tatsache, dass wir ihm nur ein vages Schlüsselwort über die Höhe eines Elements übergeben können, ist verdammt beeindruckend. Es ermöglicht uns, von einem festen Wert zur intrinsischen Größe des Elements und zurück zu gelangen.
Ich musste es ausprobieren. Ich bin sicher, dass es hier unzählige Anwendungsfälle gibt, aber ich habe mich für eine schwebende Schaltfläche in einer Kalenderkomponente entschieden, die eine bestimmte Anzahl ausstehender Kalendereinladungen anzeigt. Klicken Sie auf die Schaltfläche, und ein Bereich erweitert sich über dem Kalender und zeigt die Einladungen an. Klicken Sie erneut darauf, und der Bereich kehrt zu seinem ursprünglichen Zustand zurück. JavaScript kümmert sich um die Klickinteraktion, die eine Klassenänderung auslöst, die die Höhe in CSS übergibt.
Ein Video, falls Sie keine Lust haben, Canary zu öffnen
Dies ist das relevante CSS
.invite-panel {
height: 0;
overflow-y: clip;
transition: height 0.25s ease-in;
}
Beim Klicken setzt JavaScript die automatische Höhe des Elements als Inline-Stil, um das CSS zu überschreiben.
<div class="invite-panel" style="height: calc(auto)">
Die transition-Eigenschaft in CSS teilt dem Browser mit, dass wir die height-Eigenschaft irgendwann ändern wollen, und macht dies reibungslos. Und wie bei jeder Übergangs- oder Animationsbewegung ist es ratsam, Bewegungsunempfindlichkeiten zu berücksichtigen, indem Sie die Bewegung mit prefers-reduced-motion verlangsamen oder entfernen.
Was ist mit display: none?
Dies ist eine der ersten Fragen, die mir in den Sinn kamen, als ich Chris' Beitrag las, und er geht auch darauf ein. Der Übergang von einem Element von display: none zu seiner intrinsischen Größe ist ähnlich wie der Übergang von height: 0. Es mag den Anschein haben, dass ein nicht angezeigtes Element keine Höhe hat, aber es hat tatsächlich eine berechnete Höhe von auto, es sei denn, ihm wird eine bestimmte Höhe zugewiesen.

Daher ist zusätzliche Arbeit erforderlich, wenn wir von display: none in CSS übergehen wollen. Ich werde einfach den Code von Chris einfügen, da er die wichtigsten Teile gut demonstriert.
.element {
/* hard mode!! */
display: none;
transition: height 0.2s ease-in-out;
transition-behavior: allow-discrete;
height: 0;
@starting-style {
height: 0;
}
&.open {
height: calc(auto);
}
}
- Das Element beginnt sowohl mit
display: noneals auch mitheight: 0. - Es gibt eine
.open-Klasse, die die Höhe des Elements aufcalc-size(auto)setzt.
Das sind die beiden Punkte, die wir verbinden müssen, und das tun wir, indem wir zuerst transition-behavior: allow-discrete auf das Element setzen. Das ist neu für mich, aber die Spezifikation besagt, dass transition-behavior "festlegt, ob Übergänge für diskrete Eigenschaften gestartet werden oder nicht". Und wenn wir allow-discrete deklarieren, "werden Übergänge für diskrete Eigenschaften sowie für interpolierbare Eigenschaften gestartet".
Nun, DevTools hat uns genau dort gezeigt, dass height: auto eine diskrete Eigenschaft ist! Beachten Sie jedoch die @starting-style-Deklaration. Wenn Sie damit nicht vertraut sind, sind Sie nicht allein. Die Idee ist, dass sie es uns ermöglicht, einen Stil für einen Übergang festzulegen, mit dem dieser "startet". Und da die diskrete Höhe unseres Elements auto ist, müssen wir dem Übergang mitteilen, stattdessen bei height: 0 zu starten.
.element {
/* etc. */
@starting-style {
height: 0;
}
}
Jetzt können wir von Null zu auto übergehen, da wir die diskrete Höhe mit @starting-style quasi überschreiben. Ziemlich cool, dass wir das können!
Das ist erstaunlich. Unzählige Male habe ich mir gewünscht, dass auto ein brauchbares Animationsziel sein könnte.
Ich habe vor ein paar Monaten @starting-style verwendet, um die Anzeige eines nativen
<dialog>zu animieren (nichts Verrücktes, nur Opazität und Übersetzung), und es verursachte immer wieder das Abstürzen von Chrome-Tabs mit der Meldung "Aw snap".Seien Sie also vorsichtig da draußen am Rande, Leute.
Nicht viele Leute wissen es, aber dieser Anwendungsfall wurde bereits mit CSS Grid unterstützt. Ein Grid mit einer nicht spezifizierten Höhe hat Grid-Spuren mit einer Höhe von 1fr. Sie können also nahtlos von 0fr zu 1fr übergehen.
Haben wir das nicht schon mit CSS-Grid herausgefunden?
Zuerst möchte ich auf einen Tippfehler hinweisen, der mich verwirrt hat (bis ich verstand, dass es einen Tippfehler gibt).
> [...] aber es hat tatsächlich eine berechnete Höhe oder automatisch, es sei denn, eine bestimmte Höhe ist darauf festgelegt.
„berechnete Höhe oder auto“ sollte „berechnete Höhe von auto“ sein.
Und zweitens: Ich glaube, Sie haben die Erklärung falsch gegeben, warum
transition-behavior: allow-discrete;benötigt wird, wenndisplay: none;beteiligt ist. Es scheint, dass in Chris' Artikel der Teil, der vondisplay: noneaufdisplay: etwaswechselt, weggelassen wurde oder zumindest habe ich ihn nicht gesehen, aber soweit ich das verstanden habe, würde der Stil oder Code, der ihn festlegt, die Eigenschaft sofort ändern, sodass wir niemals eine schließende Animation der Höhe sehen könnten. Mittransition-behavior: allow-discrete;tritt die tatsächliche Umstellung aufdisplay: noneerst in Kraft, nachdem die Animation / Übergang abgeschlossen ist. (Und umgekehrt verhält es sich, wenn ein Stil ein Element vondisplay: noneaufdisplay: etwasändert.)Das
@starting-styleist erforderlich, denn wie Sie erwähnt haben, wird ein Element mitdisplay: nonemit einem berechneten Stil vonheight: autogerendert, unabhängig von der Eigenschaft, die über den Stil aufheight: 0gesetzt wurde. Unintuitiv ja, aber wahrscheinlich altes, spezifiziertes, etabliertes Browserverhalten.Was bedeuten würde, dass wir versuchen würden, von
autozuautozu wechseln, was nichts tun würde. Daher@starting-style { height: 0; }.Und drittens: Danke für den Artikel.
Juhu. CSS-Animationen zum Öffnen/Schließen von
<details><summary>-Blöcken ohne eine Zeile JS!Ich habe auch auf Stackoverflow darüber geschrieben, bezüglich der Übergabe der
display-Eigenschaft: https://stackoverflow.com/a/78304935/104380Anstatt Höhe zu verwenden, habe ich
max-height: 0;verwendet und es zumax-height: 1000px;(größer als der Inhalt sein konnte) für viele, viele Jahre übergeben. Das funktionierte perfekt ohne feste Höhe. Aber es war ein Hack. Ich bin froh, dass ich ihn nicht mehr brauche.