Animacja do wysokości: auto; (i inne kluczowe słowa dotyczące rozmiaru) w CSS

Aby włączyć płynne przejścia i animacje z słów kluczowych z długością na słowa kluczowe z właściwościami rozmiaru, użyj właściwości interpolate-size lub funkcji calc-size().

Opublikowano: 17 września 2024 r.

Wprowadzenie

Często żądaną funkcją CSS jest możliwość animacji do height: auto. Nieznaczną odmianą tej prośby jest przejście na usługę width zamiast height lub na dowolną inną właściwą wielkość reprezentowaną przez słowa kluczowe takie jak min-content, max-contentfit-content.

Na przykład w tym demo dobrze byłoby, gdyby etykiety płynnie zmieniały swoją szerokość podczas najeżdżania kursorem na ikony.

Użyty kod 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 */
    }
}

Mimo że element transition jest zadeklarowany jako element przejściowy właściwości width, a element width: auto jest zadeklarowany jako element przejściowy właściwości :hover, nie następuje płynne przejście. Zamiast tego zmiana jest gwałtowna.

Animacja słów kluczowych z domyślnym rozmiarem za pomocą interpolate-size

Browser Support

  • Chrome: 129.
  • Edge: 129.
  • Firefox: not supported.
  • Safari: not supported.

Source

Właściwość CSS interpolate-size pozwala określić, czy animacje i przejścia z użyciem kluczowych słów dotyczących rozmiaru domyślnego w CSS mają być dozwolone.

Wartość domyślna to numeric-only, która nie umożliwia interpolacji. Gdy ustawisz tę właściwość na allow-keywords, akceptujesz interpolację z długości na słowa kluczowe z domyślnym rozmiarem CSS w przypadkach, gdy przeglądarka może animować te słowa kluczowe.

Specyfikacja:

  • numeric-only: nie można interpolować <intrinsic-size-keyword>.
  • allow-keywords: 2 wartości można interpolować, jeśli jedna z nich jest wartością <intrinsic-size-keyword>, a druga – <length-percentage>. […]

Właściwość interpolate-size jest dziedziczona, więc możesz ją zadeklarować w elementach :root, aby umożliwić przejście z kluczowych słów z właściwościami rozmiaru bezwzględnego w całym dokumencie. To zalecane podejście.

/* Opt-in the whole page to interpolate sizes to/from keywords */
:root {
    interpolate-size: allow-keywords; /* 👈 */
}

W tym pokazie reguła jest dodawana do kodu. W rezultacie animacje do i z width: auto działają prawidłowo (w obsługiwanych przeglądarkach):

Ogranicz zasięg zgody na udział, zawężając selektor

Jeśli chcesz ograniczyć allow-keywords tylko do poddrzewa dokumentu, zmień selektor z :root na element, który chcesz uwzględnić w kierowaniu. Jeśli na przykład <header> na Twojej stronie jest niezgodny z tym typem przejść, możesz ograniczyć rejestrację tylko do elementu <main> i jego elementów potomnych w ten sposób:

main { /* 👈 Scope the opt-in to only <main> and its descendants */
    interpolate-size: allow-keywords;
}

Dlaczego domyślnie nie zezwalać na animację i wymiar słów kluczowych?

W przypadku tego mechanizmu często słyszymy, że przeglądarki powinny domyślnie zezwalać na przejścia i animacje z użyciem słów kluczowych z właściwymi rozmiarami do długości domyślnie.

Podczas opracowywania tej funkcji zbadano możliwość włączenia tej opcji. Grupa robocza odkryła, że włączenie tej opcji domyślnie nie jest zgodne z wsteczną kompatybilnością, ponieważ wiele arkuszy stylów zakłada, że nie można animować elementów z właściwymi rozmiarami (takich jak auto lub min-content). Szczegółowe informacje znajdziesz w tym komentarzu do odpowiedniego problemu w grupie roboczej CSS.

Dlatego usługa jest opcjonalna. Dzięki właściwości dziedziczenia włączenie w całym dokumencie jest tylko deklaracją interpolate-size: allow-sizes w :root, jak opisano wcześniej.

Animacja słów kluczowych z domyślnym rozmiarem za pomocą calc-size()

Browser Support

  • Chrome: 129.
  • Edge: 129.
  • Firefox: not supported.
  • Safari: not supported.

Source

Innym sposobem włączenia interpolacji do i z kluczowych słów z własną wielkością jest użycie funkcji calc-size(). Umożliwia ona bezpieczne i dobrze zdefiniowane wykonywanie obliczeń na podstawie rozmiarów wewnętrznych.

Funkcja ta przyjmuje 2 argumenty w kolejności:

  • Obiekt typu calc-size, który może być obiektem typu <intrinsic-size-keyword>, ale też zagnieżdżonym obiektem typu calc-size().
  • Obliczenie wielkości obliczeń, które umożliwia wykonywanie obliczeń na podstawie wielkości obliczeń. Aby odwołać się do podstawy calc-size, użyj słowa kluczowego size.

Oto przykłady:

width: calc-size(auto, size);        // = the auto width, unaltered
width: calc-size(min-content, size); // = the min-content width, unaltered

Dodanie calc-size() do oryginalnego dema powoduje, że kod wygląda tak:

nav a {
    width: 80px;
    overflow-x: clip;
    transition: width 0.35s ease;

    &:hover,
    &:focus-visible {
        width: calc-size(max-content, size); /* 👈 */
    }
}

Wizualnie efekt jest dokładnie taki sam jak w przypadku użycia interpolate-size. W tym konkretnym przypadku należy użyć interpolate-size.

calc-size() wyróżnia się możliwością wykonywania obliczeń, których nie można wykonać za pomocą 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

Jeśli na przykład chcesz, aby rozmiar wszystkich akapitów na stronie był zbliżony do wielokrotności wartości 50px, możesz użyć tego kodu:

p {
    width: calc-size(fit-content, round(up, size, 50px));
    height: calc-size(auto, round(up, size, 50px));
}

Funkcja calc-size() umożliwia też interpolację między 2 wartościami calc-size(), gdy obie ich wartości bazowe są identyczne. Tego też nie można osiągnąć za pomocą interpolate-size.

#element {
    width: min-content; /* 👈 */
    transition: width 0.35s ease;

    &:hover {
        width: calc-size(min-content, size + 10px); /* 👈 */
    }
}

Why not allow <intrinsic-size-keyword> in calc()?

Pytanie, które często pojawia się w związku z funkcją calc-size(), brzmi, dlaczego zespół roboczy CSS nie dokonał korekty funkcji calc(), aby obsługiwała ona słowa kluczowe z własną wielkością.

Jednym z powodów jest to, że podczas wykonywania obliczeń nie można mieszać ze sobą słów kluczowych z uwzględnieniem rozmiaru. Możesz na przykład chcieć napisać calc(max-content - min-content), co wygląda na prawidłowe, ale w rzeczywistości tak nie jest. Funkcja calc-size() wymusza poprawność, ponieważ w przeciwieństwie do funkcji calc() jako pierwszy argument przyjmuje tylko jedną wartość <intrinsic-size-keyword>.

Innym powodem jest kontekst. Niektóre algorytmy układu działają w specyficzny sposób w przypadku określonych ściśle określonych rozmiarów słów kluczowych. calc-size() jest wyraźnie zdefiniowany jako rozmiar wewnętrzny, a nie <length>. Dzięki temu algorytmy mogą traktować calc-size(<intrinsic-size-keyword>, …) jako <intrinsic-size-keyword>, zachowując specjalne zachowanie tego słowa kluczowego.

Jakie podejście zastosować?

W większości przypadków należy zadeklarować interpolate-size: allow-keywords w elementach :root. Jest to najprostszy sposób włączenia animacji do i z wyszukiwania z użyciem słów kluczowych z właściwymi wymiarami, ponieważ wymaga tylko jednej linii kodu.

/* Opt-in the whole page to animating to/from intrinsic sizing keywords */
:root {
    interpolate-size: allow-keywords; /* 👈 */
}

Ten fragment kodu jest przyjemnym ulepszeniem, ponieważ przeglądarki, które go nie obsługują, nie będą używać przejść.

Jeśli potrzebujesz bardziej szczegółowej kontroli nad takimi działaniami jak wykonywanie obliczeń lub chcesz użyć zachowania, które jest możliwe tylko dla calc-size(), możesz użyć calc-size().

#specific-element {
    width: 50px;

    &:hover {
        width: calc-size(fit-content, size + 1em); /* 👈 Only calc-size() can do this */
    }
}

Jednak użycie w kodzie wartości calc-size() wymaga uwzględnienia wartości zastępczych dla przeglądarek, które nie obsługują wartości calc-size(). Możesz na przykład dodać deklaracje dodatkowych rozmiarów lub użyć funkcji wykrywania za pomocą atrybutu @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. */

Więcej wersji demonstracyjnych

Oto kilka demonstracji, które wykorzystują interpolate-size: allow-keywords.

Powiadomienia

Poniższe demo jest pochodną tego demo @starting-style. Kod został dostosowany, aby umożliwić dodawanie elementów o różnej wysokości.

Aby to osiągnąć, cała strona korzysta z interpolacji rozmiaru słowa kluczowego, a wartość height w każdym elemencie .item jest ustawiona na auto. W pozostałych miejscach kod jest dokładnie taki sam jak przed utworzeniem gałęzi.

:root {
    interpolate-size: allow-keywords; /* 👈 */
}

.item {
    height: auto; /* 👈 */

    @starting-style {
        height: 0px;
    }
}

Animowanie elementu <details>

Ten typ interpolacji jest zwykle używany do animowania widżetu wyświetlającego informacje lub ekskluzywnej harmonijki podczas jej otwierania. W HTML używasz do tego elementu <details>.

Dzięki interpolate-size: allow-keywords możesz osiągnąć wiele:

@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 */
        }
    }
}

Jak widać, animacja jest odtwarzana tylko podczas otwierania widżetu. Aby to umożliwić, pracujemy nad pseudonimem ::details-content, który zostanie dodany do Chrome jeszcze w tym roku (omówimy go w jednym z kolejnych wpisów). Połączenie właściwości interpolate-size: allow-keywords i ::details-content umożliwia animację w obie strony: