4 nowe funkcje CSS umożliwiające płynne wejście i wyjście

Ruch jest podstawą każdej cyfrowej interakcji, ponieważ prowadzi użytkownika od jednej interakcji do następnej. Na platformie internetowej występują jednak pewne przerwy w płynnych animacjach. Dotyczy to m.in. możliwości łatwego animowania animacji wejścia i wyjścia oraz płynnego animowania elementów, które można zamknąć, takich jak okna dialogowe i wyskakujące.

Aby wypełnić te luki, w Chrome 116 i 117 znajdziesz 4 nowe funkcje platformy internetowej, które umożliwiają płynne animacje i przejścia w przypadku osobnych usług.

Te 4 nowe funkcje to:

  • Możliwość animowania display i content-visibility na osi czasu klatki kluczowej (od Chrome 116).
  • Właściwość transition-behavior z kluczowym słowem allow-discrete, aby umożliwić przejścia z osobnych właściwości, takich jak display (z Chrome 117).
  • Reguła @starting-style służąca do animowania efektów wejścia z poziomu display: none do najwyższej warstwy (z Chrome 117).
  • Właściwość overlay służy do kontrolowania zachowania najwyższej warstwy podczas animacji (od Chrome 117).

Wyświetlanie animacji w klatkach kluczowych

Od wersji 116 przeglądarki Chrome możesz używać w regułach kluczowych klatek wartości displaycontent-visibility. Następnie zostaną one zastąpione w momencie wystąpienia klatki kluczowej. Nie trzeba dodawać żadnych nowych wartości, aby obsługiwać te funkcje:

.card {
  animation: fade-out 0.5s forwards;
}

@keyframes fade-out {
  100% {
    opacity: 0;
    display: none;
  }
}

W poprzednim przykładzie przezroczystość jest animowana do wartości 0 w ciągu 0,5 s, a potem ustawiana na wartość 0. Dodatkowo słowo kluczowe forwards sprawia, że animacja pozostaje w stanie końcowym, dzięki czemu element, do którego jest zastosowana, pozostaje w pozycji display: noneopacity: 0.

To prosty przykład, który pokazuje, co możesz zrobić z przejściem (zobacz demonstrację w sekcji Przejście). Przejścia nie umożliwiają jednak tworzenia bardziej złożonych animacji, takich jak ta:

.card {
  animation: spin-and-delete 1s ease-in forwards;
}

@keyframes spin-and-delete {
  0% {
    transform: rotateY(0);
    filter: hue-rotate(0);
  }
  80% {
    transform: rotateY(360deg);
    filter: hue-rotate(180deg);
    opacity: 1;
  }
  100% {
    opacity: 0;
    display: none;
  }
}

Animacja spin-and-delete to animacja zakończenia. Najpierw karta będzie się obracać wokół osi y, a następnie będzie przechodzić przez różne odcienie. Następnie w 80% na osi czasu jej przezroczystość będzie się zmieniać od 1 do 0. W końcu karta zmienia się z display: block na display: none.

W przypadku tych animacji wyjścia zamiast stosowania ich bezpośrednio do elementu możesz skonfigurować dla nich odpowiedni przełącznik. Możesz to zrobić na przykład, dołączając detektor zdarzeń do przycisku, który uruchamia klasę, aby zastosować animację.

.spin-out {
   animation: spin-and-delete 1s ease-in forwards;
}
document.querySelector('.delete-btn').addEventListener('click', () => {
 document.querySelector('.card').classList.add('spin-out');
})

W przykładzie powyżej stan końcowy to display:none. W wielu przypadkach warto usunąć węzeł DOM z czasem oczekiwania, aby najpierw zakończyła się animacja.

Przechodzenie między poszczególnymi animacjami

W przeciwieństwie do animacji właściwości dyskretnych za pomocą klatek kluczowych, aby przekształcać właściwości dyskretne, musisz użyć allow-discrete trybu zachowania przejścia.

Właściwość transition-behavior

Tryb allow-discrete umożliwia przejścia dyskretne i jest wartością właściwości transition-behavior. transition-behavior może przyjmować 2 wartości: normalallow-discrete.

.card {
  transition: opacity 0.25s, display 0.25s;
  transition-behavior: allow-discrete; /* Note: be sure to write this after the shorthand */
}

.card.fade-out {
  opacity: 0;
  display: none;
}
Uwaga: ten pokaz przejścia zawiera inną technikę niż pierwszy pokaz animacji, ale wizualnie wygląda podobnie.

Skrót transition również ustawia tę wartość, więc możesz pominąć tę usługę i zamiast niej użyć słowa kluczowego allow-discrete na końcu skrótu transition dla każdego przejścia.

.card {
  transition: opacity 0.5s, display 0.5s allow-discrete;
}

.card.fade-out {
  opacity: 0;
  display: none;
}

Jeśli animujesz kilka oddzielnych właściwości, musisz dodać allow-discrete po każdej z nich. Na przykład:

.card {
  transition: opacity 0.5s, display 0.5s allow-discrete, overlay 0.5s allow-discrete;
}

.card.fade-out {
  opacity: 0;
  display: none;
}

Reguła @starting-style dotycząca animacji wejścia

Do tej pory omawialiśmy animacje wyjścia, ale aby utworzyć animacje wejścia, musisz użyć reguły @starting-style.

Użyj @starting-style, aby zastosować styl, który przeglądarka może sprawdzić, zanim element zostanie otwarty na stronie. To stan „przed otwarciem” (gdzie rozpoczyna się animacja).

/*  0. IS-OPEN STATE   */
/*  The state at which the element is open + transition logic */
.item {
  height: 3rem;
  display: grid;
  overflow: hidden;
  transition: opacity 0.5s, transform 0.5s, height 0.5s, display 0.5s allow-discrete;
}

/*  1. BEFORE-OPEN STATE   */
/*  Starting point for the transition */
@starting-style {
  .item {
    opacity: 0;
    height: 0;
  }
}

/*  2. EXITING STATE   */
/*  While it is deleting, before DOM removal in JS, apply this
    transformation for height, opacity, and a transform which
    skews the element and moves it to the left before setting
    it to display: none */
.is-deleting {
  opacity: 0;
  height: 0;
  display: none;
  transform: skewX(50deg) translateX(-25vw);
}

Teraz masz stan wejścia i wyjścia dla tych elementów listy TODO:

Animowanie elementów do i z poziomu najwyższej warstwy

Aby animować elementy do i z warstwy najwyższej, określ @starting-style w stanie „otwarte”, aby poinformować przeglądarkę, skąd ma się rozpocząć animacja. W przypadku okna stan otwarty jest definiowany za pomocą atrybutu [open]. W przypadku wyskakującego okienka użyj pseudoklasy :popover-open.

Prosty przykład okna dialogowego może wyglądać tak:

/*   0. IS-OPEN STATE   */
dialog[open] {
  translate: 0 0;
}

/*   1. BEFORE-OPEN STATE   */
@starting-style {
  dialog[open] {
    translate: 0 100vh;
  }
}

/*   2. EXIT STATE   */
dialog {
  transition: translate 0.7s ease-out, overlay 0.7s ease-out allow-discrete, display 0.7s ease-out allow-discrete;
  translate: 0 100vh;
}

W następnym przykładzie efekty wejścia i wyjścia są różne. Wchodzenie: animacja od dołu do góry widocznego obszaru, a wychodzenie – od góry do dołu. Jest ona też napisana za pomocą zagnieżdżonego kodu CSS, co zapewnia lepszą wizualizację.

Podczas animowania wyskakującego okienka użyj pseudoklasy :popover-open zamiast atrybutu open używanego wcześniej.

.settings-popover {
  &:popover-open {
    /*  0. IS-OPEN STATE  */
    /*  state when popover is open, BOTH:
        what we're transitioning *in* to 
        and transitioning *out* from */
    transform: translateY(0);
    opacity: 1;

    /*  1. BEFORE-OPEN STATE  */
    /*  Initial state for what we're animating *in* from, 
        in this case: goes from lower (y + 20px) to center  */
    @starting-style {
      transform: translateY(20px);
      opacity: 0;
    }
  }
  
  /*  2. EXIT STATE  */
  /*  Initial state for what we're animating *out* to , 
      in this case: goes from center to (y - 50px) higher */
  transform: translateY(-50px);
  opacity: 0;
  
  /*  Enumerate transitioning properties, 
      including display and allow-discrete mode */
  transition: transform 0.5s, opacity 0.5s, display 0.5s allow-discrete;
}

overlay miejsce zakwaterowania

Aby zniknął element popover lub dialog z najwyższej warstwy, dodaj właściwość overlay do listy przejść. popover i dialog uciekają z klipów i przekształceń przodków, a także umieszczają zawartość w górnej warstwie. Jeśli nie wybierzesz opcji overlay, element natychmiast wróci do stanu ucięcia, przekształcenia i przykrycia, a Ty nie zobaczysz przejścia.

[open] {
  transition: opacity 1s, display 1s allow-discrete;
}

Zamiast tego dodaj overlay do przejścia lub animacji, aby animować overlay wraz z resztą funkcji, i upewnij się, że pozostaje on na najwyższej warstwie podczas animacji. Dzięki temu będzie wyglądać znacznie płynniej.

[open] {
  transition: opacity 1s, display 1s allow-discrete, overlay 1s allow-discrete;
}

Dodatkowo, gdy masz otwarte w warstwie górnej wiele elementów, nakładka pomaga kontrolować płynne przejście do warstwy górnej i z niej. Różnicę możesz zobaczyć na tym prostym przykładzie. Jeśli nie zastosujesz overlay do drugiego wyskakującego okienka podczas przechodzenia do niego, najpierw wyjdzie ono z górnej warstwy, przeskakując za inne wyskakujące okienko, zanim rozpocznie się przejście. Nie jest to zbyt płynny efekt.

Uwaga na temat przejścia między widokami

Jeśli wprowadzasz zmiany w DOM, np. dodajesz i usuwasz elementy z DOM, innym świetnym rozwiązaniem na płynne animacje są przejścia między widokami. Oto 2 przykłady z powyżej, które zostały utworzone za pomocą przejść między widokami.

W tym pierwszym pokazie zamiast konfigurowania @starting-style i innych przekształceń CSS przejścia będą obsługiwane przez przejścia widoku. Przejście między widokami jest konfigurowane w ten sposób:

Najpierw w CSS nadaj każdej karcie osobny identyfikator view-transition-name.

.card-1 {
  view-transition-name: card-1;
}

.card-2 {
  view-transition-name: card-2;
}

/* etc. */

Następnie w JavaScript owiń mutację DOM (w tym przypadku usuwanie karty) w ramy przejścia widoku.

deleteBtn.addEventListener('click', () => {
  // Check for browser support
  if (document.startViewTransition) {
    document.startViewTransition(() => {
      // DOM mutation
      card.remove();
    });
  } 
  // Alternative if no browser support
  else {
    card.remove();
  }
})

Teraz przeglądarka może zająć się wygaszaniem i przekształceniem każdej karty w nowej pozycji.

Innym przykładem, w którym może się to przydać, jest dodawanie i usuwanie elementów listy. W takim przypadku musisz pamiętać, aby dodać unikalny identyfikator view-transition-name do każdej utworzonej karty.

Podsumowanie

Te nowe funkcje platformy przybliżają nas do płynnych animacji otwierania i zamykania na platformie internetowej. Aby dowiedzieć się więcej, kliknij te linki: