Mundarija (32)
- Bu darsda
- 1. Nega bu kerak?
- 2. Timeline: animatsiyaning "soati"
- 2.1 Vaqt o'rniga skroll
- 2.2 Ikki xil skroll soati
- 3. scroll(): o'qish progress chizig'i
- 3.1 Birinchi misol
- 3.2 Kod qatorma-qator
- 3.3 scroll() argumentlari
- 4. view(): element sahnaga chiqishi
- 4.1 Paydo bo'luvchi bosqichlar
- 4.2 animation-range: skrollning qaysi bo'lagida
- 5. Nomli timeline
- 5.1 Qachon kerak
- 5.2 view-timeline
- 6. Harakatni kamaytirish va zaxira
- 6.1 Baseline holati
- 6.2 Xavfsiz andoza
- 6.3 Parallaks — ehtiyotkorlik bilan
- 7. Ko'p uchraydigan xatolar
- 7.1 animation qisqa yozuvi keyin yozilgan
- 7.2 Skroll konteyner topilmadi
- 7.3 view() elementi overflow: hidden ichida
- 7.4 Kontent zaxirasiz yashirin qoldi
- 8. Mashqlar
- 1-mashq (oson): fon rangi skrollga bog'liq
- 2-mashq (o'rta): bosqichlar chapdan kirsin
- 3-mashq (qiyin): kirish va chiqish
- 4-mashq: Portfolio qadami — loyiha kartalari "sahnaga chiqsin"
- 9. Real ishda
- Xulosa
- Manbalar
CSS scroll-driven animatsiyalar: animation-timeline, scroll() va view()
Qisqacha: Scroll-driven animatsiyada
@keyframessoniyalar bo'yicha emas, skroll bo'yicha o'ynaydi: skroll 0% da — animatsiya boshida, 100% da — oxirida. Xususiyatanimation-timeline: scroll()animatsiyani skroll konteyner holatiga,view()esa elementning ekranda ko'rinish darajasiga bog'laydi. Bu imkoniyat hali Baseline emas — Firefox'da yo'q, shuning uchun uni@supports (animation-timeline: view())ichida, bezak sifatida yozing.
Bu darsda
- Vaqt va skroll "timeline"lari farqini tushuntira olasiz.
scroll()bilan o'qish progress chizig'ini,view()bilan paydo bo'luvchi kartalarni JavaScript'siz yasaysiz.animation-rangebilan animatsiya skrollning qaysi qismida o'ynashini belgilaysiz.- Nomli timeline (
scroll-timeline,view-timeline,timeline-scope) nima uchun kerakligini bilasiz. @supportsvaprefers-reduced-motionbilan xavfsiz zaxira yozasiz.
Oldin bilishingiz kerak: @keyframes va animation, Skroll xulqi va scroll-snap, Brauzer mosligi va @supports, prefers-reduced-motion.
1. Nega bu kerak?
O'tgan darsda scroll snap bilan skrollni "magnitli" qildik. Endi skrollga animatsiya bog'laymiz.
«Bahor» blogida oshpaz Rustam akaning uzun maqolasi bor: "Oshni qanday damlash kerak". U ikki narsani so'radi:
- Sahifa tepasida ingichka chiziq bo'lsin — o'quvchi maqolaning qancha qismini o'qiganini ko'rsin. Xuddi yuklab olish ko'rsatkichi kabi.
- Retsept bosqichlari sahifaga "suzib" kirsin — o'quvchi skroll qilganda har bosqich asta paydo bo'lsin.
Bir necha yil oldin buning yagona yo'li JavaScript edi. Skroll har o'zgarganda kod ishga tushardi, foizni hisoblab, CSS o'zgaruvchisiga yozardi (CSS o'zgaruvchilari 2 darsidagi usul). Paydo bo'lish uchun esa IntersectionObserver kerak edi — "element ekranga kirdimi?" deb kuzatadigan JavaScript vositasi (uni keyinroq o'rganamiz, hozir bilish shart emas). Kod ko'p, telefonda sekinlashish xavfi bor.
Bugun buni bir necha qator CSS qiladi. Kalit so'z — timeline (vaqt chizig'i).
2. Timeline: animatsiyaning "soati"
2.1 Vaqt o'rniga skroll
@keyframes darsida har animatsiyaning bitta "soati" bor edi — vaqt. animation-duration: 2s degani: 0 soniyada from, 2 soniyada to. Bu soat hujjat timeline'i (document timeline) deyiladi va u o'z-o'zidan yuradi.
Scroll-driven animatsiya (skrollga bog'langan animatsiya) soatni almashtiradi. Endi animatsiya o'rnini soniyalar emas, skroll o'rni belgilaydi:
flowchart LR
subgraph V["Oddiy animatsiya"]
direction TB
V1["0 s"] --> V2["1 s"] --> V3["2 s"]
end
subgraph S["Scroll-driven"]
direction TB
S1["Skroll 0%"] --> S2["Skroll 50%"] --> S3["Skroll 100%"]
end
V3 --> K["@keyframes: from → to"]
S3 --> KNimaga qarang: @keyframes bir xil qoladi, faqat unga "vaqt"ni kim berishi o'zgaradi. Foydalanuvchi skrollni to'xtatsa, animatsiya ham to'xtaydi. Orqaga qaytarsa — animatsiya ham orqaga o'ynaydi. Xuddi video pleyerdagi slayderni barmoq bilan surish kabi: kadrni siz boshqarasiz, soat emas.
2.2 Ikki xil skroll soati
| Funksiya | Nimani o'lchaydi | Qachon |
|---|---|---|
scroll() |
Konteyner qancha skroll qilingani | Progress chizig'i, fon o'zgarishi |
view() |
Element konteyner oynasida qanchalik ko'ringani | Paydo bo'lish, parallaks |
Birinchisi — butun sahifaning holati, ikkinchisi — bitta elementning "sahna"dagi holati.
3. scroll(): o'qish progress chizig'i
3.1 Birinchi misol
<style>
.maqola {
height: 240px;
overflow-y: auto;
border: 2px solid #2f6b3a;
background-color: #fffaf0;
font-family: system-ui, sans-serif;
}
.progress {
position: sticky;
top: 0;
height: 6px;
background-color: #b4461a;
transform-origin: left;
animation: tolish linear both;
animation-timeline: scroll();
}
@keyframes tolish {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
.maqola > :not(.progress) {
padding-inline: 16px;
}
</style>
<article class="maqola" tabindex="0" aria-label="Maqola">
<div class="progress"></div>
<h2>Oshni qanday damlash kerak</h2>
<p>1. Qozonni qizdirib, yog'ni tutunga qadar qizdiring.</p>
<p>2. Go'shtni qo'shib, qizarguncha qovuring.</p>
<p>3. Piyoz va sabzini somon qilib to'g'rab soling.</p>
<p>4. Zirvak 20 daqiqa qaynasin, tuz va ziravor.</p>
<p>5. Guruchni yuvib, tekis qilib soling.</p>
<p>6. Suv guruchdan bir barmoq yuqori bo'lsin.</p>
<p>7. Suv singgach, guruchni tepa qilib yig'ing.</p>
<p>8. Qopqog'ini yopib, 20 daqiqa damlang.</p>
<p>Yoqimli ishtaha! Rustam aka, «Bahor».</p>
</article>Nimaga qarang: ramka ichida pastga skroll qiling — tepadagi qizg'ish chiziq chapdan o'ngga o'sadi. Yarmiga kelganda chiziq ham yarmida. Eng pastda — to'liq. Tepaga qaytsangiz, chiziq qisqaradi. Bitta ham JavaScript qatori yo'q.
Chrome'da o'lchadik: skroll 25% da transform — scaleX(0.25) atrofida, 50% da — aynan 0.5, 100% da — 1.
3.2 Kod qatorma-qator
animation: tolish linear both;— odatdagi animatsiya, lekin davomiylik yo'q. Scroll-driven animatsiyada soniya ma'nosiz: davomiylikni skroll uzunligi belgilaydi. Yozilmasa,animation-durationning qiymatiautobo'ladi.linear— skroll bilan to'g'ri proporsiya: 10% skroll → 10% chiziq.easebersangiz, chiziq boshida sekin, o'rtada tez o'sardi.both— skroll boshidan oldin va oxiridan keyin ham chetki holatlar saqlansin (@keyframesdarsidagianimation-fill-mode).animation-timeline: scroll();— "soat — eng yaqin skroll konteyner".transform: scaleX()—widtho'rniga. Rendering pipeline darsidan eslang:transformlayout'ni qayta hisoblatmaydi. Chrome bunday scroll-driven animatsiyani to'g'ridan-to'g'ri kompozitorda, sahifaning boshqa ishlaridan alohida o'ynata oladi — sahifa og'ir bo'lsa ham chiziq silliq qoladi.
3.3 scroll() argumentlari
scroll() ikkita ixtiyoriy argument oladi: qaysi konteyner va qaysi o'q.
| Yozuv | Ma'nosi |
|---|---|
scroll() |
Eng yaqin skroll qiluvchi ota, vertikal (sukut) |
scroll(root) |
Butun sahifa skrolli (html) |
scroll(self) |
Elementning o'z skrolli |
scroll(nearest x) |
Eng yaqin ota, gorizontal o'q |
Haqiqiy blog sahifasida chiziq butun sahifa skrolliga bog'lanadi: animation-timeline: scroll(root); va position: fixed. Natija oynasida biz ichki ramka ishlatdik — oyna balandligi o'zgaruvchan, shuning uchun sahifa skrolli ishonchli emas.
Diqqat:
animationqisqa yozuvianimation-timelineni ham o'z ichiga oladi va uniautoga qaytaradi (CSS nima darsidagi qisqa yozuv tuzog'i). Shuning uchunanimation-timelinedoimanimationdan keyin yozilsin. Teskari tartibda Chrome'da tekshirdik:animation-timelineautobo'lib qoldi, chiziq skrollga qaramay birdan to'liq chizildi.
Tekshirib ko'ring: Progress chizig'ida
animation: tolish 3s linear both;yozildi — davomiylik 3 soniya. Nima bo'ladi?
Javob
Hech narsa buzilmaydi, agar animation-timeline: scroll() undan keyin yozilgan bo'lsa. Scroll-driven animatsiyada vaqt birligidagi davomiylik e'tiborga olinmaydi — "vaqt"ni skroll beradi. Lekin bu kodni o'qigan odam chalkashadi. Shuning uchun davomiylik yozilmaydi yoki auto qoldiriladi.
4. view(): element sahnaga chiqishi
4.1 Paydo bo'luvchi bosqichlar
view() butun konteynerga emas, elementning o'ziga qaraydi: u konteyner oynasiga (scrollport) kirib kelyaptimi, o'rtadami, chiqib ketyaptimi.
<style>
.retsept {
height: 240px;
overflow-y: auto;
padding-inline: 16px;
border: 2px solid #2f6b3a;
font-family: system-ui, sans-serif;
}
.bosqich {
margin-block: 48px;
padding: 16px;
border-radius: 12px;
background-color: #e8f1ec;
animation: paydo linear both;
animation-timeline: view();
animation-range: entry 0% entry 100%;
}
@keyframes paydo {
from { opacity: 0; transform: translateY(24px); }
to { opacity: 1; transform: none; }
}
</style>
<div class="retsept" tabindex="0" aria-label="Retsept">
<p>Pastga skroll qiling.</p>
<div class="bosqich">1. Qozonni qizdiring</div>
<div class="bosqich">2. Go'shtni qovuring</div>
<div class="bosqich">3. Sabzini soling</div>
<div class="bosqich">4. Guruchni soling</div>
<div class="bosqich">5. Damlang</div>
</div>Nimaga qarang: har bosqich ramkaning pastki chetidan kirib kela boshlaganda shaffof va biroz pastda. U to'liq ko'ringan paytda — butunlay aniq va joyida. Orqaga skroll qilsangiz, bosqichlar yana xiralashib pastga tushadi. Ochilgan zahoti birinchi bosqich to'liq ko'rinadi, ikkinchisi pastki chetda endi kirib kelmoqda, qolganlari hali "sahnaga chiqmagan".
4.2 animation-range: skrollning qaysi bo'lagida
view() elementning butun yo'lini o'lchaydi: pastki chetdan kira boshlagan paytdan tepadan butunlay chiqib ketguncha. animation-range shu yo'lning qaysi bo'lagida animatsiya o'ynashini aytadi. Asosiy nomlar:
| Nom | Qaysi bo'lak |
|---|---|
entry |
Element kira boshlaganidan to'liq ko'ringuncha |
exit |
Chiqa boshlaganidan butunlay chiqib ketguncha |
contain |
Element to'liq ko'rinib turgan butun vaqt |
cover |
Butun yo'l: birinchi pikseldan oxirgisigacha (sukut) |
Elementning yo'li va bo'laklari ketma-ket shunday:
flowchart LR
A["Pastdan kira<br/>boshladi"] -->|entry| B["To'liq<br/>ko'rindi"]
B -->|contain| C["Tepadan chiqa<br/>boshladi"]
C -->|exit| D["Butunlay<br/>chiqdi"]Nimaga qarang: strelkalar ustidagi nomlar — yo'lning bo'laklari. cover esa A dan D gacha bo'lgan butun yo'l.
Maslahat: Yuqoridagi retsept natijasida "Tahrirlab ko'rish" ni bosing va
entry 0% entry 100%o'rnigacoveryozing. Endi animatsiya butun yo'lga cho'zildi: ramka o'rtasida bosqich hali yarim shaffof, to'liq aniq bo'lishiga esa tepadan chiqib ketayotganda yetadi. Paydo bo'lish uchunentrynega qulayroq ekani shunda ko'rinadi.
Har nom yonidagi foiz — shu bo'lakning qayeri: entry 0% — kirish boshlanishi, entry 100% — kirish tugashi. Chrome'da o'lchadik: 200 pikselli oynada 100 pikselli element. Uning yuqori cheti oyna tepasidan 200 pikselda (endigina kirmoqda) — opacity 0; 150 pikselda — 0.5; 100 pikselda (to'liq kirdi) — 1.
Aralashtirish ham mumkin: animation-range: entry 25% cover 50% — "kirishning choragidan boshlab, butun yo'lning yarmigacha".
Tekshirib ko'ring: Bosqich ekrandan tepaga chiqib ketayotganda xiralashishi kerak.
animation-rangeqanday bo'ladi?
Javob
animation-range: exit 0% exit 100%; — chiqish boshlanganidan tugaguncha. @keyframes ham teskari bo'lsin: from { opacity: 1; } va to { opacity: 0; }. Kirish va chiqishni bitta elementda xohlasangiz — ikkita animatsiya, har biriga o'z animation-range i vergul bilan yoziladi.
5. Nomli timeline
5.1 Qachon kerak
scroll() va view() "anonim": ular eng yaqin ota konteynerni o'zlari topadi. Lekin ba'zan animatsiya qilinadigan element skroll konteynerning ichida emas. Masalan, gorizontal lenta ostida "qancha surildi" chizig'i: chiziq lentaning qo'shnisi, bolasi emas.
Bunda timeline'ga nom beriladi:
- Konteynerga:
scroll-timeline: --lenta x;— "mening gorizontal skrollim--lentadeb atalsin". To'liq yozuvi —scroll-timeline-namevascroll-timeline-axis. - Animatsiya qilinadigan elementga:
animation-timeline: --lenta;. - Umumiy otaga:
timeline-scope: --lenta;— "bu nom butun ichki daraxtimga ko'rinsin". Usiz nom faqat konteynerning o'z bolalariga ko'rinadi.
Nom — CSS o'zgaruvchilari kabi -- bilan boshlanadi, lekin o'zgaruvchi emas.
<style>
.blok {
timeline-scope: --lenta;
font-family: system-ui, sans-serif;
}
.lenta {
display: flex;
gap: 12px;
overflow-x: auto;
scroll-timeline: --lenta x;
scroll-snap-type: x mandatory;
}
.taom-karta {
flex: 0 0 70%;
padding: 24px 16px;
border-radius: 12px;
background-color: #e8f1ec;
scroll-snap-align: start;
}
.korsatkich {
height: 4px;
margin-block-start: 8px;
background-color: #2f6b3a;
transform-origin: left;
animation: tolish linear both;
animation-timeline: --lenta;
}
@keyframes tolish {
from { transform: scaleX(0.25); }
to { transform: scaleX(1); }
}
</style>
<div class="blok">
<div class="lenta" tabindex="0" aria-label="Taomlar">
<article class="taom-karta">Osh</article>
<article class="taom-karta">Lag'mon</article>
<article class="taom-karta">Manti</article>
<article class="taom-karta">Ko'k choy</article>
</div>
<div class="korsatkich"></div>
</div>Nimaga qarang: lentani yon tomonga suring — ostidagi yashil chiziq chorakdan to'liqqa qarab o'sadi. Chiziq lentaning ichida emas, yonida. Uni --lenta nomi va otadagi timeline-scope bog'ladi. scaleX(0.25) dan boshlandi: birinchi kartada ham chiziq ko'rinsin, "4 tadan 1" degan ma'noda.
Chrome'da tekshirdik: xuddi shunday chiziqni .blok dan tashqariga qo'ysak, u timeline'ni topmaydi va skrollga javob bermaydi.
5.2 view-timeline
view() ning nomli varianti — view-timeline: --karta; elementning o'ziga yoziladi. Keyin uning ichidagi istalgan bola animation-timeline: --karta bilan otaning ko'rinishiga bog'lanadi. Masalan, karta kirib kelganda uning ichidagi rasm bir oz kattalashadi, sarlavha esa boshqacha harakatlanadi — ikkalasi ham kartaning bitta "sahna" holatiga qaraydi.
6. Harakatni kamaytirish va zaxira
6.1 Baseline holati
Baseline ma'lumotiga ko'ra scroll-driven animatsiyalar hali Baseline emas. Chrome va Edge'da 115-versiyadan, Safari'da 26-versiyadan bor. Firefox'da esa yo'q: MDN'ning brauzerlar jadvalida u faqat sinov (Nightly) versiyasida ko'rsatilgan, oddiy Firefox'da ishlamaydi. timeline-scope va animation-duration: auto ham shu holatda.
Demak, Firefox foydalanuvchisi uchun dars kodimiz nima qiladi? animation-timeline qatorini tushunmaydi va tashlaydi. Qoladi: animation: paydo linear both — davomiyligi yo'q, ya'ni 0 soniya. both sabab element darhol oxirgi holatda: opacity: 1. Kartalar ko'rinadi, faqat animatsiyasiz. Bu omadli holat. Agar davomiylik yozilgan bo'lsa (animation: paydo 1s ...), Firefox'da kartalar sahifa ochilganda bir marta, skrollga qaramay "paydo bo'lib" o'tardi.
6.2 Xavfsiz andoza
Omadga tayanmaymiz. Scroll-driven kodni ikki shartga o'raymiz:
@supports (animation-timeline: view()) {
@media (prefers-reduced-motion: no-preference) {
.bosqich {
animation: paydo linear both;
animation-timeline: view();
animation-range: entry 0% entry 100%;
}
}
}@supports(Brauzer mosligi) — brauzeranimation-timeline: view()ni tushunmasa, blok umuman qo'llanmaydi. Kartalar oddiy, harakatsiz.prefers-reduced-motion(Harakat etikasi) — parallaks va "suzib kirish" vestibulyar muammosi bor odamga eng ko'p zarar beradigan harakatlar qatorida. Harakat o'chirilgan bo'lsa — kartalar joyida.
Progress chizig'i esa o'zi ma'lumot beradi, harakat kamaytirilganda ham foydali. Uni prefers-reduced-motion dan tashqarida qoldirsa bo'ladi — u foydalanuvchi skrolliga ergashadi, o'zi harakatlanmaydi.
Maslahat: Zaxirani tekshirish uchun Firefox shart emas. Chrome'da
@supportsshartiga ataylab xato nom yozing (masalan,animation-timelin) — sahifa Firefox'dagi kabi animatsiyasiz ko'rinadi.
6.3 Parallaks — ehtiyotkorlik bilan
Parallaks — orqa fon oldingi kontentdan sekinroq harakatlanishi, chuqurlik hissini beradi. view() bilan:
@supports (animation-timeline: view()) {
@media (prefers-reduced-motion: no-preference) {
.bosh-rasm img {
animation: suzish linear both;
animation-timeline: view();
}
}
}
@keyframes suzish {
from { transform: translateY(-15%); }
to { transform: translateY(15%); }
}Rasm o'z konteyneri ichida skroll yo'nalishiga qarshi biroz suriladi va sekinroq harakatlanayotgandek ko'rinadi. Konteynerga overflow: hidden bering, aks holda rasm chetidan chiqib ketadi. Parallaksni tejab ishlating: sahifada bitta-ikkita joy yetadi.
7. Ko'p uchraydigan xatolar
7.1 animation qisqa yozuvi keyin yozilgan
.progress {
animation-timeline: scroll();
animation: tolish linear both;
}Qisqa yozuv animation-timeline ni auto ga qaytardi. Tuzatish: avval animation, keyin animation-timeline.
7.2 Skroll konteyner topilmadi
scroll() eng yaqin skroll qiluvchi otani qidiradi. Ota konteynerda overflow: auto yo'q yoki kontent sig'ib turibdi (skroll yo'q) — animatsiya harakatlanmaydi. Tuzatish: DevTools'da konteynerni tekshiring: haqiqatan skroll bormi? Butun sahifa uchun — scroll(root).
7.3 view() elementi overflow: hidden ichida
Karta overflow: hidden li o'ramda turibdi. overflow: hidden ham skroll konteyner yaratadi — view() aynan shuni "eng yaqin" deb oladi va hech qachon o'zgarmaydigan holatni o'lchaydi. Chrome'da tekshirdik: bunday karta skrollga qaramay doim to'liq ko'rinib turdi. Tuzatish: o'ramga overflow: clip bering (Overflow darsi): u kesadi, lekin skroll konteyner yaratmaydi.
7.4 Kontent zaxirasiz yashirin qoldi
@keyframes dagi from { opacity: 0 } ni animatsiyadan tashqariga, oddiy qoidaga ko'chirishdi: .bosqich { opacity: 0 }. Firefox'da animatsiya yo'q — kartalar abadiy ko'rinmas. Tuzatish: boshlang'ich yashirin holat faqat @keyframes ichida yoki @supports ichida bo'lsin.
8. Mashqlar
Mashqlarni kurs/mashqlar/06/ papkasida bajaring.
1-mashq (oson): fon rangi skrollga bog'liq
«Bahor» menyusi 300 pikselli ichki skroll konteynerda. Konteyner foni skroll boshida qaymoq rang (#fffaf0), oxirida och yashil (#e8f1ec) bo'lsin — skroll bilan silliq o'zgarsin.
Ishora: animatsiya konteynerning o'zida — u o'z skrolliga qaraydi: scroll(self).
Yechim
<style>
.menyu-oyna {
height: 200px;
overflow-y: auto;
padding-inline: 16px;
font-family: system-ui, sans-serif;
animation: fon linear both;
animation-timeline: scroll(self);
}
@keyframes fon {
from { background-color: #fffaf0; }
to { background-color: #e8f1ec; }
}
</style>
<div class="menyu-oyna" tabindex="0" aria-label="Menyu">
<p>Osh — 35 000 so'm</p><p>Lag'mon — 28 000 so'm</p>
<p>Manti — 30 000 so'm</p><p>Ko'k choy — 5 000 so'm</p>
<p>Non — 4 000 so'm</p><p>Somsa — 8 000 so'm</p>
<p>Shashlik — 18 000 so'm</p><p>Salat — 12 000 so'm</p>
</div>scroll(self) — "o'zimning skrollim". scroll() yozilsa, brauzer konteynerning otasidagi skrollni qidirardi va bu yerda topmasdi. background-color — arzon xususiyat emas (har kadrda qayta bo'yaladi), lekin kichik konteynerda muammo yo'q.
2-mashq (o'rta): bosqichlar chapdan kirsin
Retsept misolini o'zgartiring:
- Bosqichlar pastdan emas, chapdan kirsin (
translateX(-40px)dan). - Animatsiya kirishning yarmida tugasin.
- Kod faqat qo'llab-quvvatlaydigan brauzerda va harakat kamaytirilmagan holatda ishlasin.
Ishora: «Xavfsiz andoza» bo'limi. entry 0% entry 50%.
Yechim
@keyframes chapdan {
from { opacity: 0; transform: translateX(-40px); }
to { opacity: 1; transform: none; }
}
@supports (animation-timeline: view()) {
@media (prefers-reduced-motion: no-preference) {
.bosqich {
animation: chapdan linear both;
animation-timeline: view();
animation-range: entry 0% entry 50%;
}
}
}@keyframes shartdan tashqarida qolishi mumkin: uni hech kim ishlatmasa, u hech narsaga ta'sir qilmaydi. entry 50% — element yarmigacha kirganda animatsiya tugaydi, keyin to'liq ko'rinadi. Retsept konteyneri ichida bosqichlar chap chetdan 40 piksel tashqarida boshlaydi — konteynerning chap padding i (16px) yetmasa, gorizontal skroll paydo bo'lishi mumkin. Buni oldini olish uchun konteynerga overflow-x: clip qo'shing.
3-mashq (qiyin): kirish va chiqish
Har bosqich kirib kelganda paydo bo'lsin, tepadan chiqib ketayotganda esa xiralashib kichraysin (scale(0.9)). Bitta elementda ikki animatsiya.
Ishora: animation va animation-range da vergul bilan ikki qiymat — birinchisi birinchi animatsiyaga, ikkinchisi ikkinchisiga (@keyframes darsidagi bir nechta animatsiya).
Yechim
<style>
.retsept {
height: 240px;
overflow-y: auto;
padding-inline: 16px;
border: 2px solid #2f6b3a;
font-family: system-ui, sans-serif;
}
.bosqich {
margin-block: 48px;
padding: 16px;
border-radius: 12px;
background-color: #e8f1ec;
}
@keyframes kir {
from { opacity: 0; transform: translateY(24px); }
}
@keyframes chiq {
to { opacity: 0; transform: scale(0.9); }
}
@supports (animation-timeline: view()) {
@media (prefers-reduced-motion: no-preference) {
.bosqich {
animation: kir linear both, chiq linear both;
animation-timeline: view(), view();
animation-range: entry, exit;
}
}
}
</style>
<div class="retsept" tabindex="0" aria-label="Retsept">
<p>Pastga skroll qiling.</p>
<div class="bosqich">1. Qozonni qizdiring</div>
<div class="bosqich">2. Go'shtni qovuring</div>
<div class="bosqich">3. Sabzini soling</div>
<div class="bosqich">4. Guruchni soling</div>
<div class="bosqich">5. Damlang</div>
</div>@keyframes kirda faqatfrom,chiqda faqatto— qolgan chet elementning o'z holati (opacity: 1,transform: none). Ikki animatsiya bir-biriga xalaqit bermaydi.animation-range: entry, exit— nomning o'zientry 0% entry 100%degani.animation-timeline: view(), view()— har animatsiyaga o'z timeline'i. Bittaview()yozilsa ham ikkalasiga qo'llanadi, lekin aniq yozgan tushunarliroq.
4-mashq: Portfolio qadami — loyiha kartalari "sahnaga chiqsin"
Portfolio'ning loyihalar sahifasida kartalar (.loyihalar > article) skroll bilan paydo bo'lsin:
- Karta pastdan kira boshlaganda — shaffof va 16px pastda, kirishning 60% ida — joyida.
- Faqat qo'llab-quvvatlaydigan brauzerda va harakat kamaytirilmagan bo'lsa.
- Chrome'da (DevTools'da ekran enini 360 qilib) va Firefox'da tekshiring: Firefox'da kartalar oddiy ko'rinishi kerak. So'ng
npm run check.
Ishora: timeline — sahifa skrolli, kartalar esa uning bolalari, shuning uchun anonim view() yetarli. Kompyuterda kartalar birinchi ekranga sig'ib qolishi mumkin — ular allaqachon "kirgan" bo'ladi va animatsiya ko'rinmaydi. Bu to'g'ri xulq.
Yechim
Avval eski animatsiya. Micro-interaktsiyalar darsida kartalar sahifa ochilganda kirish stagger'i bilan chiqqan edi. Ikkala animatsiya bitta animation xususiyatiga yoziladi — kaskadda faqat bittasi yutadi, qaysi biri — fayldagi tartibga bog'liq. Kartaga ikki xil "kirish" kerak emas: skroll bilan paydo bo'lish uni almashtiradi. O'sha darsdagi karta qoidalarini o'chiring: --i raqamlari, @keyframes kirish va harakat blokidagi .loyihalar > article { animation: ... }. Tugmaning bosilish javobi qoladi.
Keyin asosiy.css ning «Komponentlar» qismidagi kartalar qoidalaridan keyin:
/* Kartalar skroll bilan paydo bo'ladi (Scroll-driven animatsiyalar
darsi). Firefox'da va harakat kamaytirilganda — oddiy */
@keyframes karta-kir {
from {
opacity: 0;
transform: translateY(1rem);
}
}
@supports (animation-timeline: view()) {
@media (prefers-reduced-motion: no-preference) {
.loyihalar > article {
animation: karta-kir linear both;
animation-timeline: view();
animation-range: entry 0% entry 60%;
}
}
}@keyframesda faqatfrom— oxirgi holat kartaning o'z stili. @property darsidagi hover chegarasiga ham xalaqit bermaydi: u--karta-chegarani o'zgartiradi, bu esaopacityvatransformni.- Kartalar subgrid'da (subgrid) —
transformvaopacitylayout'ga tegmaydi, qatorlar tekisligi buzilmaydi. 1rem— portfoliopxo'rnigaremishlatadi (O'lcham birliklari).
Telefonda ikkinchi va uchinchi karta pastdan suzib kiradi. Kompyuterda ikki ustunli to'rda kartalar birinchi ekranda — ular sahifa ochilganda to'liq ko'rinadi.
9. Real ishda
- Blog va hujjat saytlari — o'qish progress chizig'i. Ilgari har biri
scrollhodisasi va JavaScript bilan edi. - Landing sahifalar — bo'limlar paydo bo'lishi, raqamlar sanalishi, parallaks. Ko'pincha GSAP ScrollTrigger yoki Motion kabi JS kutubxonalari bilan yoziladi (Motion IV darsida) — CSS varianti yengilroq, lekin hozircha Firefox'da yo'q.
- Samaradorlik — CSS'dagi scroll-driven animatsiya
transformvaopacitybilan asosiy oqimdan tashqarida ishlashi mumkin, JavaScript'dagiscrolltinglovchisi esa har kadrda asosiy oqimni band qiladi. - Intervyuda: "Skroll progress chizig'ini JavaScript'siz qanday qilasiz va eski brauzer uchun nima qilasiz?" —
animation-timeline: scroll()va@supports.
Xulosa
- Scroll-driven animatsiya — oddiy
@keyframes, lekin soatni skroll beradi:animation-timeline. scroll()— konteyner qancha skroll qilingani (progress chizig'i);view()— element oynada qanchalik ko'ringani (paydo bo'lish).animation-range—entry,exit,contain,coverva foizlar bilan animatsiya bo'lagini tanlaydi.animation-timelinedoimanimationqisqa yozuvidan keyin; davomiylik yozilmaydi (auto).- Qo'shni elementga bog'lash — nomli timeline va
timeline-scope. - Baseline emas (Firefox'da yo'q):
@supports (animation-timeline: view())+prefers-reduced-motionichida, bezak sifatida.
Keyingi dars: View Transitions — ikki holat yoki hatto ikki sahifa orasida brauzer o'zi yasaydigan silliq o'tishlarni o'rganamiz.
Manbalar
- MDN: "CSS scroll-driven animations", "animation-timeline", "scroll()", "view()", "animation-range", "timeline-scope" — developer.mozilla.org
- W3C: "Scroll-driven Animations" — w3.org/TR/scroll-animations-1
- web-features (Baseline ma'lumotlari): "scroll-driven-animations" — github.com/web-platform-dx/web-features
- MDN browser-compat-data:
css.properties.animation-timeline(Firefox — preview) — github.com/mdn/browser-compat-data
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!