반응형
안녕하세요 😊
이번 글에서는 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-selected와 hidden을 토글하여 접근성과 가시성을 동시에 관리합니다.
- 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/지연 로딩 고려
- 모바일에서는 탭 버튼을 가로 스크롤 가능하게 만들면 긴 라벨도 깔끔
✅ 마무리
기본 탭 → 접근성 → 애니메이션 → 딥링크까지
실무에서 바로 쓰는 탭 메뉴를 완성하였습니다.
이 패턴은 상품 상세/대시보드/설정 화면 등 다양한 곳에 응용하실 수 있습니다.
프로젝트에 맞게 클래스명·효과·데이터 로딩 방식만 바꿔 바로 활용해보세요! 😊
반응형
'JavaScript, jQuery' 카테고리의 다른 글
JavaScript debounce vs throttle 차이 완벽 정리 – 부드럽고 빠른 웹을 위한 필수 개념 (2) | 2025.08.08 |
---|---|
jQuery로 드롭다운 메뉴 만들기 – 초보자도 가능한 간단한 실습 예제 (1) | 2025.08.04 |