Miért ugrik az animáció első képkockája?
A mozgás-kód hibátlan volt, a doboz mégis ugrott egy nagyot az induláskor, és utána mozgott csak szépen. Az ok két lépéssel arrébb állt.
A keresőpanel alján egy lábsor mondja meg, hány találat van, és azt is, ha nincs egy sem. Ez a sor nulla magasságról nyílik ki, JavaScriptből: egy követő minden képkockán ráír egy magasságot, és a szám végig azon az íven halad, amin haladnia kell.
A képernyőn viszont ugrott. Az első képkockán majdnem teljes magasságra állt, és onnantól mozgott finoman — ez rosszabb, mint ha végig ugrálna, mert a mozgás második fele tökéletesen sima, tehát a mozgás-kód jónak látszik.
Mit mutat a mérés, ha a kód jónak látszik?
A mozgás-kód olvasása itt nem visz előre, mert nincs benne hiba. Ami előrevisz: képkockánként kiírni két számot egymás mellé — amit a szkript beállít, és amit a doboz valójában felvesz.
$ ~/.kk-venv/bin/python tipp-nyom.py
116,0ms h= 20,19 lepes= +19,19 style.height= 1px
184,0ms h= 20,30 lepes= +0,11 style.height= 20,3px
201,0ms h= 20,50 lepes= +0,20 style.height= 20,5px
217,0ms h= 20,69 lepes= +0,19 style.height= 20,7px
234,0ms h= 21,00 lepes= +0,31 style.height= 21px
A két szám nem egyezett. A szkript egy képpontra állította a magasságot, a doboz mégis 20,19 képpontot foglalt. Innentől a kérdés az, mi nem engedi a dobozt egy képpontnál kisebbre.
Mi tesz padlót a doboz alá?
A 20,19 kijön papíron: 9,6 meg 9,6 meg 1. Padding fent, padding lent, egy
képpont keret. A box-sizing: border-box azt jelenti, hogy a
megadott magasság a keretet és a paddingot is magában foglalja — a padding
viszont nem nyomható össze. A padding padlót tesz a doboz alá,
és a magasság-animáció addig nem látszik, amíg a padló fölé nem ér.
- a rövidítéssela padló — padding és keret — azonnal a végértéken
- a két longhanddala padló együtt emelkedik
- a rövidítésselamit a szkript ráír, az a padló alatt marad — ugrás
- a két longhanddala doboz végig követi
a szkript mindkét esetben ugyanazt a magasságot írja rá
Miért állt a padding már a végértéken?
Mert a paddingnak is animálódnia kellett volna, csak nem tette. A
stíluslapban egyetlen átmenet-lista állt, három tulajdonsággal: az
opacity mozgott, a border-color mozgott, a
padding-block pedig egyetlen képkockán a végértékre
ugrott. Ez az a pont, ahol a padló azonnal a helyére állt,
miközben a magasság még alulról jött.
Az ok motorfüggő. A WebKit a padding-block
rövidítésre nem indít átmenetet, a
padding-block-start és a padding-block-end
longhandra viszont igen. Chromiumban a rövidítés is megy — vagyis az
előnézeti böngészőben az egész hibátlanul nézett ki.
$ ~/.kk-venv/bin/python pad-teszt.py
transition: padding-block → 20px UGROTT
transition: padding-block-start → 1px animál
transition: padding-top → 1.1px animál
transition: opacity → 0.056667 animál
A mérésnek van egy csapdája. A beállítás után rögtön olvasva a computed érték már a végértéket adja, mert az átmenet csak a következő stílusszámoláskor indul el. Ebből úgy tűnik, mintha semmilyen tulajdonság nem animálódna — két képkockával később kell olvasni.
Mi lett a javítás?
Egy sor helyett kettő, ugyanazzal a tempóval és lágyítással.
transition: opacity var(--t-felulet) var(--ease-oda-vissza),
padding-block-start var(--t-felulet) var(--ease-oda-vissza),
padding-block-end var(--t-felulet) var(--ease-oda-vissza),
border-color var(--t-felulet) var(--ease-oda-vissza);
Ezzel a padding a magassággal együtt nő. A padló is emelkedik, csak lassabban, mint amilyen gyorsan a magasság távolodik tőle: a teljes padding és keret 20,19 képpont, a teljes magasság 36,8 — a doboz így soha nem éri utol a saját padlóját. Mérve az első lépés 19,2 képpontról 1,5-re csökkent, a küszöb 3,5.
Mit lehet ebből általánosítani?
Az elsőt a tünet és az ok távolsága adja. Ha egy animált méret
az elején ugrik, utána szép, akkor jellemzően nem a
mozgással van baj: valami padlót tesz a doboz alá, és a mozgás első
szakasza a padló alatt zajlik, láthatatlanul. Padlót tesz a padding, a
keret, a min-height, a sor magassága, és flexben az elem
tartalmi minimuma.
A második a rövidítés. Egy átmenet-listában a rövidítés-tulajdonság
kockázat: ha a motor nem ismeri fel animálhatónak, akkor nem hibázik,
hanem ugrik — és az ugrás nem ott jelentkezik, ahol a
rövidítés áll. Ugyanez a gyanú áll a padding, a
margin, az inset és a
padding-inline esetére.
Ezen a szabályon egy korábbi kör már elcsúszott. Ugyanerre a 20,19
képpontra akkor min-height: 0 került a szabályba, és az a
tünet egy másik megjelenését meg is oldotta — a számot viszont nem, mert a
padló továbbra is ott volt, csak máshonnan.
Ezt a hibát egy ellenőrzés találta meg, ami számot adott — képkockánkénti csúcsot és küszöböt. Arról, hogy mit érdemes gépre bízni egy oldal átnézéséből, a gépi ellenőrzésről szóló darab szól.
Kérdések a témáról
Miért ugrik egy magasság-animáció az első képkockán?
Jellemzően nem a mozgás a hibás, hanem az, hogy valami padlót tesz a doboz alá: a megadott magasság egy darabig a padló alatt van, tehát a doboz nem mozdul, majd amint a magasság a padló fölé ér, a doboz egyszerre ugrik oda. A mozgás második fele ilyenkor tökéletesen sima, ezért látszik a mozgás-kód jónak.
Mi tesz padlót egy doboz alá?
A box-sizing: border-box mellett a megadott magasság a keretet és a paddingot is magában foglalja, a padding viszont nem nyomható össze. Fent és lent 9,6 képpont belső térköz plusz egy képpont keret azt jelenti, hogy a doboz 20,19 képpontnál alacsonyabb nem lehet, akármit ír rá a szkript. Ugyanígy padlót tesz a min-height, a sor magassága, és flexben az elem tartalmi minimuma.
Melyik átmenet-tulajdonságokra érdemes gyanakodni?
A rövidítésekre. A WebKit a padding-block rövidítésre nem indít átmenetet, a padding-block-start és a padding-block-end longhandra igen; Chromiumban a rövidítés is megy, tehát a különbség csak az egyik motoron látszik. Ugyanez a gyanú áll a padding, a margin, az inset és a padding-inline esetére.
Hogyan lehet megmérni, hogy egy átmenet tényleg fut-e?
Két képkockával a változtatás után kell olvasni a computed értéket, nem közvetlenül utána. Az átmenet a következő stílusszámoláskor indul el, tehát a szinkron olvasás még a végértéket adja vissza — abból pedig úgy tűnik, mintha semmilyen tulajdonság nem animálódna.