Dışa kayan duyarlı bir yan gezinme alanının nasıl oluşturulacağına ilişkin temel bir genel bakış
Bu yayında, web için duyarlı, durum bilgili, klavyeyle gezinmeyi destekleyen, JavaScript ile ve JavaScript olmadan çalışan ve tarayıcılarda çalışan bir Sidenav bileşeninin prototipini nasıl oluşturduğumu sizinle 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ır, bazıları güçlü masaüstü bilgisayarlara, 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, kritik web platformu özelliklerinden birkaçını bir araya getirmekten memnun oldum:
- CSS
:target
- CSS ızgarası
- CSS transforms
- Görüntü alanı ve kullanıcı tercihi için CSS Medya Sorguları
focus
kullanıcı deneyimi geliştirmeleri için JS
Çözümümün bir kenar çubuğu var ve yalnızca 540px
veya daha düşük bir "mobil" görüntü alanında geçiş yapıyor.
540px
, mobil etkileşimli düzen ile statik masaüstü düzeni arasında geçiş yapmak için ayrılma noktamız olacaktır.
CSS :target
sözde sınıfı
Bir <a>
bağlantısı, URL karmasını #sidenav-open
ve diğeri boş (''
) olarak ayarlar.
Son olarak, bir öğede karmayla eşleşecek 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ıklamak, sayfa URL'mizin karma durumunu değiştirir, ardından sahte bir sınıfla kenar gezinme çubuğunu gösterir ve gizlerim:
@media (max-width: 540px) {
#sidenav-open {
visibility: hidden;
}
#sidenav-open:target {
visibility: visible;
}
}
CSS Tablosu
Geçmişte, yalnızca mutlak veya sabit konumlu yan gezinme düzenleri ve bileşenleri kullanıyordum. Bununla birlikte ızgara, grid-area
söz dizimiyle aynı satır veya sütuna birden fazla öğe atamamıza olanak tanır.
Gruplar
#sidenav-container
birincil düzen öğesi, 1 satır ve 2 sütun oluşturan bir ızgaradır. Her sütundan 1 tanesi stack
olarak adlandırılmıştır. Alan kısıtlandığında, CSS <main>
öğesinin tüm alt öğelerini aynı ızgara adına atar ve tüm öğeleri aynı alana yerleştirerek 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 bölmesini içeren animasyon öğesidir. 2 alt öğesi vardır: [nav]
adlı <nav>
gezinme kapsayıcısı ve menüyü kapatmak için kullanılan [escape]
adlı <a>
arka plan.
#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
öğelerini ayarlayın.
CSS 3D dönüşümleri ve geçişleri
Düzenimiz artık mobil görüntü alanı boyutunda yığılmış durumda. Birkaç yeni stil ekleyene kadar, varsayılan olarak makalemizin üzerine yazılır. Bir sonraki bölümde ele almakta olduğum bazı kullanıcı deneyimi şunlar:
- Açılış ve kapanış animasyonu
- Animasyon yalnızca kullanıcının buna onay verdiği durumlarda hareketli
- Klavye odağının ekran dışı öğeye girmemesi için
visibility
animasyonu gösterilir
Hareket animasyonlarını uygulamaya başlarken, önceliği erişilebilirlikle başlamak istiyorum.
Erişilebilir hareket
Herkes kaydırmalı hareket deneyimi istemez. Çözümümüzde bu tercih, medya sorgusu 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) temsil eder.
#sidenav-open {
--duration: .6s;
}
@media (prefers-reduced-motion: reduce) {
#sidenav-open {
--duration: 1ms;
}
}
Şimdi yan gezinme çubuğumuz açılıp kapandığında, kullanıcı daha az hareket etmeyi tercih ederse öğeyi anında görüntüye taşıyorum ve hareketsiz haldeki durumunu koruyorum.
Geçiş, dönüştürme, çevirme
Yan taraftaki gezinme çubuğu (varsayılan)
Mobildeki yan gezinme çubuğumuzun varsayılan durumunu ekran dışı durumuna ayarlamak için öğeyi transform: translateX(-110vw)
ile konumlandırıyorum.
Yan gezinme bölmesinin box-shadow
öğesinin, gizlendiğinde ana görüntü alanına göz atmaması için -100vw
adlı tipik 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);
}
}
Kenar gezinme çubuğu
#sidenav
öğesi :target
olarak eşleştiğinde, translateX()
konumunu 0
ana tabanı olarak ayarlayın. CSS'nin, URL karması değiştirildiğinde öğeyi -110vw
olan çıkış konumundan 0
üzerinden "giriş" konumuna kaydırmasını izleyin.var(--duration)
@media (max-width: 540px) {
#sidenav-open:target {
visibility: visible;
transform: translateX(0);
transition:
transform var(--duration) var(--easeOutExpo);
}
}
Geçiş görünürlüğü
Amaç, bu menü kapalıyken ekran okuyuculardan gizlenmesini sağlamak.
Böylece sistemler odağı ekran dışı menüye odaklanmaz. Bunu, :target
değiştiğinde bir görünürlük geçişi ayarlayarak yapıyorum.
- İçeri girerken görünürlüğü değiştirmeyin. Öğenin içine kaydığı ve odağı kabul edebilmem için hemen görünür olun.
- Dışarı çıkarken görünürlüğü değiştirin ancak erteleyin, bu nedenle geçişin sonunda
hidden
olarak dönüyor.
Erişilebilirlik kullanıcı deneyimi iyileştirmeleri
Bağlantılar
Bu çözüm, durumun yönetilebilmesi için URL'nin değiştirilmesine dayanır.
Doğal olarak, <a>
öğesi burada kullanılmalıdır. Bazı güzel erişilebilirlik özellikleri ücretsiz olarak sunulur. Etkileşimli öğelerimizi, niyeti açıkça belirten 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 fare ve klavye işlevlerini açıkça belirtiyor.
:is(:hover, :focus)
Bu kullanışlı CSS işlevsel sözde seçici, fareyle üzerine gelme stillerimizi odakla da paylaşarak hızlı bir şekilde kapsayıcı olmamızı sağlıyor.
.hamburger:is(:hover, :focus) svg > line {
stroke: hsl(var(--brandHSL));
}
JavaScript üzerine yerleştir
Kapatmak için escape
tuşlarına basın
Klavyenizdeki Escape
tuşu menüyü kapatmalı, değil mi? Bunu kabloyla 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çık ve kapalı etkileşimin, tarayıcı geçmişinde birden fazla girişi yığmasını önlemek için kapat düğmesine aşağıdaki JavaScript satır içi kodunu 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ünür.
Kullanıcı deneyimine odaklanın
Sonraki snippet, aç veya kapandıktan sonra aç ve kapat düğmelerine odaklanmamıza yardımcı olur. Geçişi 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. Yan gezinme bölmesi kapandığında,
açık düğmeye odaklanın. Bunu JavaScript'teki öğede focus()
çağrısı yaparak yapıyorum.
Sonuç
Nasıl yaptığımı artık bildiğine göre sen ne yaparsın? Bu da bileşen mimarisini eğlenceli hale getiriyor. Slot'larla 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şturup versiyonunu tweet'le bana gönder, ardından bunu aşağıdaki Topluluk remiksleri bölümüne ekleyeceğim.
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