Duyarlı bir kayar yan gezinme çubuğu oluşturma hakkında temel bilgiler
Bu yayında, web için duyarlı, durum bilgisi olan, klavye ile gezinmeyi destekleyen, JavaScript ile ve JavaScript olmadan çalışan ve tarayıcılar arası uyumluluğa sahip bir Sidenav bileşeninin prototipini nasıl oluşturduğumu sizinle paylaşmak istiyorum. Demoyu deneyin.
Video tercih ediyorsanız bu yayının YouTube versiyonunu aşağıda bulabilirsiniz:
Genel Bakış
Duyarlı bir gezinme sistemi oluşturmak zordur. Bazı kullanıcılar klavye kullanır, bazıları güçlü masaüstü bilgisayarlara sahiptir ve bazıları da küçük bir mobil cihazdan ziyaret eder. Ziyaret eden herkes menüyü açıp kapatabilmelidir.
Web Taktikleri
Bu bileşen keşfinde, birkaç önemli web platformu özelliğini birleştirme keyfini yaşadım:
- CSS
:target
- CSS grid
- CSS dönüşümleri
- Görüntü alanı ve kullanıcı tercihi için CSS medya sorguları
focus
Kullanıcı deneyimi iyileştirmeleri için JS
Çözümümde bir kenar çubuğu var ve yalnızca 540px
veya daha küçük bir görüntü alanında "mobil" olarak değiştiriliyor.
540px
, mobil etkileşimli düzen ile statik masaüstü düzeni arasında geçiş yaparken kullanacağımız kesme noktası olacak.
CSS :target
sözde sınıfı
Bir <a>
bağlantısı URL karmasını #sidenav-open
, diğeri ise boş (''
) olarak ayarlar.
Son olarak, bir öğe karmayla eşleşecek id
değerine sahiptir:
<a href="#sidenav-open" id="sidenav-button" title="Open Menu" aria-label="Open Menu">
<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu"></a>
<aside id="sidenav-open">
…
</aside>
Bu bağlantıların her birini tıkladığınızda sayfa URL'mizin karma durumu değişir. Ardından, bir sözde sınıf kullanarak yan gezinme çubuğunu gösterir ve gizlerim:
@media (max-width: 540px) {
#sidenav-open {
visibility: hidden;
}
#sidenav-open:target {
visibility: visible;
}
}
CSS Izgarası
Geçmişte yalnızca mutlak veya sabit konumlu kenar çubuğu düzenleri ve bileşenleri kullanıyordum. Ancak grid-area
söz dizimine sahip olan Grid, aynı satıra veya sütuna birden fazla öğe atamamıza olanak tanır.
Şekil grupları
Birincil düzen öğesi #sidenav-container
, 1 satır ve 2 sütun oluşturan bir ızgaradır. Bunlardan 1'ine stack
adı verilir. Alan sınırlı olduğunda CSS, <main>
öğesinin tüm alt öğelerini aynı ızgara adına atar. Böylece tüm öğeler aynı alana yerleştirilerek bir yığın oluşturulur.
#sidenav-container {
display: grid;
grid: [stack] 1fr / min-content [stack] 1fr;
min-height: 100vh;
}
@media (max-width: 540px) {
#sidenav-container > * {
grid-area: stack;
}
}
Menü arka planı
<aside>
, yan gezinmeyi içeren animasyonlu öğedir. Bu öğenin 2 alt öğesi vardır: <nav>
adlı gezinme kapsayıcısı [nav]
ve menüyü kapatmak için kullanılan [escape]
adlı arka plan <a>
.
#sidenav-open {
display: grid;
grid-template-columns: [nav] 2fr [escape] 1fr;
}
Menü yerleşimi ve negatif alan kapatma düğmesi için istediğiniz oranı bulmak üzere 2fr
ve 1fr
değerlerini ayarlayın.
CSS 3D dönüştürme işlemleri ve geçişleri
Düzenimiz artık mobil görüntü alanı boyutunda yığılmış durumda. Until I add some new styles, it's overlaying our article by default. Bu sonraki bölümde hedeflediğim bazı kullanıcı deneyimleri şunlardır:
- Açılış ve kapanış animasyonu
- Yalnızca kullanıcı kabul ediyorsa hareketle animasyon yapın
- Klavye odağının ekran dışındaki öğeye girmemesi için
visibility
öğesine animasyon ekleyin.
Hareket animasyonlarını uygulamaya başlarken erişilebilirliği ön planda tutmak istiyorum.
Erişilebilir hareket
Herkes kaydırma hareketli deneyim istemeyebilir. Çözümümüzde bu tercih, medya sorgusunun içindeki bir --duration
CSS değişkeni ayarlanarak uygulanır. Bu medya sorgusu değeri, kullanıcının hareketle ilgili işletim sistemi tercihini (varsa) gösterir.
#sidenav-open {
--duration: .6s;
}
@media (prefers-reduced-motion: reduce) {
#sidenav-open {
--duration: 1ms;
}
}
Artık yan gezinme çubuğumuz açılıp kapanırken kullanıcı hareket azaltmayı tercih ediyorsa öğeyi anında görünür hale getiriyorum ve durumu hareket olmadan koruyorum.
Geçiş, dönüştürme, çeviri
Sidenav out (varsayılan)
Mobil cihazlarda kenar gezinme çubuğumuzun varsayılan durumunu ekran dışı olarak ayarlamak için öğeyi transform: translateX(-110vw)
ile konumlandırıyorum.
Yan gezinme çubuğunun box-shadow
gizlendiğinde ana görünüm penceresine sızmamasını sağlamak için normalde -100vw
olan ekran dışı koda başka bir 10vw
eklediğimi unutmayın.
@media (max-width: 540px) {
#sidenav-open {
visibility: hidden;
transform: translateX(-110vw);
will-change: transform;
transition:
transform var(--duration) var(--easeOutExpo),
visibility 0s linear var(--duration);
}
}
Yan gezinme çubuğu
#sidenav
öğesi :target
ile eşleştiğinde translateX()
konumunu ana üs 0
olarak ayarlayın.
URL karması değiştirildiğinde CSS'nin öğeyi -110vw
olan dış konumundan var(--duration)
süresince 0
olan "iç" konumuna kaydırmasını izleyin.
@media (max-width: 540px) {
#sidenav-open:target {
visibility: visible;
transform: translateX(0);
transition:
transform var(--duration) var(--easeOutExpo);
}
}
Geçiş görünürlüğü
Şimdi amaç, menü gösterildiğinde ekran okuyuculardan gizlemek. Böylece sistemler, ekran dışındaki bir menüye odaklanmaz. Bunu, :target
değiştiğinde görünürlük geçişi ayarlayarak yapıyorum.
- Görünürlüğe geçiş yapmayın. Öğenin kayarak gelmesini ve odaklanmasını görebilmem için hemen görünür olun.
- Dışarı çıkarken görünürlüğü geçişli hale getirin ancak geçişi geciktirin. Böylece geçişin sonunda
hidden
simgesine döner.
Erişilebilirlik kullanıcı deneyimi geliştirmeleri
Bağlantılar
Bu çözüm, durumun yönetilmesi için URL'nin değiştirilmesine dayanır.
Burada doğal olarak <a>
öğesi kullanılmalıdır ve bu öğe, ücretsiz olarak bazı güzel erişilebilirlik özellikleri sunar. Etkileşimli öğelerimizi, amacı net bir şekilde ifade eden etiketlerle süsleyelim.
<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu"></a>
<a href="#sidenav-open" id="sidenav-button" class="hamburger" title="Open Menu" aria-label="Open Menu">
<svg>...</svg>
</a>
Artık birincil etkileşim düğmelerimiz hem fare hem de klavye için amaçlarını net bir şekilde belirtiyor.
:is(:hover, :focus)
Bu kullanışlı CSS işlevsel sözde seçici, üzerine gelme stillerini odaklanma stiliyle de paylaşarak hızlı bir şekilde kapsayıcı olmamızı sağlar.
.hamburger:is(:hover, :focus) svg > line {
stroke: hsl(var(--brandHSL));
}
JavaScript'i ekleyin
Kapatmak için escape
düğmesine basın
Klavyenizdeki Escape
tuşu menüyü kapatmalıdır, değil mi? Şimdi bu sorunu çözelim.
const sidenav = document.querySelector('#sidenav-open');
sidenav.addEventListener('keyup', event => {
if (event.code === 'Escape') document.location.hash = '';
});
Tarayıcı geçmişi
Açma ve kapatma etkileşiminin tarayıcı geçmişine birden fazla giriş eklemesini önlemek için kapatma düğmesine aşağıdaki satır içi JavaScript'i ekleyin:
<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu" onchange="history.go(-1)"></a>
Bu işlem, kapatıldığında URL geçmişi girişini kaldırarak menü hiç açılmamış gibi görünmesini sağlar.
Focus UX
Aşağıdaki snippet, açma ve kapatma düğmeleri açıldıktan veya kapatıldıktan sonra bu düğmelere odaklanmamıza yardımcı olur. Geçişleri kolaylaştırmak istiyorum.
sidenav.addEventListener('transitionend', e => {
const isOpen = document.location.hash === '#sidenav-open';
isOpen
? document.querySelector('#sidenav-close').focus()
: document.querySelector('#sidenav-button').focus();
})
Yan gezinme çubuğu açıldığında kapat düğmesine odaklanın. Sidenav kapandığında,
aç düğmesine odaklanın. Bunu, JavaScript'te öğe üzerinde focus()
çağırarak yapıyorum.
Sonuç
Benim nasıl yaptığımı öğrendiğinize göre, siz nasıl yapardınız? Bu, eğlenceli bir bileşen mimarisi oluşturur. Who's going to make the 1st version with slots? 🙂
Yaklaşımlarımızı çeşitlendirelim ve web'de içerik oluşturmanın tüm yollarını öğrenelim. Bir Glitch oluşturun, sürümünüzü bana tweet atın. Ben de sürümünüzü aşağıdaki Topluluk remiksleri bölümüne ekleyeyim.
Topluluk remiksleri
- Özel öğelerle @_developit: demo ve kod
- HTML/CSS/JS ile @mayeedwin1: demo ve kod
- Glitch Remix ile @a_nurella: demo ve kod
- HTML/CSS/JS ile @EvroMalarkey: demo ve kod