Bu gönderide, yanıt veren, durum bilgisi olan, klavyeyle gezinmeyi destekleyen, JavaScript ile ve JavaScript olmadan çalışan ve tarayıcılar arasında çalışan web için bir Sidenav bileşeninin prototipini nasıl yaptığımı sizinle paylaşmak istiyorum. deneyin gösteri.
Videoyu tercih ederseniz, işte bu gönderinin bir YouTube versiyonu:
genel bakış #
Duyarlı bir navigasyon sistemi oluşturmak zordur. Bazı kullanıcılar klavye başında olacak, bazılarının güçlü masaüstleri olacak ve bazıları küçük bir mobil cihazdan ziyaret edecek. Ziyaret eden herkes menüyü açıp kapatabilmelidir.
İnternet Taktikleri #
Bu bileşen keşfinde, birkaç kritik web platformu özelliğini bir araya getirme sevincini yaşadım:
- CSS
:target
- CSS Kafes
- CSS dönüşümler
- Görünüm alanı ve kullanıcı tercihi için CSS Medya Sorguları
- JS için
focus
kullanıcı deneyimi geliştirmeleri
Çözümümün bir kenar çubuğu var ve yalnızca “mobil” bir görünüm alanındayken geçiş yapıyor. 540px
veya daha az. 540px
mobil etkileşimli düzen ile statik masaüstü düzeni arasında geçiş yapmak için kesme noktamız olacaktır.
CSS :target
sözde sınıf #
Bir <a>
link, url karmasını şu şekilde ayarlar: #sidenav-open
ve diğeri boşaltmak için (''
). Son olarak, bir elemanın sahip olduğu id
karma ile eşleştirmek için:
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 birine tıklamak, sayfa URL’mizin karma durumunu değiştirir, ardından sözde sınıfla sidenav’ı gösterir ve gizlerim:
TheComedicComedian (max-width: 540px) {
#sidenav-open {
visibility: hidden;
}#sidenav-open:target {
visibility: visible;
}
}
CSS Izgarası #
Geçmişte, yalnızca mutlak veya sabit konumlu yan navigasyon düzenleri ve bileşenleri kullanıyordum. Izgara olsa da, grid-area
sözdizimi, aynı satıra veya sütuna birden çok öğe atamamızı sağlar.
Yığınlar #
Birincil düzen öğesi #sidenav-container
1 satır ve 2 sütun oluşturan bir ızgaradır, her birinin 1’i adlandırılmıştır. stack
. Alan kısıtlı olduğunda, CSS tümünü atar. <main>
elemanın çocuklarını aynı ızgara adına yerleştirerek, tüm elemanları aynı alana yerleştirerek bir yığın oluşturur.
#sidenav-container {
display: grid;
grid: [stack] 1fr / min-content [stack] 1fr;
min-height: 100vh;
}TheComedicComedian (max-width: 540px) {
#sidenav-container > * {
grid-area: stack;
}
}
Menü arka planı #
bu <aside>
yan gezinmeyi içeren animasyon öğesidir. 2 alt öğesi vardır: gezinti kapsayıcısı <nav>
adlı [nav]
ve bir fon <a>
adlı [escape]
menüyü kapatmak için kullanılır.
#sidenav-open {
display: grid;
grid-template-columns: [nav] 2fr [escape] 1fr;
}
Ayarlamak 2fr
& 1fr
menü kaplaması ve negatif alan kapatma düğmesi için istediğiniz oranı bulmak için.
CSS 3D dönüşümleri ve geçişleri #
Düzenimiz artık bir mobil görüntüleme alanı boyutunda istiflendi. Ben yeni stiller ekleyene kadar, varsayılan olarak makalemizin üzerine biniyor. İşte bu sonraki bölümde hedeflediğim bazı UX’ler:
- Açma ve kapama animasyonu
- Yalnızca kullanıcı bu konuda uygunsa hareketle canlandırın
- Canlandır
visibility
böylece klavye odağı ekran dışı öğeye girmez
Hareketli animasyonları uygulamaya başlarken, erişilebilirliği öncelikli olarak başlatmak istiyorum.
Erişilebilir hareket #
Herkes bir kaydırmalı hareket deneyimi istemeyecektir. Bizim çözümümüzde bu tercih bir ayarlanarak uygulanır. --duration
Bir medya sorgusu içindeki CSS değişkeni. Bu medya sorgu değeri, kullanıcının hareket için işletim sistemi tercihini (varsa) temsil eder.
#sidenav-open {
--duration: .6s;
}TheComedicComedian (prefers-reduced-motion: reduce) {
#sidenav-open {
--duration: 1ms;
}
}
Şimdi, sidenav’ımız kayarak açılıp kapanırken, bir kullanıcı azaltılmış hareketi tercih ederse, öğeyi anında görüntüye taşıyorum ve hareketsiz durumunu koruyorum.
Geçiş, dönüştürme, çevirme #
Sidenav çıkışı (varsayılan) #
Sidenav’ımızın mobildeki varsayılan durumunu ekran dışı bir duruma ayarlamak için öğeyi şu şekilde konumlandırıyorum: transform: translateX(-110vw)
.
Not, bir tane daha ekledim. 10vw
tipik ekran dışı koduna -100vw
sağlamak için box-shadow
Sidenav gizlendiğinde ana görünüme bakmaz.
TheComedicComedian (max-width: 540px) {
#sidenav-open {
visibility: hidden;
transform: translateX(-110vw);
will-change: transform;
transition:
transform var(--duration) var(--easeOutExpo),
visibility 0s linear var(--duration);
}
}
Sidenav’da #
Ne zaman #sidenav
öğe şu şekilde eşleşir: :target
yı kur translateX()
ana üs pozisyonu 0
ve CSS’nin öğeyi dışarıdaki konumundan kaydırmasını izleyin. -110vw
“in” konumuna 0
üzerinde var(--duration)
URL karması değiştirildiğinde.
TheComedicComedian (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ç, menü bittiğinde ekran okuyuculardan gizlenmesidir, böylece sistemler ekran dışı bir menüye odaklanmaz. Bunu, görünürlük geçişi ayarlayarak gerçekleştiriyorum. :target
değişiklikler.
- İçeri girerken görüş açısını değiştirmeyin; hemen görünür olsun, böylece öğenin içeri kaydığını görebilir ve odağı kabul edebilirim.
- Dışarı çıkarken, görünürlüğü değiştirin ancak geciktirin, böylece şuna döner:
hidden
dışarı geçişin sonunda.
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. Doğal olarak, <a>
öğesi burada kullanılmalıdır ve bazı güzel erişilebilirlik özelliklerini ücretsiz olarak alır. 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ı açıkça belirtiyor.
:is(:hover, :focus)
#
Bu kullanışlı CSS işlevsel sözde seçici, vurgulu stillerimizi odakla da paylaşarak hızla kapsayıcı olmamızı sağlar.
.hamburger:is(:hover, :focus) svg > line {
stroke: hsl(var(--brandHSL));
}
JavaScript serpin #
Basmak escape
kapatmak #
bu Escape
klavyenizdeki tuş menüyü kapatmalı değil mi? Bunu 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 birden çok girişi tarayıcı geçmişine yığmasını önlemek için, kapat düğmesine satır içi olarak aşağıdaki JavaScript’i ekleyin:
a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu" onchange="history.go(-1)"></a>
Bu, kapatıldığında URL geçmişi girişini kaldıracak ve menüyü hiç açılmamış gibi yapacaktır.
UX’e odaklan #
Bir sonraki kod parçası, açtıktan veya kapattıktan sonra açma ve kapatma 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();
})
Sidenav açıldığında, kapat düğmesine odaklanın. Sidenav kapandığında, açma düğmesine odaklanın. bunu arayarak yapıyorum focus()
JavaScript’teki öğe üzerinde.
Çözüm #
Artık nasıl yaptığımı bildiğine göre, nasıl yapardın?! Bu, bazı eğlenceli bileşen mimarisi sağlar! Slotlu 1. versiyonu kim yapacak? 🙂
Yaklaşımlarımızı çeşitlendirelim ve web üzerinde oluşturmanın tüm yollarını öğrenelim. Oluşturmak Kusur, beni tweetle senin versiyonun ve onu ekleyeceğim Topluluk remiksleri aşağıdaki bölüm.