Duyarlı bir yan gezinme paneli oluşturmaya dair temel bir genel bakış
Bu gönderide, web için Sidenav bileşeninin prototipini nasıl oluşturduğumu, duyarlı, durum bilgili, klavyeyle gezinmeyi destekliyor, JavaScript ile ve JavaScript olmadan çalışıyor, ve tüm tarayıcılarda çalışır. Demoyu deneyin.
Video kullanmayı tercih ederseniz bu gönderinin YouTube versiyonunu kullanabilirsiniz:
Genel Bakış
Duyarlı bir gezinme sistemi oluşturmak zordur. Bazı kullanıcılar klavyede, Bazıları güçlü masaüstü bilgisayarlara sahipken 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ç kritik web platformu özelliğini bir araya getirmekten keyif aldım:
- CSS
:target
- CSS ızgarası
- 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 bu özellik yalnızca "mobil" durumdayken geçiş yapıyor 540px
veya daha az görüntü alanı.
540px
, mobil etkileşimli düzen ile statik masaüstü düzeni arasında geçiş yapmak için kullandığımız ayrılma noktamız olacak.
CSS :target
sözde sınıfı
<a>
bağlantısı, URL karmasını #sidenav-open
, diğeri de boş (''
) olarak ayarlar.
Son olarak, bir öğe karmayla eşleşecek id
etiketine 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. kenardaki gezinmeyi gösterip gizlediğim yapay bir sınıfla:
@media (max-width: 540px) {
#sidenav-open {
visibility: hidden;
}
#sidenav-open:target {
visibility: visible;
}
}
CSS Izgarası
Eskiden yalnızca mutlak veya sabit konum kullanıyordum.
yan gezinme düzenlerini ve bileşenlerini içerir. Ancak grid-area
söz dizimiyle ızgara
aynı satıra veya sütuna birden fazla öğe atamamızı sağlar.
Gruplar
Birincil düzen öğesi #sidenav-container
, 1 satır ve 2 sütun oluşturan bir ızgaradır.
Her birinden 1 tanesi stack
olarak adlandırıldı. Alan kısıtlı olduğunda CSS, <main>
öğesinin tüm
alt öğeleri aynı ızgara adına yerleştirerek, tüm öğeler aynı alana yerleştirilerek bir yığın oluşturuyor.
#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 animasyon öğesidir. İçinde
2 alt öğe: [nav]
adlı <nav>
gezinme kapsayıcısı ve <a>
arka planı
Bu menü, menüyü kapatmak için kullanılan [escape]
adlı bir uzantıya sahip.
#sidenav-open {
display: grid;
grid-template-columns: [nav] 2fr [escape] 1fr;
}
Ayarlayın: 2fr
ve Menü yer paylaşımı ve negatif alanı kapat düğmesi için istediğiniz oranı bulmak üzere 1fr
tuşlarına basın.
CSS 3D dönüşümleri ve geçişler
Düzenimiz artık mobil görüntü alanı boyutunda üst üste dizilmiş. Ben yeni stiller ekleyene kadar varsayılan olarak makalemizle yer paylaşımlı oluyor. Sonraki bölümde ele aldığım kullanıcı deneyiminden bazıları şunlar:
- Açıp kapatarak animasyon
- Yalnızca kullanıcı buna izin veriyorsa hareketle animasyon kullan
- Klavye odağının ekran dışı öğeye girmemesi için
visibility
animasyonu canlandırılır
Hareket animasyonlarını uygulamaya başladığımda, öncelikle erişilebilirlikle başlamak istiyorum.
Erişilebilir hareket
Herkes kayan hareket deneyimi istemez. Çözümümüzde bu tercih
değeri, medya sorgusu içindeki bir --duration
CSS değişkeni ayarlanarak uygulanır. Bu medya sorgusu değeri şunu temsil eder:
Kullanıcının işletim sistemi tercihi (varsa).
#sidenav-open {
--duration: .6s;
}
@media (prefers-reduced-motion: reduce) {
#sidenav-open {
--duration: 1ms;
}
}
Yan gezinme panelimiz açık ve kapalı kaydırılırken, kullanıcı daha az hareketi tercih ederse Öğeyi anında görünüme taşıyarak hareket etmeden bu durumunu koruyorum.
Geçiş, dönüştürme, çeviri
Yana gezinme (varsayılan)
Mobil cihazda kenar gezinmemizin varsayılan durumunu ekran dışı duruma ayarlamak için:
Öğeyi transform: translateX(-110vw)
ile konumlandırıyorum.
Not: -100vw
olan tipik ekran dışı koduna bir 10vw
daha ekledim.
gizlendiğinde yan gezinme bölmesinin box-shadow
ana görüntü alanına gözükmemesini sağlamak için.
@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);
}
}
Yandaki bölmede
#sidenav
öğesi :target
olarak eşleştiğinde translateX()
konumunu 0
ana tabanı olarak ayarlayın.
CSS'nin öğeyi -110vw
konumundan "içinde" konumuna kaydırmasını izleyin
URL karması değiştirildiğinde, var(--duration)
yerine 0
konumu.
@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ü kullanıma hazır olmadığında menünün ekran okuyuculardan gizlenmesini sağlamaktır.
Böylece sistemler ekran dışındaki bir menüye odaklanmıyor. Bunu başarmak için
görünürlük geçişi :target
değiştiğinde.
- İçeri giderken görünürlüğü değiştirmeyin; hemen görünür olması gerekir, böylece öğenin kaydığını görebilir ve odağı kabul edebilirim.
- Dışarı çıkarken görünürlüğü değiştirin ancak geçişi geciktirin. Böylece, geçişin sonunda
hidden
dönüşür hale gelir.
Erişilebilirlikle ilgili kullanıcı deneyimi geliştirmeleri
Bağlantılar
Bu çözüm, durumun yönetilmesi için URL'nin değiştirilmesine dayanır.
Doğal olarak <a>
öğesi burada kullanılmalıdır. Bu öğe için bazı erişilebilirlik özellikleri
özellikleri ücretsiz olarak sunar. 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 kullanım amacını net bir şekilde belirtiyor.
:is(:hover, :focus)
Bu kullanışlı CSS işlevsel sözde seçicisi, hızlı bir şekilde kapsayıcı olmamızı sağlar bunları odaklayarak da paylaşabilirsiniz.
.hamburger:is(:hover, :focus) svg > line {
stroke: hsl(var(--brandHSL));
}
JavaScript'e ekleme
Kapatmak için escape
tuşlarına basın
Klavyenizdeki Escape
tuşu menüyü kapatmalı, doğru mu? Bunu kabloyla açalı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 birden fazla öğeyi yığılmasını önlemek için geçmişine eklemek için aşağıdaki JavaScript satır içi kodunu ekleyin: kapat düğmesi:
<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu" onchange="history.go(-1)"></a>
Bu işlem, kapanışta URL geçmişi girişini kaldıracak ve böylece menünün en az hiç açılmadı.
Kullanıcı deneyimine odaklanma
Sonraki snippet, açılış sayfası ve reklamdan sonra açma ve kapatma düğmelerine zaman alabilirler. 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 paneli açıldığında kapat düğmesine odaklanın. Yan gezinme paneli kapandığında
açma düğmesine odaklanıyorum. Bunu, JavaScript'teki öğede focus()
yöntemini çağırarak yapıyorum.
Sonuç
Şimdi bunu nasıl yaptığımı biliyorsun, şimdi nasıl yaparsın? Bu da eğlenceli bir bileşen mimarisi oluşturur. Slotlarla ilk sürümü kim yapacak? 🙂
Ürün ve hizmetlerinizi çeşitlendirmek için ve web üzerinde geliştirme yapmanın tüm yollarını öğreneceğiz. Bir Aksak oluşturun sürümünüzü tweet'le gönderin, Topluluk remiksleri bölümünü inceleyin.
Topluluk remiksleri
- Özel öğeler içeren @_developit: demo & kod
- HTML/CSS/JS ile @mayeedwin1: demo & kod
- Glitch Remix ile @a_nurella: demo ve kod
- HTML/CSS/JS ile @EvroMalarkey: demo & kod