iOS ve Android uygulamalarında bulunan sekmelere benzer bir sekme bileşeninin nasıl oluşturulacağına dair temel bilgiler içerir.
Bu yayında, web için duyarlı, birden fazla cihaz girişini destekleyen ve tarayıcılarda çalışan bir Sekmeler bileşeni oluşturma konusunda düşüncelerimizi paylaşmak istiyorum. Demoyu deneyin.
Videoyu tercih ediyorsanız bu yayının YouTube sürümünü burada bulabilirsiniz:
Genel bakış
Sekmeler, tasarım sistemlerinin yaygın bir bileşenidir ancak birçok şekilde ve biçimde olabilir. Öncelikle <frame>
öğesine dayalı masaüstü sekmeleri vardı ve şimdi, fizik özelliklerine dayalı olarak içerik canlandıran tereyağlı mobil bileşenlerimiz var.
Hepsi aynı şeyi yapmaya çalışıyor: alandan tasarruf etmek.
Günümüzde, sekmeler kullanıcı deneyiminin olmazsa olmazları, içeriklerin ekran çerçevesi içindeki görünürlüğünü değiştiren düğmeyle gezinme alanıdır. Birçok farklı içerik alanı aynı alanı paylaşır ancak gezinmede seçilen düğmeye göre koşullu olarak sunulur.
![Web'in bileşen konseptine uyguladığı stil çeşitliliği nedeniyle oldukça kaotik.](https://web.dev/static/articles/building/a-tabs-component/image/the-collage-is-quite-chao-b6f8cd38f8ddd.png?authuser=5&hl=tr)
Web Taktikleri
Sonuçta, çok önemli birkaç web platformu özelliği sayesinde bu bileşeni oluşturmayı oldukça kolay buldum:
- Uygun kaydırma durdurma konumları ile şık kaydırma ve
klavye etkileşimleri için
scroll-snap-points
- Tarayıcı için URL karmaları aracılığıyla kullanılan derin bağlantılar sayfa içi kaydırma sabitleme ve paylaşım desteği
<a>
veid="#hash"
öğe işaretlemesiyle ekran okuyucu desteği- Çapraz geçiş geçişlerini ve anında sayfa içi kaydırmayı etkinleştirmek için
prefers-reduced-motion
- Seçilen sekmenin dinamik olarak altını çizmek ve renk değişikliği yapmak için taslak içi
@scroll-timeline
web özelliği
HTML
Temel olarak kullanıcı deneyimi şu şekildedir: Bir bağlantıyı tıklayın, URL'nin iç içe yerleştirilmiş sayfa durumunu temsil etmesini sağlayın ve tarayıcı eşleşen öğeye doğru kaydırdıkça içerik alanının güncellendiğini görürsünüz.
Yapısal içerik üyeleri de var: bağlantılar ve :target
. Elimizde <nav>
özelliğinin mükemmel olduğu bir bağlantı listesine ve <section>
öğesinin mükemmel olduğu <article>
öğelerinin bir listesine ihtiyacımız vardır. Her bağlantı karması bir bölümle eşleşir ve tarayıcının sabitleme aracılığıyla öğeleri kaydırmasına izin verir.
Örneğin, bir bağlantının tıklanması, Chrome 89'da :target
makalesinin otomatik olarak odaklanmasını sağlar. JS gerekli değildir. Kullanıcı daha sonra her zamanki gibi giriş cihazıyla makale içeriğini
kaydırabilir. İşaretlemede belirtildiği gibi bu ücretsiz içeriktir.
Sekmeleri düzenlemek için aşağıdaki işaretlemeyi kullandım:
<snap-tabs>
<header>
<nav>
<a></a>
<a></a>
<a></a>
<a></a>
</nav>
</header>
<section>
<article></article>
<article></article>
<article></article>
<article></article>
</section>
</snap-tabs>
<a>
ve <article>
öğeleri arasında href
ve id
özellikleriyle aşağıdaki gibi bağlantılar oluşturabilirim:
<snap-tabs>
<header>
<nav>
<a href="#responsive"></a>
<a href="#accessible"></a>
<a href="#overscroll"></a>
<a href="#more"></a>
</nav>
</header>
<section>
<article id="responsive"></article>
<article id="accessible"></article>
<article id="overscroll"></article>
<article id="more"></article>
</section>
</snap-tabs>
Daha sonra makaleleri karışık miktarda lorem ile, bağlantıları da karışık uzunluk ve resim başlık grubuyla doldurdum. Üzerinde çalışacağımız içerikle, düzeni başlatmaya başlayabiliriz.
Kayan düzenler
Bu bileşende 3 farklı kaydırma alanı türü vardır:
- Gezinme (pembe), yatay olarak kaydırılabilir
- İçerik alanı (mavi) yatay olarak kaydırılabilir
- Her makale öğesi (yeşil) dikey olarak kaydırılabilir.
![Kaydırma alanlarını ana hatlarıyla belirten ve hangi yönün kaydırılacağını gösteren, renk eşlemeli yön oklarının bulunduğu 3 renkli kutu.](https://web.dev/static/articles/building/a-tabs-component/image/3-colorful-boxes-color-m-da0de23b13551.png?authuser=5&hl=tr)
Kaydırmayla ilgili 2 farklı öğe türü vardır:
- Pencere
overflow
özellik stiline sahip tanımlı boyutlara sahip bir kutu. - Aşırı büyük bir yüzey
Bu düzende liste kapsayıcılarıdır: gezinme bağlantıları, bölüm makaleleri ve makale içerikleri.
<snap-tabs>
düzeni
Seçtiğim üst düzey düzen esnek (Flexbox) idi. Yönü column
olarak ayarladım. Böylece başlık ve bölüm dikey olarak sıralanmış. Bu, ilk kaydırma penceremizdir ve taşma işlevi gizlenmiş her şeyi gizler. Başlık ve bölüm, yakında ayrı alt bölgeler olarak fazladan kaydırmayı kullanacaktır.
<snap-tabs> <header></header> <section></section> </snap-tabs>
snap-tabs { display: flex; flex-direction: column; /* establish primary containing box */ overflow: hidden; position: relative; & > section { /* be pushy about consuming all space */ block-size: 100%; } & > header { /* defend againstneeding 100% */ flex-shrink: 0; /* fixes cross browser quarks */ min-block-size: fit-content; } }
Renkli 3 kaydırma şemasına dönelim:
<header>
artık (pink) kaydırma kapsayıcısı olmaya hazır.<section>
, (mavi) kaydırma kapsayıcısı için hazırdır.
Aşağıda VisBug ile vurguladığım çerçeveler, kaydırma kapsayıcılarının oluşturduğu pencereleri görmemize yardımcı olur.
![başlık ve bölüm öğelerinin üzerinde, bileşen içinde kapladıkları alanı gösteren hotpink yer paylaşımları bulunur.](https://web.dev/static/articles/building/a-tabs-component/image/the-header-section-eleme-dd313d7eb1453.png?authuser=5&hl=tr)
Sekmeler <header>
düzeni
Sonraki düzen neredeyse aynıdır: Dikey sıralama oluşturmak için flex özelliğini kullanıyorum.
<snap-tabs> <header> <nav></nav> <span class="snap-indicator"></span> </header> <section></section> </snap-tabs>
header { display: flex; flex-direction: column; }
.snap-indicator
, bağlantı grubuyla yatay olarak hareket etmelidir ve bu başlık düzeni sahnenin ayarlanmasına yardımcı olur. Burada mutlak konumlandırılmış öğe yok!
![nav ve span.indicator öğelerinin üzerinde, bileşende kapladıkları alanı özetleyen hotpink yer paylaşımları bulunur](https://web.dev/static/articles/building/a-tabs-component/image/the-nav-spanindicator-e-eddaf5b04df39.png?authuser=5&hl=tr)
Sonra, kaydırma stilleri. Kaydırma stillerini 2 yatay kaydırma alanımız (başlık ve bölüm) arasında paylaşabileceğimiz ortaya çıktı. Ben de bir yardımcı sınıf (.scroll-snap-x
) yaptım.
.scroll-snap-x {
/* browser decide if x is ok to scroll and show bars on, y hidden */
overflow: auto hidden;
/* prevent scroll chaining on x scroll */
overscroll-behavior-x: contain;
/* scrolling should snap children on x */
scroll-snap-type: x mandatory;
@media (hover: none) {
scrollbar-width: none;
&::-webkit-scrollbar {
width: 0;
height: 0;
}
}
}
Her birinin x ekseninde taşma, fazla kaydırmayı yakalamak için kaydırma çubuğu, dokunmatik cihazlar için gizli kaydırma çubukları ve son olarak içerik sunum alanlarını kilitlemek için kaydırma çubuğunun olması gerekir. Klavye sekme sıramıza erişilebiliyor ve etkileşimler doğal bir şekilde odaklanmaya odaklanıyor. Kaydırma tutturma kapsayıcıları, klavyelerinden atlı karınca stilinde güzel bir etkileşim de elde eder.
Sekme başlığı <nav>
düzeni
Gezinme bağlantılarının bir satır içine, satır sonu olmadan, dikey olarak ortalanmış şekilde yerleştirilmesi ve her bir bağlantı öğesi, kaydırma tutturma kapsayıcısına tutturulmalıdır. Swift, 2021 CSS için çalıştı!
<nav> <a></a> <a></a> <a></a> <a></a> </nav>
nav { display: flex; & a { scroll-snap-align: start; display: inline-flex; align-items: center; white-space: nowrap; } }
Her bağlantı stili ve kendisinin boyutu olduğundan gezinme düzeninin yalnızca yönü ve akışı belirtmesi gerekir. Gezinme öğelerinin benzersiz genişlikleri, gösterge genişliğini yeni hedefe göre ayarlarken sekmeler arasındaki geçişi eğlenceli hale getirir. Burada kaç öğe olduğuna bağlı olarak tarayıcı bir kaydırma çubuğu oluşturur veya oluşturmaz.
![gezinme öğelerinin üzerinde, bileşen içinde kapladıkları alanı ve nereye taştıklarını gösteren hotpink yer paylaşımları bulunur.](https://web.dev/static/articles/building/a-tabs-component/image/the-elements-the-nav-h-c8efe2b10b412.png?authuser=5&hl=tr)
Sekmeler <section>
düzeni
Bu bölüm, esnek bir öğedir ve alanın baskın tüketicisi olmalıdır. Ayrıca, makalelerin yerleştirileceği sütunlar oluşturması gerekir. Yine CSS 2021 için
hızlı bir şekilde çalışın. block-size: 100%
, bu öğeyi üst öğeyi mümkün olduğunca dolduracak şekilde genişletir. Daha sonra, kendi düzeni için üst öğenin genişliği 100%
olan bir sütun serisi oluşturur. Burada yüzdeler çok işe yarıyor,
çünkü ana yayıncıyla ilgili güçlü kısıtlamalar yazdık.
<section> <article></article> <article></article> <article></article> <article></article> </section>
section { block-size: 100%; display: grid; grid-auto-flow: column; grid-auto-columns: 100%; }
Tam yükseklikte bir grup sütun için satır yüksekliğini ayarlayan "bu genişletme aktarmaya karşı bir savunmadır" ifadesiyle "mümkün olduğunca dikey olarak, ısrarla genişlet" diyoruz (flex-shrink: 0
olarak ayarladığımız başlığı unutmayın). auto-flow
stili, ızgaraya alt öğeleri her zaman yatay bir çizgide, sarmalama yapmadan, tam olarak istediğimiz şekilde yerleştirmesini ve üst pencereden taşacak şekilde yerleştirmesini söyler.
![makale öğelerinin üzerinde, bileşen içinde kapladıkları alanı ve nereye taştıklarını gösteren hotpink yer paylaşımları bulunur.](https://web.dev/static/articles/building/a-tabs-component/image/the-article-elements-hot-924ae524ee8fb.png?authuser=5&hl=tr)
Bazen kafamı çevirmekte zorlanıyorum. Bu bölüm öğesi bir kutuya sığıyor, ancak aynı zamanda bir dizi kutu da oluşturmuş. Görsellerin ve açıklamaların yardımcı olduğunu umuyorum.
Sekmeler <article>
düzeni
Kullanıcı, makale içeriğini kaydırabilmelidir ve kaydırma çubukları yalnızca taşma olduğunda görünmelidir. Bu makale öğeleri düzgün bir konumdadır. Bunlar aynı anda, kaydırma üst ve kaydırma alt öğesidir. Tarayıcı, burada bizim için bazı zorlu dokunma, fare ve klavye etkileşimlerini gerçekten işliyor.
<article> <h2></h2> <p></p> <p></p> <h2></h2> <p></p> <p></p> ... </article>
article { scroll-snap-align: start; overflow-y: auto; overscroll-behavior-y: contain; }
Makalelerin, üst kaydırıcıya tutturulmasını tercih ettim. Gezinme bağlantısı öğelerinin ve makale öğelerinin, ilgili kaydırma kapsayıcılarının satır içi başlangıcına tutturulmasını çok seviyorum. Uyumlu bir ilişki gibi görünür ve hissedilir.
![makale öğesinin ve alt öğelerinin üzerinde hotpink yer paylaşımları var. Bu yer paylaşımları, bileşende kapladıkları alanı ve taştıkları yönü özetliyor](https://web.dev/static/articles/building/a-tabs-component/image/the-article-element-its-8afcb8a6817ff.png?authuser=5&hl=tr)
Makale, ızgara alt öğesidir ve boyutu, kaydırma kullanıcı deneyimi sağlamak istediğimiz görüntü alanı olarak önceden belirlenir. Yani, burada herhangi bir yüksekliğe veya genişlik stiline ihtiyacım yok, sadece nasıl taşacağını tanımlamam gerekiyor. Taşma-y ayarını otomatik olarak yapıyorum ve ardından kaydırma etkileşimlerini, kullanışlı "fazla kaydırma davranışı" özelliğiyle yakalıyorum.
3 kaydırma alanı özeti
Sistem ayarlarımda aşağıda "kaydırma çubuklarını her zaman göster" seçeneğini belirledim. Düzeni ve kaydırma düzenini incelemem gerektiğinden, düzenin bu ayar etkinken çalışması iki kat önemli.
![3 kaydırma çubuğu gösterilecek şekilde ayarlandı. Bu çubuk artık düzen alanında yer kaplıyor ve bileşenimiz hâlâ harika görünüyor](https://web.dev/static/articles/building/a-tabs-component/image/the-3-scrollbars-are-set-ca02ac51f046d.png?authuser=5&hl=tr)
Bence bu bileşendeki kaydırma çubuğu oluğunu görmek, kaydırma alanlarının nerede olduğunu, destekledikleri yönün ve birbirleriyle nasıl etkileşim kurduklarını açıkça göstermeye yardımcı oluyor. Bu kaydırma penceresi çerçevelerinin her birinin aynı zamanda bir düzenin esnek veya ızgara üst öğesi olduğunu düşünün.
Geliştirici Araçları, aşağıdakileri görselleştirmemize yardımcı olabilir:
![kaydırma alanlarında ızgara ve flexbox aracı yer paylaşımları bulunuyor. Bileşenin içinde kapladıkları alan ve bu yüzeylerin taşma yönü gösteriliyor.](https://web.dev/static/articles/building/a-tabs-component/image/the-scroll-areas-grid-f-79f0ae5839bcc.png?authuser=5&hl=tr)
Kaydırma düzenleri tamdır: yapışma, derin bağlantı oluşturma ve klavyeden erişilebilir. Kullanıcı deneyimi iyileştirmeleri, stil ve memnuniyet için sağlam bir temel.
Öne çıkan özellik
Kaydırarak tutturulan alt öğeler, yeniden boyutlandırma sırasında kilitli konumlarını korur. Diğer bir deyişle, cihaz döndürme veya tarayıcı yeniden boyutlandırmada JavaScript'in herhangi bir şey görüntülemesi gerekmez. Bu özelliği Chromium Geliştirici Araçları Cihaz Modu'nda deneyin. Bunun için Duyarlı dışında bir mod seçip cihaz çerçevesini yeniden boyutlandırın. Öğenin görünümde kaldığına ve içeriğiyle kilitlendiğine dikkat edin. Bu özellik, Chromium uygulamasını spesifikasyonla eşleşecek şekilde güncellediğinden beri kullanılabilir. Bu konuyla ilgili blog yayınını burada bulabilirsiniz.
Animasyonlar
Buradaki animasyon çalışmasının amacı, etkileşimleri kullanıcı arayüzü geri bildirimiyle açık bir şekilde bağlamaktır. Bu, kullanıcının tüm içeriği sorunsuz bir şekilde keşfetmesine yardımcı olur. Belirli bir amaçla ve koşula olarak hareket ekliyorum. Kullanıcılar artık hareket tercihlerini işletim sistemlerinde belirtebiliyor ve arayüzlerimde tercihlerini yanıtlamaktan büyük keyif alıyorum.
Makale kaydırma konumuna bir sekme alt çizgisi bağlayacağım. Yapıştırma sadece uygun bir hizalama değil, aynı zamanda bir animasyonun başlangıcını ve sonunu da sabitler.
Bu şekilde, mini harita işlevi gören <nav>
, içeriğe bağlı kalır.
Kullanıcının hareket tercihini hem CSS hem de JS'den kontrol edeceğiz. Dikkate alınması gereken
birkaç harika yer var.
Kaydırma davranışı
Hem :target
hem de element.scrollIntoView()
uygulamasının hareket davranışını iyileştirme fırsatı bulunmaktadır. Varsayılan olarak anında çalışır. Tarayıcı yalnızca kaydırma
konumunu ayarlar. Orada yanıp sönmek yerine
o kaydırma konumuna geçiş yapmak istersek ne olur?
@media (prefers-reduced-motion: no-preference) {
.scroll-snap-x {
scroll-behavior: smooth;
}
}
Burada hareket ve kullanıcının kontrol edemediği hareket (kaydırma gibi) uygulamaya başladığımızdan, bu stili yalnızca kullanıcının işletim sisteminde azaltılmış hareketle ilgili bir tercihi yoksa uyguluyoruz. Bu şekilde, kaydırma hareketini yalnızca bu konuda memnun olan kişiler için tanıtırız.
Sekme göstergesi
Bu animasyonun amacı, göstergeyi içeriğin durumuyla ilişkilendirmeye yardımcı olmaktır. Daha az hareket etmeyi tercih eden kullanıcılar için border-bottom
stillerinin renk geçişine, harekete geçmeyen kullanıcılar için kaydırma bağlantılı kaydırmalı ve rengi soldurma animasyonu uygulamaya karar verdim.
Chromium Geliştirici Araçları'nda tercihi açıp kapatabilir ve 2 farklı geçiş stilini gösterebilirim. Bunu hazırlarken çok eğlendim.
@media (prefers-reduced-motion: reduce) {
snap-tabs > header a {
border-block-end: var(--indicator-size) solid hsl(var(--accent) / 0%);
transition: color .7s ease, border-color .5s ease;
&:is(:target,:active,[active]) {
color: var(--text-active-color);
border-block-end-color: hsl(var(--accent));
}
}
snap-tabs .snap-indicator {
visibility: hidden;
}
}
Kullanıcılar artık ihtiyacım kalmadığı için azalan hareketi tercih ettiğinde .snap-indicator
etiketini saklıyorum. Daha sonra, bunu border-block-end
stilleri ve transition
ile değiştiriyorum. Ayrıca, sekmeler etkileşiminde, etkin gezinme öğesinin yalnızca bir marka altı çizili vurgusu olmadığını, metin renginin daha koyu da olduğuna dikkat edin. Etkin öğe daha yüksek metin rengi kontrastına ve parlak bir alt ışık vurgusuna sahiptir.
Sadece birkaç satır CSS ile izleyicilerin fark edildiklerini hissetmelerini sağlayabilirsiniz (hareket tercihlerine özenli bir şekilde saygı gösterdiğimiz için). Buna bayıldım.
@scroll-timeline
Yukarıdaki bölümde, azaltılmış hareket çapraz geçişi stillerini nasıl ele aldığımı göstermiştim. Bu bölümde ise gösterge ile kaydırma alanını nasıl birbirine bağladığımı göstereceğim. Sırada eğlenceli ve deneysel bir şeyler var. Umarım siz de benim kadar heyecanlısınızdır.
const { matches:motionOK } = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
);
Önce JavaScript'ten kullanıcının hareket tercihini kontrol ediyorum. Bunun sonucunda false
(kullanıcının daha az hareket tercih ettiği anlamına gelir) kaydırma bağlantı hareketi efektlerinin hiçbirini çalıştırmayız.
if (motionOK) {
// motion based animation code
}
Bu makalenin yazıldığı tarihte @scroll-timeline
için tarayıcı desteği mevcut değildir. Yalnızca deneysel uygulamaları olan bir taslak spesifikasyondur. Yine de bu demoda kullandığım
bir çoklu dolgusu var.
ScrollTimeline
Hem CSS hem de JavaScript kaydırma zaman çizelgeleri oluşturabiliyor olsa da animasyonda canlı öğe ölçümlerini kullanabilmek için JavaScript'i etkinleştirdim.
const sectionScrollTimeline = new ScrollTimeline({
scrollSource: tabsection, // snap-tabs > section
orientation: 'inline', // scroll in the direction letters flow
fill: 'both', // bi-directional linking
});
1 öğenin başka bir öğenin kaydırma konumunu takip etmesini istiyorum ve bir ScrollTimeline
oluşturarak kaydırma bağlantısı sürücüsünü (scrollSource
) tanımlıyorum.
Normalde web'deki bir animasyon genel bir zaman aralığı onayına karşı çalışır, ancak bellekte özel bir sectionScrollTimeline
ile bunların tümünü değiştirebilirim.
tabindicator.animate({
transform: ...,
width: ...,
}, {
duration: 1000,
fill: 'both',
timeline: sectionScrollTimeline,
}
);
Animasyonun animasyon karelerine girmeden önce, kaydırmanın takipçisine (tabindicator
) özel bir zaman çizelgesine, yani bölümümüzün kaydırıldığı yere göre animasyon uygulanacağını belirtmenin önemli olduğunu düşünüyorum. Bu işlem, bağlantıyı tamamlar ancak animasyon kareleri olarak da bilinen son bileşen olan durum bilgili noktalara eksik kalır.
Dinamik animasyon kareleri
@scroll-timeline
ile animasyon yapmanın gerçekten basit bir bildirim temelli CSS yolu var ama seçtiğim animasyon çok dinamikti. auto
genişliği arasında geçiş yapılamaz ve alt öğelerin uzunluğuna göre dinamik olarak birkaç animasyon karesi oluşturulamaz.
JavaScript, bu bilgiyi nasıl edineceğini bilir; bu yüzden alt öğeleri kendimiz tekrarlayıp, hesaplanan değerleri çalışma zamanında yakalarız:
tabindicator.animate({
transform: [...tabnavitems].map(({offsetLeft}) =>
`translateX(${offsetLeft}px)`),
width: [...tabnavitems].map(({offsetWidth}) =>
`${offsetWidth}px`)
}, {
duration: 1000,
fill: 'both',
timeline: sectionScrollTimeline,
}
);
Her bir tabnavitem
için offsetLeft
konumunu yok edin ve bu konumu translateX
değeri olarak kullanan bir dize döndürün. Bu işlem, animasyon için 4 dönüşüm animasyon karesi
oluşturur. Aynı şey genişlik için de yapılır. Her birine dinamik genişliğinin ne olduğu sorulur ve daha sonra, bu değer bir animasyon karesi değeri olarak kullanılır.
Yazı tiplerime ve tarayıcı tercihlerime dayalı olarak örnek çıktıyı aşağıda bulabilirsiniz:
TranslateX Animasyon Kareleri:
[...tabnavitems].map(({offsetLeft}) =>
`translateX(${offsetLeft}px)`)
// results in 4 array items, which represent 4 keyframe states
// ["translateX(0px)", "translateX(121px)", "translateX(238px)", "translateX(464px)"]
Genişlik Animasyon Kareleri:
[...tabnavitems].map(({offsetWidth}) =>
`${offsetWidth}px`)
// results in 4 array items, which represent 4 keyframe states
// ["121px", "117px", "226px", "67px"]
Stratejiyi özetlemek için, sekme göstergesi bölüm kaydırıcısının kaydırma tutturma konumuna bağlı olarak 4 animasyon karesinde animasyon oluşturur. Yapışma noktaları, animasyon karelerimiz arasında net bir betimleme oluşturur ve animasyonun senkronize hissine gerçekten katkıda bulunur.
![etkin sekme ve etkin olmayan sekme, her ikisi için de geçiş puanlarını gösteren VisBug yer paylaşımları ile gösterilir.](https://web.dev/static/articles/building/a-tabs-component/image/active-tab-inactive-tab-9604191ea7007.png?authuser=5&hl=tr)
Kullanıcı, etkileşimiyle animasyonu yönlendirir. Göstergenin genişliğinin ve konumunun bir bölümden diğerine geçtiğini görür ve kaydırmayla bunu mükemmel bir şekilde izler.
Fark etmemiş olabilirsiniz, ama vurgulanan gezinme öğesi seçildikçe renk geçişinden gurur duyuyorum.
Vurgulanan öğe daha fazla kontrasta sahip olduğunda, seçilmeyen açık gri renk daha da geriye itilir. Metin için renk geçişi (ör. fareyle üzerine gelindiğinde ve seçildiğinde) yaygındır, ancak alt çizgi göstergesiyle senkronize olarak kaydırma sırasında bu rengin geçişi bir sonraki düzeydir.
Bunu şu şekilde yaptım:
tabnavitems.forEach(navitem => {
navitem.animate({
color: [...tabnavitems].map(item =>
item === navitem
? `var(--text-active-color)`
: `var(--text-color)`)
}, {
duration: 1000,
fill: 'both',
timeline: sectionScrollTimeline,
}
);
});
Her sekme gezinme bağlantısı, alt çizgi göstergesiyle aynı kaydırma zaman çizelgesini izleyen bu yeni renkli animasyona ihtiyaç duyar. Öncekiyle aynı zaman çizelgesini kullanıyorum. Görevi kaydırmada onay işareti yapmak olduğundan, bu onay işaretini istediğimiz türlerde kullanabiliriz. Daha önce yaptığım gibi, döngü içinde 4 animasyon karesi oluşturuyor ve renkleri döndürüyorum.
[...tabnavitems].map(item =>
item === navitem
? `var(--text-active-color)`
: `var(--text-color)`)
// results in 4 array items, which represent 4 keyframe states
// [
"var(--text-active-color)",
"var(--text-color)",
"var(--text-color)",
"var(--text-color)",
]
var(--text-active-color)
renge sahip animasyon karesi bağlantıyı vurgular. Aksi halde standart bir metin rengi olur. Dış döngü her bir nav öğesi, iç döngü ise her navitem'ın kişisel animasyon kareleri olduğundan iç içe geçmiş döngü bunu nispeten basit hale getirir. Dış döngü öğesinin iç döngüyle aynı olup olmadığını
kontrol ediyorum ve ne zaman seçileceğini bilmek için bunu kullanıyorum.
Bunu yazarken çok eğlendim. Oldukça çok.
Daha fazla JavaScript geliştirmesi
Burada gösterdiklerimin temelinin JavaScript olmadan çalıştığını hatırlatmak isteriz. Bununla birlikte, JS kullanılabilir olduğunda bunu nasıl geliştirebileceğimize bakalım.
Derin bağlantılar
Derin bağlantılar daha çok mobil bir terimdir, ancak bence derin bağlantının amacı, bir URL'yi doğrudan bir sekmenin içeriğiyle
paylaşabilmenizi sağlayan sekmelerle karşılanıyor. Tarayıcı sayfa içinde, URL karmasıyla eşleşen kimliğe gider. Bu onload
işleyicinin platformlar genelinde etkili olduğunu buldum.
window.onload = () => {
if (location.hash) {
tabsection.scrollLeft = document
.querySelector(location.hash)
.offsetLeft;
}
}
Kaydırma senkronizasyonunu sonlandır
Kullanıcılarımız her zaman tıklama yapmıyor veya klavye kullanmıyor, bazen de normalde yapabilecekleri gibi yalnızca serbest kaydırma yapıyorlar. Bölüm kaydırma çubuğu kaydırmayı durdurduğunda, indiği yerin üst gezinme çubuğunda eşleştirilmesi gerekir.
Kaydırma sonu için beklemem şu şekilde:
js
tabsection.addEventListener('scroll', () => {
clearTimeout(tabsection.scrollEndTimer);
tabsection.scrollEndTimer = setTimeout(determineActiveTabSection, 100);
});
Bölümler kaydırılırken, varsa bölüm zaman aşımını temizleyin ve yeni bir bölüm başlatın. Bölümlerin kaydırılması durduğunda, zaman aşımını silmeyin ve dinledikten sonra 100 ms. Tetiklendiğinde, kullanıcının nerede durduğunu bulmaya çalışan fonksiyonu çağırın.
const determineActiveTabSection = () => {
const i = tabsection.scrollLeft / tabsection.clientWidth;
const matchingNavItem = tabnavitems[i];
matchingNavItem && setActiveTab(matchingNavItem);
};
Kaydırmanın yapıştığını varsayarsak, geçerli kaydırma konumunun kaydırma alanının genişliğinden böldüğümüzde ondalık değer yerine bir tam sayı olması gerekir. Daha sonra, bu hesaplanan dizin aracılığıyla önbelleğimizden bir navitem almaya çalışıyorum ve bir şey bulursa eşleşmeyi etkin olarak ayarlamak üzere gönderiyorum.
const setActiveTab = tabbtn => {
tabnav
.querySelector(':scope a[active]')
.removeAttribute('active');
tabbtn.setAttribute('active', '');
tabbtn.scrollIntoView();
};
Etkin sekmenin ayarlanması, o sırada etkin olan herhangi bir sekmenin temizlenmesi ve ardından gelen gezinme öğesine etkin durum özelliğinin verilmesiyle başlar. scrollIntoView()
çağrısı, CSS ile kayda değer bir eğlenceli etkileşim içeriyor.
.scroll-snap-x {
overflow: auto hidden;
overscroll-behavior-x: contain;
scroll-snap-type: x mandatory;
@media (prefers-reduced-motion: no-preference) {
scroll-behavior: smooth;
}
}
Yatay kaydırma yapma yardımcı programı CSS'de, kullanıcı harekete izin veriyorsa smooth
kaydırma uygulayan bir medya sorgusunu iç içe yerleştirdik. JavaScript, öğeleri görünüme kaydırmak için serbestçe çağrılar yapabilir ve CSS, kullanıcı deneyimini bildirimli şekilde yönetebilir.
Bazen çok keyifli ve keyifli bir eşleştirme yapıyorlar.
Sonuç
Nasıl yaptığımı artık bildiğine göre sen ne yaparsın? Bu da bileşen mimarisini eğlenceli hale getirir. En sevdiği çerçevedeki slotlarla 1. sürümü kim yapacak? 🙂
Yaklaşımlarımızı çeşitlendirelim ve web'de geliştirme yapmanın tüm yollarını öğrenelim. Bir Glitch oluşturun, kendi sürümünüzü tweet'leyin, ardından bunu aşağıdaki Topluluk remiksleri bölümüne eklerim.
Topluluk remiksleri
- @devnook, @rob_dodson ve Web Bileşenleri ile @DasSurma: article.
- @jhvanderschee ve düğmeler: Codepen.