Codelab: ساخت کامپوننت Sidenav

این کد لبه به شما می آموزد که چگونه یک جزء طرح بندی ناوبری جانبی کشویی پاسخگو در وب بسازید. ما کامپوننت را همانطور که پیش می‌رویم، با HTML، سپس CSS و سپس جاوا اسکریپت شروع می‌کنیم.

برای آشنایی با ویژگی‌های پلتفرم وب CSS که برای ساخت این مؤلفه انتخاب شده‌اند، پست وبلاگ من «ساخت مؤلفه Sidenav» را بررسی کنید.

برپایی

  1. روی Remix to Edit کلیک کنید تا پروژه قابل ویرایش باشد.
  2. app/index.html را باز کنید.

HTML

ابتدا، ملزومات تنظیمات HTML را دریافت کنید تا محتوا و تعدادی جعبه برای کار با آنها وجود داشته باشد.

HTML زیر را در تگ <body> رها کنید.

<aside></aside>
<main></main>

<aside> منوی پیمایش را به عنوان یک عنصر مکمل برای <main> نگه می دارد که محتوای صفحه اصلی را در خود نگه می دارد.

سپس آن عناصر معنایی را با بقیه محتوای صفحه پر می کنیم.

یک عنصر ناوبری، چند پیوند پیمایش و یک پیوند نزدیک در داخل عنصر <aside> اضافه کنید.

<aside>
  <nav>
    <h4>My</h4>
    <a href="#">Dashboard</a>
    <a href="#">Profile</a>
    <a href="#">Preferences</a>
    <a href="#">Archive</a>

    <h4>Settings</h4>
    <a href="#">Accessibility</a>
    <a href="#">Theme</a>
    <a href="#">Admin</a>
  </nav>

  <a href="#"></a>
</aside>

پیوندها در عناصر <nav> و عناصر <nav> در نوارهای جانبی <aside> عالی هستند. با این حال، کارهای بیشتری برای بهبود می توانیم انجام دهیم.

در عنصر محتوای اصلی، یک سرصفحه و یک مقاله اضافه کنید تا محتوای طرح بندی را به صورت معنایی نگه دارید.

<main>
  <header>
    <a href="#sidenav-open" class="hamburger">
      <svg viewBox="0 0 50 40">
        <line x1="0" x2="100%" y1="10%" y2="10%" />
        <line x1="0" x2="100%" y1="50%" y2="50%" />
        <line x1="0" x2="100%" y1="90%" y2="90%" />
      </svg>
    </a>
    <h1>Site Title</h1>
  </header>

  <article>
    {put some placeholder content here}
  </article>
</main>

هدر دارای پیوند باز منو است. کناری دکمه بستن دارد. به زودی عناصر را بر اساس اندازه ویو نمایش داده و پنهان خواهیم کرد.

در عنصر <article> ، یک جمله نگهدارنده جایگذاری کردیم. «» را با چیزهای خود جایگزین کنید، یا لورم ارائه شده در زیر را بچسبانید:

<h2>Totam Header</h2>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Cum consectetur, necessitatibus velit officia ut impedit veritatis temporibus soluta? Totam odit cupiditate facilis nisi sunt hic necessitatibus voluptatem nihil doloribus! Enim.</p>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>

<h3>Subhead Totam Odit</h3>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>

<h3>Subhead</h3>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>

این محتوا و طول آن چیزی است که باعث می شود صفحه زمانی که از ارتفاع نمای شما بیشتر شود قابل پیمایش باشد.

تا اینجا شما یک عنصر کناری، با ناوبری، پیوندها و راهی برای بستن نوار کناری اضافه کرده‌اید. شما همچنین یک هدر، راهی برای باز کردن sidenav و یک مقاله به عنصر اصلی اضافه کردید. این در حال حاضر تمیز، معنایی و تقریباً بی‌زمان است، اما ما می‌توانیم آن را برای همه تمیزتر و واضح‌تر کنیم. پیوند باز در sidenav می تواند به وضوح مشخص شود.

title ویژگی و aria-label به عنصر پیوند باز هدر اضافه کنید:

<a href="#sidenav-open" class="hamburger">
<a href="#sidenav-open" title="Open Menu" aria-label="Open Menu" class="hamburger">

نماد SVG باز نیز می تواند با وضوح بیشتری مشخص شود. ویژگی های زیر را به SVG در داخل عنصر پیوند باز اضافه کنید:

<svg viewBox="0 0 50 40">
<svg viewBox="0 0 50 40" role="presentation" focusable="false" aria-label="trigram for heaven symbol">

پیوند نزدیک در نوار کناری را می توان با وضوح بیشتری مشخص کرد. title ویژگی و aria-label به عنصر پیوند نزدیک sidenav اضافه کنید:

<a href="#"></a>
<a href="#" title="Close Menu" aria-label="Close Menu"></a>

CSS

زمان برای چیدمان عناصر محتوای اصلی و sidenav فرزندان مستقیم تگ <body> هستند، بنابراین این مکان خوبی برای شروع است.

CSS زیر را به css/sidenav.css اضافه کنید تا عنصر <body> بچه ها را نشان دهد.

body {
  display: grid;
  grid: [stack] 1fr / min-content [stack] 1fr;

  @media (max-width: 540px) {
    & > :matches(aside, main) {
      grid-area: stack;
    }
  }
}

این طرح اساساً می‌گوید: یک stack ردیف با نام با همه چیز در آن ایجاد کنید، و 2 ستون در آن سطر، که دومین آن stack نیز نامیده می‌شود. ستون 1 باید بر اساس حداقل نیازهای محتوایی خود اندازه شود و ستون 2 می تواند بقیه را اشغال کند. سپس، اگر در یک نمای محدود 540px یا کمتر هستید، نوار جانبی و عناصر محتوای اصلی را در یک ردیف و ستون قرار دهید، در نتیجه آنها در یک شبکه 1x1 روی هم قرار می گیرند.

با این عملکرد انباشته پاسخگو به عنوان پایه، اکنون می‌توانیم از وضعیت نوار URL استفاده کنیم تا نمایان بودن و سبک انتقال sidenav را تغییر دهیم.

عنصر <aside> را دوباره در app/index.html به روز کنید:

<aside>
<aside id="sidenav-open">

این CSS را قادر می سازد تا یک عنصر و هش URL را با هم تطبیق دهد. این برای استفاده :target مهم است. اکنون شناسه عنصر می تواند با هش URL که با تگ های <a> تنظیم می کنیم مطابقت داشته باشد.

به‌علاوه، برای هدف‌یابی آسان‌تر جاوا اسکریپت، شناسه‌هایی را برای عناصر کلیدی که نوار کناری را کنترل می‌کنند، اضافه کنید. ابتدا یک شناسه به لینک باز کردن sidenav اضافه کنید:

<a href="#sidenav-open" class="hamburger" title="Open Menu" aria-label="Open Menu">
<a href="#sidenav-open" id="sidenav-button" class="hamburger" title="Open Menu" aria-label="Open Menu">

سپس، یک شناسه به پیوند بستن sidenav اضافه کنید:

<a href="#" title="Close Menu" aria-label="Close Menu"></a>
<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu"></a>

این طرح‌بندی ماکرو پاسخ‌گوی <body> را تکمیل می‌کند، به علاوه ما را به نوار URL متصل می‌کند. بیا ادامه بدیم!

<aside> نیز دارای طرح بندی منظمی است. دارای 2 فرزند، یک <nav> که مولفه ای شبیه کاغذ است که به بیرون می رود، و یک عنصر پیوند <a> در حال بسته شدن که url را روی # تنظیم می کند. پیوند در سمت راست نوار کشویی کاغذ نامرئی است. به این دلیل است که مردم می توانند مؤلفه بصری را "کلیک" کنند تا آن را رد کنند.

CSS زیر را به css/sidenav.css اضافه کنید:

#sidenav-open {
  display: grid;
  grid-template-columns: [nav] 2fr [escape] 1fr;
}

من فکر می‌کردم که نسبت و نام‌ها در اینجا بسیار خوب هستند، جایی که شبکه می‌تواند بدرخشد و کنترل زیادی به طراح بدهد.

در مرحله بعد، باید محتوای اصلی را به صورت مشروط پوشش دهم و موقعیت خود را از طریق هر پیمایش سند حفظ کنم. این یک کار عالی برای position: sticky و برخی overscroll-behavior .

سبک های زیر را برای sidenav اضافه کنید:

#sidenav-open {
  display: grid;
  grid-template-columns: [nav] 2fr [escape] 1fr;

  @media (max-width: 540px) {
    position: sticky;
    top: 0;
    max-height: 100vh;
    overflow: hidden auto;
    overscroll-behavior: contain;

    visibility: hidden; /* not keyboard accessible when closed */
  }
}

این سبک‌ها تضمین می‌کنند که نوار کناری ارتفاع درگاه دید است، به صورت عمودی پیمایش می‌کند و حاوی اسکرول است. بسیار مهم است، این عنصر را پنهان می کند. به‌طور پیش‌فرض، وقتی نمای پورت 540px یا کوچک‌تر است، آن sidenav را پنهان کنید. مگر اینکه!

یک شبه انتخابگر :target به عنصر #sidenav-open اضافه کنید:

#sidenav-open {

  @media (max-width: 540px) {

    &:target {
      visibility: visible;
    }
  }
}

وقتی شناسه آن عنصر و نوار URL یکسان است، visibility را روی visible تنظیم کنید. پیش بروید و پس از پیمایش صفحه، منوی کناری را باز کنید، یا در حالی که نوار کناری باز است، صفحه را اسکرول کنید. شما چی فکر میکنید؟

CSS زیر را به پایین app/sidenav.css اضافه کنید:

#sidenav-button,
#sidenav-close {
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  user-select: none;
  touch-action: manipulation;

  @media (min-width: 540px) {
    display: none;
  }
}

این سبک‌ها دکمه‌های باز و بسته ما را هدف قرار می‌دهند، سبک‌های لمسی و لمسی آن‌ها را مشخص می‌کنند، و همچنین زمانی که درگاه‌های نمایش 540px یا بزرگ‌تر هستند، آنها را پنهان می‌کنند.

برای کمی استعداد، اجازه دهید تبدیل های CSS را با قابلیت دسترسی محترمانه اضافه کنیم. CSS زیر را به css/sidenav.css اضافه کنید:

#sidenav-open {
  --easeOutExpo: cubic-bezier(0.16, 1, 0.3, 1);
  --duration: .6s;

  ...

  @media (max-width: 540px) {
    ...

    transform: translateX(-110vw);
    will-change: transform;
    transition:
      transform var(--duration) var(--easeOutExpo),
      visibility 0s linear var(--duration);

    &:target {
      visibility: visible;
      transform: translateX(0);
      transition: transform var(--duration) var(--easeOutExpo);
    }
  }

  @media (prefers-reduced-motion: reduce) {
    --duration: 1ms;
  }
}
نمایشی از تعامل با و بدون مدت زمان اعمال شده بر اساس درخواست رسانه «ترجیحات-حرکت کاهش یافته».

مقداری جاوا اسکریپت بپاشید

کلید Escape باید منو را ببندد. این JS را به js/index.js اضافه کنید:

const sidenav = document.querySelector('#sidenav-open');

sidenav.addEventListener('keyup', e => {
  if (e.code === 'Escape') {
    document.location.hash = '';
  }
});

این به یک رویداد کلیدی در عنصر sidenav گوش می دهد. اگر Escape باشد، هش URL را خالی می‌کند و انتقال sidenav را خارج می‌کند.

بخش بعدی UX JS مدیریت تمرکز است. من می‌خواهم باز کردن و بسته شدن را آسان کنم، بنابراین منتظر می‌مانم تا sidenav یک نوع انتقال را تمام کند، سپس آن را در برابر هش URL بررسی می‌کنم تا مشخص کنم که داخل یا خارج است. سپس از جاوا اسکریپت استفاده می‌کنم تا فوکوس را روی دکمه‌ای که اخیراً فشار داده‌اند، تکمیل کنم.

جاوا اسکریپت زیر را به js/index.js اضافه کنید:

const closenav = document.querySelector('#sidenav-close');
const opennav = document.querySelector('#sidenav-button');

sidenav.addEventListener('transitionend', e => {
  if (e.propertyName !== 'transform') {
    return;
  }

  const isOpen = document.location.hash === '#sidenav-open';

  isOpen
    ? closenav.focus()
    : opennav.focus();
});

آن را امتحان کنید

  • برای پیش نمایش سایت، View App را فشار دهید. سپس تمام صفحه را فشار دهید تمام صفحه .

نتیجه

این یک جمع بندی برای نیازهایی است که من با کامپوننت داشتم. با خیال راحت از آن استفاده کنید، آن را با حالت جاوا اسکریپت به جای URL هدایت کنید و به طور کلی آن را مال خود کنید! همیشه موارد بیشتری برای اضافه کردن یا موارد استفاده بیشتری برای پوشش وجود دارد.

css/brandnav.css باز کنید تا سبک‌های غیر مرتبط با طرح‌بندی را که برای این مؤلفه اعمال کردم، بررسی کنید. احساس نمی‌کردم برای مجموعه ویژگی‌هایی که روی آن تمرکز می‌کردم مهم باشد، و امیدوار بودم که جدا کردن سبک‌ها از طرح‌بندی باعث تشویق کپی و چسباندن شود. ممکن است در آنجا یادگیری بیشتری برای شما وجود داشته باشد!

چگونه می توانید اجزای sidenav پاسخگوی اسلاید را ایجاد کنید؟ آیا تا به حال بیش از 1، مانند یکی در هر دو طرف دارید؟ من دوست دارم راه حل شما را در یک ویدیوی YouTube نشان دهم، مطمئن شوید که برای من توییت کنید یا با کد خود در YouTube نظر دهید، این به همه کمک می کند!