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

Ruch jest podstawą każdego cyfrowego doświadczenia i pokazuje użytkownikowi, jak przejść z jednego elementu interakcji do następnego. Na platformie internetowej występują jednak pewne przerwy w płynnych animacjach. Do funkcji tych należy m.in. możliwość ł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 okienka.

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 oddzielnych 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ższego poziomu (z Chrome 117).
  • Właściwość overlay umożliwia kontrolowanie zachowania najwyższej warstwy podczas animacji (od Chrome 117).

Wyświetlanie animacji w klatkach kluczowych

Od wersji 116 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 to umożliwić:

.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 brak. Dodatkowo słowo kluczowe forwards sprawia, że animacja pozostaje w swoim końcowym stanie, 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ścia). 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 przechodzić przez całą gamę kolorów. Następnie w 80% na osi czasu jej przezroczystość będzie się zmieniać od 1 do 0. Wreszcie karta zmienia się z display: block na display: none.

Zamiast stosować te animacje bezpośrednio do elementu, możesz skonfigurować dla nich odpowiednią regułę. Na przykład możesz dołączyć detektor zdarzeń do przycisku, który uruchamia klasę, aby zastosować animację. W tym celu:

.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 do oddzielnych usług

Właściwości, które animują się dyskretnie, nie powodują domyślnie zdarzeń przejścia. Aby to umożliwić, ustaw tryb zachowania podczas przejścia na allow-discrete.

Właściwość transition-behavior

Właściwość transition-behavior określa, czy w przypadku właściwości dyskretnych mają być uruchamiane przejścia. Może mieć 2 wartości: normalallow-discrete, przy czym wartość początkowa to normal.

  • normal: Przenoszenie nie zostanie rozpoczęte w przypadku właściwości dyskretnych, tylko w przypadku właściwości umożliwiających interpolację.
  • allow-discrete: Przenoszenie rozpocznie się w przypadku właściwości dyskretnych i właściwości, w przypadku których można stosować interpolację.

Aby włączyć tryb allow-discrete w przypadku konkretnej usługi, dodaj ją do skrótu transition:

.card {
  transition: opacity 0.25s, display 0.25s allow-discrete; /* Enable allow-discrete for the display property */
}

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

Podczas przenoszenia wielu oddzielnych właściwości musisz ustawić allow-discrete dla każdej z nich. Na przykład:

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

Aby zdefiniować zachowanie wszystkich właściwości w procesie przejścia, po deklaracji transition należy zadeklarować transition-behavior: allow-discrete. Jest to często najprostsze podejście.

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

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 zaczyna 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. Wprowadzanie: animacja od dołu widocznego obszaru w górę, a następnie odwrotnie. Jest ona też napisana za pomocą osadzonego CSS, co zapewnia lepszą wizualną izolację.

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

.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 na koniec stonować element popover lub dialog z górnej 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 poziomu najwyższego, przeskakując za inne wyskakujące okienko, a dopiero potem 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 skonfigurowane 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: