테두리, 리프트, 박스형 및 알약 스타일 변형이 포함된 CSS 전용 Tailwind CSS 탭입니다. 활성 상태 및 크기, JavaScript가 필요하지 않습니다. WCAG AA 액세스 가능하며 Django, HTMX, Laravel, React 및 모든 스택에서 작동합니다.
탭 구성 요소는 사용자가 페이지를 떠나지 않고도 전환할 수 있는 별도의 섹션으로 콘텐츠를 구성합니다. 시맨틱 HTML 및 라디오 입력 패턴으로 구축된 탭은 관련 정보를 그룹화하기 위한 직관적인 탐색 기능을 제공합니다. Frutjam 탭 시스템은 CSS 전용 또는 JavaScript 제어 등 다양한 크기, 스타일 및 레이아웃 방향을 지원하므로 대시보드, 문서 및 탭 인터페이스에 이상적입니다.
CSS 전용이며 JavaScript가 필요하지 않습니다. WCAG AA 액세스 가능 및 프레임워크에 구애받지 않음 — Django, HTMX, Laravel, React 및 모든 스택에서 작동합니다.
| 수업 | 유형 | 설명 |
|---|---|---|
| tabs | 베이스 | 탭 입력 및 콘텐츠 패널 그룹을 위한 컨테이너 |
| tab | 수정자 | 개별 탭 라디오 입력 |
| tab-content | 수정자 | 탭과 연결된 콘텐츠 패널 |
| tab-active | 수정자 | 탭에서 활성/선택 상태를 강제합니다(JS 제어 탭의 경우). |
| tab-disabled | 수정자 | 탭의 비활성화된 모양 |
| tabs-underline | 스타일 | 밑줄 표시 스타일 |
| tabs-lifted | 스타일 | 카드처럼 들어 올려진 탭 스타일 |
| tabs-box | 스타일 | 박스형 알약 스타일 탭 |
| tabs-vertical | 수정자 | 왼쪽 열에 탭이 있는 세로 탭 레이아웃 |
| tabs-end | 수정자 | 탭 행을 끝으로 정렬합니다(LTR에서는 오른쪽). |
| tabs-bottom | 수정자 | 콘텐츠 패널 아래에 탭을 배치합니다. |
| tabs-xs | 크기 | 매우 작은 탭 패딩 |
| tabs-sm | 크기 | 작은 탭 패딩 |
| tabs-md | 크기 | 중간 탭 패딩(기본값) |
| tabs-lg | 크기 | 대형 탭 패딩 |
| tabs-xl | 크기 | 초대형 탭 패딩 |
기본 사용법
기본 탭은 라디오 입력과 함께 간단한 밑줄 표시 스타일을 사용합니다. 각 tab 입력은 바로 뒤에 있는 tab-content 패널과 쌍을 이룹니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <div class="tabs"> <input type="radio" name="tabs-basic" class="tab" aria-label="Overview" checked> <div class="tab-content pt-4"> <p>Overview content: a high-level summary of features, metrics, or status. This panel is visible by default.</p> </div> <input type="radio" name="tabs-basic" class="tab" aria-label="Details"> <div class="tab-content pt-4"> <p>Details content: in-depth information such as configuration options, data breakdown, or extended documentation.</p> </div> <input type="radio" name="tabs-basic" class="tab" aria-label="Activity"> <div class="tab-content pt-4"> <p>Activity content: a timeline, event log, or recent changes relevant to this section.</p> </div> </div> |
탭 스타일
탭 표시줄의 시각적 스타일을 변경하려면 tabs-underline, tabs-box 또는 tabs-lifted를 사용하세요.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <div class="tabs tabs-underline"> <input type="radio" name="style-underline" class="tab" aria-label="Overview" checked> <div class="tab-content pt-4">Underline style — a colored bottom border marks the active tab against a full-width separator line.</div> <input type="radio" name="style-underline" class="tab" aria-label="Details"> <div class="tab-content pt-4">Details panel.</div> <input type="radio" name="style-underline" class="tab" aria-label="Activity"> <div class="tab-content pt-4">Activity panel.</div> </div> <div class="tabs tabs-box"> <input type="radio" name="style-box" class="tab" aria-label="Overview" checked> <div class="tab-content pt-4">Box style — the active tab gets a raised background inside a tinted pill container.</div> <input type="radio" name="style-box" class="tab" aria-label="Details"> <div class="tab-content pt-4">Details panel.</div> <input type="radio" name="style-box" class="tab" aria-label="Activity"> <div class="tab-content pt-4">Activity panel.</div> </div> <div class="tabs tabs-lifted"> <input type="radio" name="style-lifted" class="tab" aria-label="Overview" checked> <div class="tab-content p-4">Lifted style — the active tab appears as a card tab with borders that merge into the content panel below.</div> <input type="radio" name="style-lifted" class="tab" aria-label="Details"> <div class="tab-content p-4">Details panel.</div> <input type="radio" name="style-lifted" class="tab" aria-label="Activity"> <div class="tab-content p-4">Activity panel.</div> </div> |
탭 크기
레이아웃 밀도에 맞게 탭 패딩을 tabs-xs에서 tabs-xl로 조정하세요.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <div class="tabs tabs-underline tabs-xs"> <input type="radio" name="size-xs" class="tab" aria-label="Extra Small" checked> <div class="tab-content pt-3">Extra small tabs</div> <input type="radio" name="size-xs" class="tab" aria-label="Tab 2"> <div class="tab-content pt-3">Content</div> </div> <div class="tabs tabs-underline tabs-sm"> <input type="radio" name="size-sm" class="tab" aria-label="Small" checked> <div class="tab-content pt-3">Small tabs</div> <input type="radio" name="size-sm" class="tab" aria-label="Tab 2"> <div class="tab-content pt-3">Content</div> </div> <div class="tabs tabs-underline tabs-md"> <input type="radio" name="size-md" class="tab" aria-label="Medium" checked> <div class="tab-content pt-3">Medium tabs (default)</div> <input type="radio" name="size-md" class="tab" aria-label="Tab 2"> <div class="tab-content pt-3">Content</div> </div> <div class="tabs tabs-underline tabs-lg"> <input type="radio" name="size-lg" class="tab" aria-label="Large" checked> <div class="tab-content pt-3">Large tabs</div> <input type="radio" name="size-lg" class="tab" aria-label="Tab 2"> <div class="tab-content pt-3">Content</div> </div> <div class="tabs tabs-underline tabs-xl"> <input type="radio" name="size-xl" class="tab" aria-label="Extra Large" checked> <div class="tab-content pt-3">Extra large tabs</div> <input type="radio" name="size-xl" class="tab" aria-label="Tab 2"> <div class="tab-content pt-3">Content</div> </div> |
버튼이 있는 탭
tab을 btn과 결합하여 탭을 스타일 버튼으로 렌더링합니다. btn 클래스는 탭 선택 논리가 유지되는 동안 색상과 테두리 반경을 담당합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <div class="tabs gap-2"> <input type="radio" name="btn-tabs" class="tab btn btn-sm" aria-label="Home" checked> <div class="tab-content pt-4"> <p>Home — your primary landing panel with quick access to key actions and a summary view.</p> </div> <input type="radio" name="btn-tabs" class="tab btn btn-sm" aria-label="Profile"> <div class="tab-content pt-4"> <p>Profile — manage personal information, preferences, and account details.</p> </div> <input type="radio" name="btn-tabs" class="tab btn btn-sm" aria-label="Settings"> <div class="tab-content pt-4"> <p>Settings — configure notifications, privacy options, and connected integrations.</p> </div> </div> |
비활성화된 탭
탭과의 상호 작용을 방지하려면 tab-disabled 및 disabled 속성을 추가하세요.
1 2 3 4 5 6 7 8 9 10 | <div class="tabs tabs-underline"> <input type="radio" name="disabled-tabs" class="tab" aria-label="Available" checked> <div class="tab-content pt-4">This tab is active and accessible.</div> <input type="radio" name="disabled-tabs" class="tab tab-disabled" aria-label="Unavailable" disabled> <div class="tab-content pt-4">This content is not reachable.</div> <input type="radio" name="disabled-tabs" class="tab" aria-label="Another"> <div class="tab-content pt-4">Another available tab panel.</div> </div> |
수직 탭
tabs-vertical은 탭이 왼쪽 열에 있고 콘텐츠가 오른쪽 열을 채우는 그리드 레이아웃으로 전환합니다. 전체 높이 구분선이 열 사이에 자동으로 추가됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <div class="tabs tabs-vertical"> <input type="radio" name="vertical" class="tab" aria-label="General" checked> <div class="tab-content px-6 py-2"> <h3 class="font-semibold mb-1">General Settings</h3> <p>Manage your display name, language preference, and time zone.</p> </div> <input type="radio" name="vertical" class="tab" aria-label="Security"> <div class="tab-content px-6 py-2"> <h3 class="font-semibold mb-1">Security</h3> <p>Update your password, enable two-factor authentication, and review active sessions.</p> </div> <input type="radio" name="vertical" class="tab" aria-label="Notifications"> <div class="tab-content px-6 py-2"> <h3 class="font-semibold mb-1">Notifications</h3> <p>Choose which events trigger email, push, or in-app notifications.</p> </div> <input type="radio" name="vertical" class="tab" aria-label="Billing"> <div class="tab-content px-6 py-2"> <h3 class="font-semibold mb-1">Billing</h3> <p>View invoices, update your payment method, and manage your subscription plan.</p> </div> </div> |
하단 탭
tabs-bottom은 레이아웃을 뒤집어 콘텐츠가 탭 표시줄 위에 나타나도록 하며 모바일 스타일 탐색 모음이나 하단 도구 모음에 유용합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <div class="tabs tabs-bottom tabs-underline"> <input type="radio" name="bottom-tabs" class="tab" aria-label="Feed" checked> <div class="tab-content pb-4"> <p>Feed — latest posts and updates from people you follow.</p> </div> <input type="radio" name="bottom-tabs" class="tab" aria-label="Explore"> <div class="tab-content pb-4"> <p>Explore — discover trending topics, creators, and recommended content.</p> </div> <input type="radio" name="bottom-tabs" class="tab" aria-label="Saved"> <div class="tab-content pb-4"> <p>Saved — articles and posts you bookmarked for later.</p> </div> </div> |
탭이 끝에 정렬됨
tabs-end는 탭 표시줄을 컨테이너 오른쪽(끝)으로 밀어 보조 탐색이나 작업 메뉴에 유용합니다.
1 2 3 4 5 6 7 8 9 10 | <div class="tabs tabs-underline tabs-end"> <input type="radio" name="end-tabs" class="tab" aria-label="Week" checked> <div class="tab-content pt-4">Weekly view — aggregated metrics for the past 7 days.</div> <input type="radio" name="end-tabs" class="tab" aria-label="Month"> <div class="tab-content pt-4">Monthly view — trend analysis over the past 30 days.</div> <input type="radio" name="end-tabs" class="tab" aria-label="Year"> <div class="tab-content pt-4">Yearly view — annual summary and year-over-year comparison.</div> </div> |
JavaScript로 제어되는 탭
라디오가 아닌 패턴(예: 앵커 링크, 동적 콘텐츠)의 경우 JavaScript에서 선택한 탭에 tab-active를 추가하세요. 페어링된 tab-content는 .tab-active + .tab-content 선택기를 통해 표시됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <div class="tabs tabs-box" id="js-tabs"> <button class="tab tab-active" data-tab="0">Dashboard</button> <div class="tab-content pt-4">Dashboard panel — visible because this tab has <code>tab-active</code>.</div> <button class="tab" data-tab="1">Reports</button> <div class="tab-content pt-4">Reports panel.</div> <button class="tab" data-tab="2">Integrations</button> <div class="tab-content pt-4">Integrations panel.</div> </div> <script> document.querySelectorAll('#js-tabs .tab').forEach(tab => { tab.addEventListener('click', () => { document.querySelectorAll('#js-tabs .tab').forEach(t => t.classList.remove('tab-active')); tab.classList.add('tab-active'); }); }); </script> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import { useTabs } from 'frutjam/react' export default function TabsDemo() { const tabs = useTabs(0) return ( <div className="tabs tabs-box"> <button {...tabs.tabProps(0)}>Dashboard</button> <div {...tabs.panelProps(0)} className="tab-content pt-4">Dashboard panel.</div> <button {...tabs.tabProps(1)}>Reports</button> <div {...tabs.panelProps(1)} className="tab-content pt-4">Reports panel.</div> <button {...tabs.tabProps(2)}>Integrations</button> <div {...tabs.panelProps(2)} className="tab-content pt-4">Integrations panel.</div> </div> ) } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <script setup> import { ref } from 'vue' const active = ref(0) </script> <template> <div class="tabs tabs-box"> <button v-for="(label, i) in ['Dashboard', 'Reports', 'Integrations']" :key="i" class="tab" :class="{ 'tab-active': active === i }" :aria-selected="active === i" role="tab" @click="active = i" ></button> <div class="tab-content pt-4" :hidden="active !== 0">Dashboard panel.</div> <div class="tab-content pt-4" :hidden="active !== 1">Reports panel.</div> <div class="tab-content pt-4" :hidden="active !== 2">Integrations panel.</div> </div> </template> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <script> let active = $state(0) const labels = ['Dashboard', 'Reports', 'Integrations'] </script> <div class="tabs tabs-box"> {#each labels as label, i} <button class="tab" class:tab-active={active === i} aria-selected={active === i} role="tab" onclick={() => active = i} >{label}</button> <div class="tab-content pt-4" hidden={active !== i}>{label} panel.</div> {/each} </div> |
Claude Code, Cursor 또는 다른 AI 편집기를 사용하시나요?
Cherry MCP는 AI 편집기에 요청 시 정확한 탭 클래스 이름과 구조를 제공합니다. 더 이상 환각에 빠진 수업은 없습니다.