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

Ruch to podstawowy element wszystkich usług cyfrowych, który prowadzi użytkownika od jednej interakcji do drugiej. Jednak jest kilka luk w zakresie płynnych animacji na platformie internetowej. Obejmują one możliwość łatwego animowania animacji wejścia i wyjścia oraz płynne animowanie do i z górnej warstwy w przypadku elementów, które można zamknąć, takich jak okna czy wyskakujące okienka.

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

Te 4 nowe funkcje:

  • Możliwość animowania elementów display i content-visibility na osi czasu klatki kluczowej (wersja Chrome 116).
  • Właściwość transition-behavior ze słowem kluczowym allow-discrete, która umożliwia przełączanie odrębnych właściwości, np. display (od Chrome 117).
  • Reguła @starting-style animująca efekty wejścia z poziomu display: none do warstwy najwyższego poziomu (od Chrome 117).
  • Właściwość overlay do kontrolowania działania górnej warstwy podczas animacji (wersja Chrome 117).

Wyświetlaj animacje w klatkach kluczowych

W Chrome 116 możesz używać w regułach klatek kluczowych elementów display i content-visibility. Zostaną one zastępowane w momencie wystąpienia klatki kluczowej. Nie są wymagane żadne nowe wartości, które to potwierdzają:

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

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

W poprzednim przykładzie animowano przezroczystość na 0 w czasie trwania wynoszącym 0,5 s, a następnie ustawiano brak. Dodatkowo słowo kluczowe forwards powoduje, że animacja pozostaje w końcowym stanie – element, do którego zostało zastosowane, ma zawsze display: none i opacity: 0.

To prosty przykład, który imituje działanie przejścia (zobacz demonstrację w sekcji dotyczącej przenoszenia). Przejścia nie są jednak w stanie utworzyć bardziej złożonych animacji, jak w tym przykładzie:

.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 wyjścia. Najpierw karta obróci się wokół osi Y, potem obróci odcień, a potem w czasie 80% na osi czasu zmieni przezroczystość z 1 na 0. Na koniec następuje zmiana karty z display: block na display: none.

Zamiast stosować je bezpośrednio do elementu, możesz skonfigurować regułę uruchamiającą animacje. Jeśli na przykład dołączysz detektor zdarzeń do przycisku, który wyzwala klasę w celu zastosowania animacji, w ten sposób:

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

Stan końcowy w powyższym przykładzie to display:none. W wielu przypadkach warto pójść o krok dalej i usunąć węzeł DOM z ustawionym limitem czasu, by umożliwić zakończenie animacji jako pierwsze.

Przechodzenie między dyskretnymi animacjami

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

Właściwość transition-behavior

Tryb allow-discrete umożliwia dyskretne przejścia. Wartość właściwości transition-behavior jest wymagana. Funkcja transition-behavior akceptuje 2 wartości: normal i allow-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: ta wersja demonstracyjna przejścia przedstawia inną technikę niż pierwsza animacja, ale wygląda podobnie.

Skrót transition również ustawia tę wartość, więc możesz pominąć tę właściwość i zamiast tego 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 wiele odrębnych właściwości, musisz dodać parametr allow-discrete po każdej właściwości, którą chcesz animować. 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 wpisów

Do tej pory w tym artykule omówiliśmy animacje wyjścia. Aby utworzyć taką animację, musisz użyć reguły @starting-style.

Użyj @starting-style, aby zastosować styl, który przeglądarka może wyszukać, zanim element zostanie otwarty na stronie. Jest to stan „przed otwarciem” (z którego użytkownik jest animowany).

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

/*  1. 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;
}

/*  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);
}

Masz teraz stan wejścia i wyjścia dla następujących pozycji na liście zadań do wykonania:

Animowanie elementów z górnej warstwy i z niej

Aby animować elementy z górnej warstwy, określ @starting-style w stanie „otwarty”, aby poinformować przeglądarkę, skąd ma się animować element. 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. BEFORE-OPEN STATE   */
@starting-style {
  dialog[open] {
    translate: 0 100vh;
  }
}

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

/*   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. Aby ją uruchomić, animuj obszar od dołu widocznego obszaru, zamknij efekt u góry tego obszaru. Kod ten jest też napisany za pomocą zagnieżdżonego kodu CSS, który zapewnia pełniejsze wrażenia wizualne.

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

.settings-popover {
  &:popover-open {
    /*  0. 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;
    }
    
    /*  1. IS-OPEN STATE  */
    /*  state when popover is open, BOTH:
        what we're transitioning *in* to 
        and transitioning *out* from */
    transform: translateY(0);
    opacity: 1;
  }
  
  /*  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 zanikać popover lub dialog z górnej warstwy, dodaj do listy przejść właściwość overlay. popover i dialog pozwalają użyć klipów i przekształceń elementów nadrzędnych ucieczki, a także umieszczać treść na górze warstwy. Jeśli nie wybierzesz przejścia overlay, element zostanie natychmiast przycięty, przekształcony i zasłonięty. Przejście nie będzie widoczne.

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

Zamiast tego dodaj element overlay w przejściu lub animacji, aby animować element overlay wraz z pozostałymi funkcjami i upewnić się, że pozostanie on na górze warstwy podczas animacji. Będzie to wyglądało znacznie płynniej.

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

Dodatkowo, jeśli w górnej warstwie jest otwartych wiele elementów, nakładka pomaga kontrolować płynne przejście do niej i z niej. Różnicę można zaobserwować w tym prostym przykładzie. Jeśli nie zastosujesz elementu overlay do drugiego wyskakującego okienka podczas przenoszenia, zostanie on najpierw wysunięty z górnej warstwy, przeskoczony przez drugie okienko, zanim rozpocznie się przejście. Nie jest to zbyt płynny efekt.

Uwaga na temat przechodzenia między widokami

Jeśli wprowadzasz zmiany DOM, np. dodajesz elementy do DOM lub je z niego usuwasz, innym świetnym rozwiązaniem, które zapewnia płynne animacje, są przejścia widoku. Oto 2 powyższe przykłady utworzonych z wykorzystaniem przejść między widokami.

W tej pierwszej wersji demonstracyjnej przejście będzie działać zamiast @starting-style i innych przekształceń CSS. Przejście widoku wygląda w ten sposób:

Najpierw w usłudze porównywania cen nadaj każdej karcie osobny atrybut view-transition-name.

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

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

/* etc. */

Następnie w języku JavaScript umieść mutację DOM (w tym przypadku usuń kartę) w przejściu 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 dostosować zanikanie i zmienianie wyglądu każdej karty do nowego położenia.

Innym przykładem tej przydatnej funkcji jest demonstracja dodawania/usuwania elementów listy. W takim przypadku musisz dodać unikalny view-transition-name do każdej utworzonej karty.

Podsumowanie

Te nowe funkcje platformy przybliżają nas o krok do płynnego wyświetlania animacji wstępu i zakończenia wyświetlania na platformie internetowej. Aby dowiedzieć się więcej, skorzystaj z tych linków: