Moderní tvorba webových aplikací

O webu

CSS @starting-style

Jak animovat elementy při jejich prvním zobrazení pomocí at-pravidla @starting-style.

12 minut

Animace při vstupu elementu do stránky byla dlouho problém. CSS přechody fungovaly jen při změně stavu, ne při prvním vykreslení. Pravidlo @starting-style tento problém řeší.

Problém s animacemi při vstupu

Představte si, že chcete animovat dialog při jeho otevření. S klasickým transition to nefunguje:

dialog {
  opacity: 1;
  transition: opacity 0.3s;
}

dialog:not([open]) {
  opacity: 0;
}

Dialog při otevření neanimuje — prohlížeč ho rovnou vykreslí s opacity: 1. Přechod funguje jen při změně z jednoho stavu do druhého, ne při prvním zobrazení.

Řešení pomocí @starting-style

Pravidlo @starting-style definuje počáteční styl, ze kterého element přechází při prvním vykreslení:

dialog[open] {
  opacity: 1;
  transition: opacity 0.3s;

  @starting-style {
    opacity: 0;
  }
}

Teď prohlížeč ví, že má začít s opacity: 0 a plynule přejít na opacity: 1.

Syntaxe

Existují dva způsoby zápisu — vnořený a samostatný:

Vnořený zápis

.element {
  opacity: 1;
  transform: scale(1);
  transition: all 0.3s;

  @starting-style {
    opacity: 0;
    transform: scale(0.9);
  }
}

Samostatný zápis

.element {
  opacity: 1;
  transform: scale(1);
  transition: all 0.3s;
}

@starting-style {
  .element {
    opacity: 0;
    transform: scale(0.9);
  }
}

Vnořený zápis je přehlednější a udržuje související styly pohromadě.

Ukázka

Animovaný element

Animovaný tooltip

Tooltip, který se plynule objeví při najetí myší:

Animovaný tooltip!

Notifikace / Toast

Notifikace, která přijede ze strany:

Zpráva byla odeslána

Animovaná karta

Karta, která se při zobrazení „rozbalí“:

Animovaná karta

Obsah karty s efektem rozbalení a mírného natočení.

Animovaný seznam

Položky seznamu s postupným zobrazením:

  • První položka
  • Druhá položka
  • Třetí položka
  • Čtvrtá položka

Zpětná animace (exit)

Pravidlo @starting-style definuje jen vstupní stav. Pro animaci při skrytí musíte definovat výstupní stav pomocí selektoru:

.element {
  opacity: 1;
  transform: translateY(0);
  transition: all 0.3s, display 0.3s allow-discrete;
}

/* Vstupní animace */
.element.is-visible {
  display: block;

  @starting-style {
    opacity: 0;
    transform: translateY(-20px);
  }
}

/* Výstupní animace */
.element:not(.is-visible) {
  opacity: 0;
  transform: translateY(20px);
}

Prohlížeč animuje přechod do stavu :not(.is-visible). Vlastnost display se přepne na konci animace, takže element zůstane viditelný po celou dobu přechodu.

Animace vlastnosti display

Vlastnost display není běžně animovatelná. S @starting-style a klíčovým slovem allow-discrete to ale jde:

.tooltip {
  display: none;
  opacity: 0;
  transition:
    opacity 0.3s,
    display 0.3s allow-discrete;
}

.tooltip.is-visible {
  display: block;
  opacity: 1;

  @starting-style {
    opacity: 0;
  }
}

Klíčové slovo allow-discrete říká prohlížeči, že má animovat i diskrétní vlastnosti jako display. Prohlížeč přepne display na začátku přechodu (při zobrazení) nebo na konci (při skrytí).

Použití s Popover API

Kombinace @starting-style s Popover API umožňuje animované vyskakovací prvky bez JavaScriptu:

[popover] {
  opacity: 1;
  transform: scale(1);
  transition:
    opacity 0.2s,
    transform 0.2s,
    display 0.2s allow-discrete,
    overlay 0.2s allow-discrete;

  @starting-style {
    opacity: 0;
    transform: scale(0.95);
  }
}

[popover]:not(:popover-open) {
  opacity: 0;
  transform: scale(0.95);
}

Vlastnost overlay zajišťuje, že element zůstane v top layer po dobu animace při zavírání.

Animovaný popover

Zavře se kliknutím mimo nebo na Escape.

Animovaný dialog

Animovaný modální dialog

Jak se to řešilo dříve

Před @starting-style existovalo několik workaroundů:

1. @keyframes animace

Nejběžnější řešení — definovat animaci s explicitním počátkem:

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(-20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.element {
  animation: fadeIn 0.3s ease-out;
}

Nevýhody:

  • Animace běží vždy, i když element už byl viditelný
  • Pro exit animaci potřebujete další keyframes a JavaScript
  • Složitější správa stavů

2. JavaScript s requestAnimationFrame

Přidání třídy až po vykreslení:

element.style.display = 'block';
requestAnimationFrame(() => {
  requestAnimationFrame(() => {
    element.classList.add('is-visible');
  });
});

Dvojité requestAnimationFrame zajistí, že prohlížeč stihne vykreslit počáteční stav před přidáním třídy.

3. setTimeout hack

element.style.display = 'block';
setTimeout(() => {
  element.classList.add('is-visible');
}, 10);

Nevýhody:

  • Nespolehlivé — závisí na rychlosti prohlížeče
  • Může způsobit probliknutí
  • Není deklarativní

Proč je @starting-style lepší

  • Čistě v CSS — žádný JavaScript
  • Deklarativní — jasně říká „toto je počáteční stav“
  • Spolehlivé — prohlížeč garantuje správné pořadí
  • Funguje s display — díky allow-discrete

Rozdíl oproti @keyframes

Pravidlo @starting-style není náhrada za @keyframes. Každý přístup má své využití:

@starting-style @keyframes
Použití Vstupní přechody Komplexní animace
Kroky Jeden (počátek → konec) Libovolný počet
Opakování Ne Ano
Výstupní animace Přes :not() selektor Přes animation-direction

Pro jednoduché přechody při zobrazení je @starting-style čistší řešení. Pro složitější animace s více kroky použijte @keyframes.

Podpora v prohlížečích

Pravidlo @starting-style podporují:

  • Chrome od verze 117
  • Edge od verze 117
  • Safari od verze 17.5
  • Firefox od verze 129

Pro starší prohlížeče element jednoduše nebude animovaný — zobrazí se okamžitě. Přijatelná degradace.

Tipy

  • Používejte vnořený zápis — je přehlednější a souvisí s CSS Nesting
  • Nezapomeňte na allow-discrete při animaci display
  • Přidejte overlay pro elementy v top layer (dialogy, popovers)
  • Definujte i výstupní stav pomocí :not([open]) nebo podobného selektoru

Odkazy

Související články

CSS pseudo element ::marker

CSS pseudo element ::marker umožňuje stylovat odrážky seznamů

4 minuty

Zobrazení dlouhé URL

Jak zobrazit dlouhé URL v aplikaci, aby nerozbila layout.

6 minut

Převod písmen na VELKÁ a malá

Převedení textu na velká nebo malá písmena.

12 minut

Možnosti stylování <iframe>

Co lze a nelze u <iframe> ovlivnit pomocí CSS a jak na změnu textu nebo barev.

10 minut

Novinky e-mailem

Když budu mít něco opravdu zajímavého, můžu vám to poslat e-mailem

Přidej se k 500+ čtenářům
Jen kvalitní obsah
Žádný spam

Web jecas.cz píše Bohumil Jahoda, kontakt
Seznam všech článků
2013–2025