Duyarlı kaydırmalı kenar çubuğu oluşturmaya dair temel bilgiler
Bu gönderide, web için duyarlı, durum bilgisine sahip, klavye gezinmesini destekleyen, JavaScript ile ve JavaScript olmadan çalışan ve tarayıcılarda çalışan bir Sidenav bileşeninin prototipini nasıl oluşturduğumu paylaşmak istiyorum. Demoyu deneyin.
Videoyu tercih ediyorsanız bu yayının YouTube sürümünü burada bulabilirsiniz:
Genel Bakış
Duyarlı bir gezinme sistemi oluşturmak zordur. Bazı kullanıcılar klavye kullanırken bazıları güçlü masaüstü bilgisayarlara sahip olur, bazıları ise 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 bir araya getirmenin 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 geliştirmeleri için JS
Çözümümde bir kenar çubuğu var ve yalnızca 540px
veya daha küçük bir "mobil" görüntü alanındayken açılıp kapanıyor.
540px
, mobil etkileşimli düzen ile statik masaüstü düzeni arasında geçiş yapmak için kullanacağımız kesme noktası olacaktır.
CSS :target
sözde sınıfı
Bir <a>
bağlantısı, URL karmasını #sidenav-open
olarak, diğeri ise boş (''
) olarak ayarlar.
Son olarak, bir öğede karmayı eşleştirecek id
bulunur:
<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ıfla yan menüyü gösterir ve gizlerim:
@media (max-width: 540px) {
#sidenav-open {
visibility: hidden;
}
#sidenav-open:target {
visibility: visible;
}
}
CSS Grid
Geçmişte yalnızca mutlak veya sabit konumlu kenar çubuğu düzenleri ve bileşenleri kullanıyordum. Ancak grid-area
söz dizimi sayesinde grid, aynı satıra veya sütuna birden fazla öğe atamamıza olanak tanır.
Gruplar
Birincil düzen öğesi #sidenav-container
, 1 satır ve 2 sütun oluşturan bir ızgaradır. Bu ızgaradaki her sütunun adı stack
'dur. Alan kısıtlı olduğunda CSS, <main>
öğesinin tüm alt öğelerini aynı ızgara adına atar, tüm öğeleri aynı alana yerleştirir ve bir yığın oluşturur.
#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 gezinme menüsünü içeren animasyonlu öğedir. 2 alt öğesi vardır: [nav]
adlı gezinme kapsayıcısı <nav>
ve menüyü kapatmak için kullanılan [escape]
adlı bir arka plan <a>
.
#sidenav-open {
display: grid;
grid-template-columns: [nav] 2fr [escape] 1fr;
}
Menü yer paylaşımı 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şler
Düzenimiz artık mobil görüntü alanı boyutunda yığılmış durumda. Yeni stiller ekleyene kadar varsayılan olarak makalemizin üzerine biniyor. Bu sonraki bölümde hedeflediğim kullanıcı deneyimi özelliklerini aşağıda bulabilirsiniz:
- Açma ve kapama animasyonları
- Yalnızca kullanıcının kabul etmesi durumunda hareketle animasyon oluşturma
- Klavye odağının ekran dışı öğeye girmemesi için
visibility
öğesine animasyon ekleme
Hareket animasyonları uygulamaya başladığımda erişilebilirliği göz önünde bulundurarak başlamak istiyorum.
Erişilebilir hareket
Herkes kaydırarak açma hareketi deneyimini istemez. Çözümümüzde bu tercih, medya sorgusundaki 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) temsil eder.
#sidenav-open {
--duration: .6s;
}
@media (prefers-reduced-motion: reduce) {
#sidenav-open {
--duration: 1ms;
}
}
Artık kullanıcı, yan gezinme menüsünün açılmasını ve kapanmasını tercih ettiğinde, hareketi azaltmayı seçerse öğeyi hareketsiz durumdayken anında görüntüye getiririm.
Geçiş, dönüştürme, çeviri
Yan gezinme menüsü kapalı (varsayılan)
Mobil cihazlarda kenar çubuğumuzun varsayılan durumunu ekran dışında olacak şekilde ayarlamak için öğeyi transform: translateX(-110vw)
ile konumlandırıyorum.
Yan gezinme menüsünün box-shadow
öğesinin gizliyken ana görüntü alanını gözetlemesini önlemek için -100vw
öğesinin tipik ekran dışı koduna 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 menüsü
#sidenav
öğesi :target
ile eşleştiğinde translateX()
konumunu ana sayfa 0
olarak ayarlayın ve URL karması değiştiğinde CSS'nin öğeyi -110vw
dış konumundan var(--duration)
üzerinde 0
"içinde" konumuna kaydırdığına bakın.
@media (max-width: 540px) {
#sidenav-open:target {
visibility: visible;
transform: translateX(0);
transition:
transform var(--duration) var(--easeOutExpo);
}
}
Geçiş görünürlüğü
Artık amaç, sistemlerin ekran dışındaki bir menüye odaklanmaması için menüyü görünmezken ekran okuyuculardan gizlemek. Bunu, :target
değiştiğinde görünürlük geçişi ayarlayarak yapıyorum.
- İçeri girerken görünürlüğü geçişli olarak göstermeyin. Öğenin kaydırılarak geldiğini ve odağı kabul ettiğini görebilmem için hemen görünür olmalıdır.
- Görünürlük geçişini yapın ancak geçişin sonunda
hidden
olarak görünmesi için geçişi geciktirin.
Erişilebilirlik kullanıcı deneyimi iyileştirmeleri
Bağlantılar
Bu çözüm, durumun yönetilebilmesi için URL'nin değiştirilmesini gerektirir.
Burada doğal olarak <a>
öğesi kullanılmalıdır. Bu öğe, ücretsiz olarak bazı güzel erişilebilirlik özelliklerine sahiptir. Etkileşimli öğelerimizi, amacı açıkça 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, fareyle üzerine gelme stillerimizi odak ile de paylaşarak hızlı bir şekilde kapsayıcı olmamızı sağlar.
.hamburger:is(:hover, :focus) svg > line {
stroke: hsl(var(--brandHSL));
}
JavaScript ekleme
Kapatmak için escape
tuşuna basın
Klavyenizdeki Escape
tuşu menüyü kapatıyor, değil mi? Kabloları bağlayalım.
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 kapat düğmesine aşağıdaki JavaScript'i satır içi olarak 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ırır ve menünün hiç açılmamış gibi görünmesini sağlar.
Focus UX
Sonraki snippet, açıldıktan veya kapandıktan sonra açık ve kapalı düğmelerine odaklanmamıza yardımcı olur. Geçiş yapmayı 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 menüsü açıldığında kapat düğmesine odaklanın. Yan gezinme menüsü kapandığında açık düğmesine odaklanın. Bunu, JavaScript'te öğede focus()
'yi çağırarak yapıyorum.
Sonuç
Bunu nasıl yaptığımı öğrendiğinize göre, siz ne yapardınız? Bu, eğlenceli bir bileşen mimarisi oluşturur. 1. sürümü yuvalarla kim yapacak? 🙂
Yaklaşımlarımızı çeşitlendirelim ve web'de uygulama geliştirmenin tüm yollarını öğrenelim. Bir Glitch oluşturun ve benimle tweet'de paylaşın. Topluluk remiksleri bölümüne ekleyeceğim.
Topluluk remiksleri
- Özel öğelerle @_developit: demo ve kod
- HTML/CSS/JS ile @mayeedwin1: demo ve kod
- @a_nurella'nın Glitch remiksiyle: demo ve kod
- HTML/CSS/JS ile @EvroMalarkey: demo ve kod