Yan gezinme bileşeni oluşturma

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.

Masaüstünden mobil cihaza duyarlı düzen demosu
iOS ve Android'de açık ve koyu tema kapatıldı

Web Taktikleri

Bu bileşen keşfinde birkaç kritik web platformu özelliğini bir araya getirmekten keyif aldım:

  1. CSS :target
  2. CSS ızgarası
  3. CSS dönüşümleri
  4. Görüntü alanı ve kullanıcı tercihi için CSS Medya Sorguları
  5. 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;
  }
}

<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.

Oranı değiştirdiğinizde ne olacağını gösteren bir demo.

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;
  }
}
Süre uygulanan ve uygulanmayan etkileşimin demosu.

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

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>
Seslendirme ve klavye etkileşimi kullanıcı deneyiminin demosu.

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