모바일 메뉴로 쓰기 좋은 슬라이드 사이드바 메뉴 예제

👈 클릭해보세요
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item
- Menu Item

모바일 메뉴로 사용하기 좋은 왼쪽에서 스윽~ 하고 나오는 슬라이드 사이드바 메뉴를 Alpinejs 와 Tailwindcss 프레임워크를 이용해서 만든 예제입니다.

이 예제는 코드를 입력하고 저장만 하면 바로 퍼블리싱 되는 Essepage 에서 테스트 할 수 있도록 기록합니다.


1. 라이브러리 설치

알파인 js와 테일윈드 css를 사용할 수 있게 <essepage:head> 를 이용해 Essepage 에 불러옵니다.

<essepage:head>
  <script src="https://unpkg.com/alpinejs" defer></script>
  <script src="https://cdn.tailwindcss.com"></script>
</essepage:head>

2. 사이드바 메뉴 트리거 버튼

사이드바 메뉴를 트리거 시킬 수 있는 간단한 버튼을 하나 만듭니다.

<div x-data='{SlideMenuOpen: false}'>
  <button @click="SlideMenuOpen = !SlideMenuOpen"
    class="px-4 py-2 rounded-md bg-stone-300 text-stone-700 hover:bg-strone-400">
    사이드바 메뉴 Open
  </button>
</div>

3. 슬라이드 사이드 바 메뉴 만들기

Alpine 으로 동작하도록 SlideMenuOpen 이 정의된 상위 <div> 안에 슬라이드 사이드바 메뉴 컨텐츠를 추가합니다.

<div x-data='{SlideMenuOpen: false}'>
  <button @click="SlideMenuOpen = !SlideMenuOpen"
    class="px-4 py-2 rounded-md bg-stone-300 text-stone-700 hover:bg-strone-400">
    사이드바 메뉴 Open
  </button>

  <div class="fixed z-10 inset-0 w-screen h-screen bg-black bg-opacity-75"
    x-cloak x-show="SlideMenuOpen"
    x-transition:enter="transition ease-in-out duration-400"
    x-transition:enter-start="opacity-0"
    x-transition:enter-end="opacity-100"
    x-transition:leave="transition ease-in-out duration-300"
    x-transition:leave-start="opacity-100"
    x-transition:leave-end="opacity-0">

    <div class="absolute top-0 left-0 max-w-full h-screen p-4 bg-zinc-100 overflow-auto"
      x-cloak x-show="SlideMenuOpen" @click.outside="SlideMenuOpen = false"
      x-transition:enter="transform transition ease-in-out duration-300"
      x-transition:enter-start="-translate-x-full"
      x-transition:enter-end="translate-x-0"
      x-transition:leave="transform transition ease-in-out duration-200"
      x-transition:leave-start="translate-x-0"
      x-transition:leave-end="-translate-x-full">

      <div class="min-w-[200px] max-w-[300px]">
        <div class="mb-4 flex justify-end">
          <button type="button" @click="SlideMenuOpen = false">
            <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-arrow-left" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
              <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
              <line x1="5" y1="12" x2="19" y2="12"></line>
              <line x1="5" y1="12" x2="11" y2="18"></line>
              <line x1="5" y1="12" x2="11" y2="6"></line>
            </svg>
          </button>
        </div>

        <div>
          - Menu Item<br> - Menu Item<br> - Menu Item<br> - Menu Item<br> - Menu Item<br> - Menu Item<br> - Menu Item<br> - Menu Item
        </div>
      </div>
    </div>
  </div>
</div>

알파인과 테일윈드의 간편함과 강력함으로 슬라이드 사이드 바 메뉴가 만들어졌습니다. 이걸로도 충분하지만, 사이드 메뉴 뒤로 보이는 화면이 마우스로 스크롤 되지 않게 하도록 추가해보겠습니다.

4. 사이드 메뉴 뒷배경 스크롤 방지 😊

여러가지 방법들이 있겠지만, 여기에서는 HTML 태그의 구조 중 <body> 부분의 스크롤을 막는 방법으로 예를 듭니다.

x-data 안에 스크롤을 막는 preventScroll 함수와 사이드 메뉴가 없어지면 다시 스크롤 되게 하는 allowScroll 함수를 추가하고, 사이드 메뉴가 열리는 부분과 닫히는 부분에 각가 함수를 추가해줍니다.

<div x-data='{
  SlideMenuOpen: false,
  bodyElement: document.querySelector("body"),
  preventScroll() {
    this.bodyElement.style.overflow = "hidden";
  },
  allowScroll() {
    this.bodyElement.style.overflow = "auto";
  }
}'>
  <button @click='() => {preventScroll(); SlideMenuOpen = !SlideMenuOpen;}'
    class="px-4 py-2 rounded-md bg-stone-300 text-stone-700 hover:bg-strone-400">
    사이드바 메뉴 Open
  </button>

  <div class="fixed z-10 inset-0 w-screen h-screen bg-black bg-opacity-75"
    x-cloak x-show="SlideMenuOpen"
    x-transition:enter="transition ease-in-out duration-400"
    x-transition:enter-start="opacity-0"
    x-transition:enter-end="opacity-100"
    x-transition:leave="transition ease-in-out duration-300"
    x-transition:leave-start="opacity-100"
    x-transition:leave-end="opacity-0">

    <div class="absolute top-0 left-0 max-w-full h-screen p-4 bg-zinc-100 overflow-auto"
      x-cloak x-show="SlideMenuOpen" @click.outside='() => {preventScroll(); SlideMenuOpen = false;}'
      x-transition:enter="transform transition ease-in-out duration-300"
      x-transition:enter-start="-translate-x-full"
      x-transition:enter-end="translate-x-0"
      x-transition:leave="transform transition ease-in-out duration-200"
      x-transition:leave-start="translate-x-0"
      x-transition:leave-end="-translate-x-full">

      <div class="min-w-[200px] max-w-[300px]">
        <div class="mb-4 flex justify-end">
          <button type="button" @click="() => {preventScroll(); SlideMenuOpen = false";}>
            <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-arrow-left" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
              <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
              <line x1="5" y1="12" x2="19" y2="12"></line>
              <line x1="5" y1="12" x2="11" y2="18"></line>
              <line x1="5" y1="12" x2="11" y2="6"></line>
            </svg>
          </button>
        </div>

        <div>
          - Menu Item<br>- Menu Item<br>- Menu Item<br>- Menu Item<br>- Menu Item<br>- Menu Item<br>- Menu Item<br>- Menu Item
        </div>
      </div>
    </div>
  </div>
</div>

참조

슬라이드 메뉴를 표현하기 위해 사용된 Alpine Js 의 x-transition@click 이 궁금하신 분들은 아래 페이지를 참고하세요.

x-transition : https://alpinejs.dev/directives/transition

x-on : https://alpinejs.dev/directives/on


Made by Essepage with ❤️