JavaScript, jQuery

jQuery로 탭 메뉴 만들기 – 초보자도 10분 만에 완성하는 실습 가이드

jonbeo 2025. 8. 13. 09:59
반응형

 

 

안녕하세요 😊
이번 글에서는 jQuery를 사용해 탭(Tab) 메뉴를 만들어보겠습니다.
탭 메뉴는 한 화면에서 콘텐츠를 구분해 보여줄 때 가장 많이 쓰이는 UI 패턴입니다.
기본 구조 → 스타일 → jQuery 로직 순서로 차근차근 진행하고,
마지막엔 접근성(ARIA)애니메이션/딥링크(해시) 까지 확장해보겠습니다.


1) 기본 HTML 마크업

탭은 보통 탭 버튼 목록 + 패널 영역으로 이루어집니다.

<!-- 탭 버튼 -->
<ul class="tabs" role="tablist">
  <li><button role="tab" id="tab-1" aria-controls="panel-1" aria-selected="true">공지사항</button></li>
  <li><button role="tab" id="tab-2" aria-controls="panel-2" aria-selected="false">이벤트</button></li>
  <li><button role="tab" id="tab-3" aria-controls="panel-3" aria-selected="false">FAQ</button></li>
</ul>

<!-- 탭 패널 -->
<div class="tab-panels">
  <section role="tabpanel" id="panel-1" aria-labelledby="tab-1">공지사항 내용…</section>
  <section role="tabpanel" id="panel-2" aria-labelledby="tab-2" hidden>이벤트 내용…</section>
  <section role="tabpanel" id="panel-3" aria-labelledby="tab-3" hidden>FAQ 내용…</section>
</div>
  • role, aria-* 속성으로 스크린리더에서도 의미가 전달되도록 합니다.
  • 처음에는 첫 번째 패널만 보이고, 나머지는 hidden 처리합니다.

2) 기본 CSS 스타일

보기 좋고, 클릭 영역이 넉넉한 탭을 만듭니다.

.tabs {
  display: flex; gap: 8px; padding: 0; margin: 0 0 12px; list-style: none;
}
.tabs button[role="tab"] {
  padding: 8px 16px; border: 1px solid #ddd; background: #f8f9fa; cursor: pointer;
  border-radius: 8px; font-weight: 600;
}
.tabs button[aria-selected="true"] {
  background: #1abc9c; color: #fff; border-color: #1abc9c;
}
.tabs button:focus-visible { outline: 3px solid #8fdccf; }

.tab-panels section { padding: 12px; border: 1px solid #eee; border-radius: 8px; }

 


3) jQuery 로직 (기본 탭 전환)

아래 스크립트로 클릭한 탭의 패널만 표시합니다.

<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script>
  $(function () {
    $('.tabs [role="tab"]').on('click', function () {
      const $btn = $(this);
      const target = $btn.attr('aria-controls'); // 연결된 패널 id

      // 1) 탭 상태 초기화
      $('.tabs [role="tab"]').attr('aria-selected', 'false');
      // 2) 현재 탭 활성화
      $btn.attr('aria-selected', 'true');

      // 3) 모든 패널 숨기기
      $('[role="tabpanel"]').attr('hidden', true);
      // 4) 대상 패널 보이기
      $('#' + target).removeAttr('hidden');
    });
  });
</script>

 

포인트

  • aria-selectedhidden을 토글하여 접근성과 가시성을 동시에 관리합니다.
  • DOM 탐색은 가급적 역할/속성 기반으로 선택해 유지보수에 유리하게 합니다.

4) 부드러운 전환(슬라이드/페이드) 추가

패널을 숨길 때 hidden 대신 애니메이션을 주고, 완료 후 hidden으로 마무리합니다.

<script>
  $(function () {
    const $tabs = $('.tabs [role="tab"]');
    const $panels = $('[role="tabpanel"]');

    $tabs.on('click', function () {
      const $btn = $(this);
      const targetId = $btn.attr('aria-controls');
      const $target = $('#' + targetId);

      // 탭 상태
      $tabs.attr('aria-selected', 'false');
      $btn.attr('aria-selected', 'true');

      // 애니메이션: 보이는 패널만 페이드아웃 → 숨김 → 대상 페이드인
      const $visible = $panels.filter(':not([hidden])');

      if ($visible.length && $visible.attr('id') !== targetId) {
        $visible.stop(true, true).fadeOut(150, function () {
          $visible.attr('hidden', true).show(); // hidden 적용 후 display 상태 복원
          $target.hide().removeAttr('hidden').fadeIn(150);
        });
      } else if ($target.is('[hidden]')) {
        $target.hide().removeAttr('hidden').fadeIn(150);
      }
    });
  });
</script>
  • jQuery의 fadeIn/fadeOut으로 부드러운 사용자 경험을 제공합니다.
  • .stop(true, true)연속 클릭 시 큐 누적 방지합니다.

5) 키보드 접근성(좌/우 화살표)

키보드로 탭 이동이 가능하도록 확장합니다.

<script>
  $(function () {
    const $tabs = $('.tabs [role="tab"]');

    $tabs.on('keydown', function (e) {
      const idx = $tabs.index(this);
      if (e.key === 'ArrowRight') {
        $tabs.eq((idx + 1) % $tabs.length).focus().click();
      } else if (e.key === 'ArrowLeft') {
        $tabs.eq((idx - 1 + $tabs.length) % $tabs.length).focus().click();
      }
    });
  });
</script>
  • 키보드 사용자를 배려한 접근성 강화입니다.

6) URL 해시로 딥링크(직접 링크) 지원

#panel-2로 접속하면 자동으로 해당 탭을 열어줍니다.

<script>
  $(function () {
    function openByHash() {
      const hash = window.location.hash.replace('#', '');
      if (!hash) return;
      const $panel = $('#' + hash + '[role="tabpanel"]');
      if ($panel.length) {
        const tabId = $panel.attr('aria-labelledby');
        $('#' + tabId).trigger('click');
      }
    }

    // 최초 진입/뒤로가기 시 반영
    openByHash();
    $(window).on('hashchange', openByHash);

    // 탭 클릭 시 해시 업데이트
    $('.tabs [role="tab"]').on('click', function () {
      const panelId = $(this).attr('aria-controls');
      history.replaceState(null, '', '#' + panelId);
    });
  });
</script>
  • 검색/공유 시 특정 탭을 바로 열어 UX를 향상합니다.

7) 자주 하는 실수 & 팁

  • display:none만 토글하고 ARIA를 갱신하지 않으면 스크린리더 접근성 저하
  • 탭 버튼을 <a>로 만들 땐 href="#panel-1" 사용 + 기본 스크롤 방지 주의
  • 콘텐츠가 많다면 초기 렌더 시 첫 패널만 DOM에 넣고, 나머지는 AJAX/지연 로딩 고려
  • 모바일에서는 탭 버튼을 가로 스크롤 가능하게 만들면 긴 라벨도 깔끔

✅ 마무리

기본 탭 → 접근성 → 애니메이션 → 딥링크까지
실무에서 바로 쓰는 탭 메뉴를 완성하였습니다.
이 패턴은 상품 상세/대시보드/설정 화면 등 다양한 곳에 응용하실 수 있습니다.
프로젝트에 맞게 클래스명·효과·데이터 로딩 방식만 바꿔 바로 활용해보세요! 😊

반응형