Ir al contenido principal

Componente de pestañas

Última actualización:

Pestañas CSS Tailwind solo para CSS con variantes de borde, levantado, encuadrado y de estilo píldora. Estado y tamaños activos, no se requiere JavaScript. Accesible a WCAG AA, funciona con Django, HTMX, Laravel, React y cualquier pila.

Los componentes de las pestañas organizan el contenido en secciones separadas entre las que los usuarios pueden alternar sin salir de la página. Construidas con HTML semántico y patrones de entrada de radio, las pestañas brindan navegación intuitiva para agrupar información relacionada. El sistema de pestañas de Frutjam admite múltiples tamaños, estilos y direcciones de diseño (solo CSS o controlado por JavaScript), lo que lo hace ideal para paneles, documentación e interfaces con pestañas.

Solo CSS, no se requiere JavaScript. WCAG AA accesible e independiente del marco: funciona con Django, HTMX, Laravel, React y cualquier pila.

Clase Tipo Descripción
tabsBaseContenedor para un grupo de entradas de pestañas y paneles de contenido
tabModificadorEntrada de radio de pestaña individual
tab-contentModificadorPanel de contenido asociado a una pestaña
tab-activeModificadorFuerza el estado activo/seleccionado en una pestaña (para pestañas controladas por JS)
tab-disabledModificadorApariencia deshabilitada para una pestaña
tabs-underlineEstiloEstilo del indicador de subrayado
tabs-liftedEstiloEstilo de pestaña levantada tipo tarjeta
tabs-boxEstiloPestañas estilo pastilla en caja
tabs-verticalModificadorDiseño de pestañas verticales con pestañas en una columna del lado izquierdo
tabs-endModificadorAlinea la fila de pestañas hasta el final (a la derecha en LTR)
tabs-bottomModificadorColoca pestañas debajo del panel de contenido.
tabs-xsTamañoAcolchado con lengüeta extra pequeña
tabs-smTamañoAcolchado con pestañas pequeñas
tabs-mdTamañoRelleno de pestaña medio (predeterminado)
tabs-lgTamañoAcolchado de pestañas grandes
tabs-xlTamañoAcolchado con pestañas extragrandes

Uso básico

Las pestañas predeterminadas utilizan un estilo simple de subrayado activo con entradas de radio. Cada entrada tab se empareja con un panel tab-content inmediatamente después.

Overview content: a high-level summary of features, metrics, or status. This panel is visible by default.

Details content: in-depth information such as configuration options, data breakdown, or extended documentation.

Activity content: a timeline, event log, or recent changes relevant to this section.

html
 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>

Estilos de pestaña

Utilice tabs-underline, tabs-box o tabs-lifted para cambiar el estilo visual de la tira de pestañas.

Underline style — a colored bottom border marks the active tab against a full-width separator line.
Details panel.
Activity panel.
Box style — the active tab gets a raised background inside a tinted pill container.
Details panel.
Activity panel.
Lifted style — the active tab appears as a card tab with borders that merge into the content panel below.
Details panel.
Activity panel.
html
 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>

Tamaños de pestañas

Escale el relleno de pestañas de tabs-xs a tabs-xl para que coincida con la densidad de su diseño.

Extra small tabs
Content
Small tabs
Content
Medium tabs (default)
Content
Large tabs
Content
Extra large tabs
Content
html
 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>

Pestañas con botones

Combine tab con btn para representar las pestañas como botones con estilo. La clase btn se hace cargo de los colores y el radio del borde mientras se conserva la lógica de selección de pestañas.

Home — your primary landing panel with quick access to key actions and a summary view.

Profile — manage personal information, preferences, and account details.

Settings — configure notifications, privacy options, and connected integrations.

html
 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>

Pestañas deshabilitadas

Agregue tab-disabled y el atributo disabled para evitar la interacción con una pestaña.

This tab is active and accessible.
This content is not reachable.
Another available tab panel.
html
 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>

Pestañas verticales

tabs-vertical cambia a un diseño de cuadrícula con pestañas en una columna del lado izquierdo y el contenido ocupando la derecha. Se agrega automáticamente una línea separadora de altura completa entre las columnas.

General Settings

Manage your display name, language preference, and time zone.

Security

Update your password, enable two-factor authentication, and review active sessions.

Notifications

Choose which events trigger email, push, or in-app notifications.

Billing

View invoices, update your payment method, and manage your subscription plan.

html
 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>

Pestañas en la parte inferior

tabs-bottom invierte el diseño para que el contenido aparezca encima de la barra de pestañas, lo que resulta útil para barras de navegación de estilo móvil o barras de herramientas inferiores.

Feed — latest posts and updates from people you follow.

Explore — discover trending topics, creators, and recommended content.

Saved — articles and posts you bookmarked for later.

html
 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>

Pestañas alineadas al final

tabs-end empuja la tira de pestañas hacia la derecha (final) del contenedor, lo que resulta útil para navegación secundaria o menús de acción.

Weekly view — aggregated metrics for the past 7 days.
Monthly view — trend analysis over the past 30 days.
Yearly view — annual summary and year-over-year comparison.
html
 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>

Pestañas controladas por JavaScript

Para patrones que no son de radio (por ejemplo, enlaces de anclaje, contenido dinámico), agregue tab-active a la pestaña seleccionada en JavaScript. El tab-content emparejado se muestra a través del selector .tab-active + .tab-content.

Dashboard panel — visible because this tab has tab-active.
Reports panel.
Integrations panel.
 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>

¿Usando Claude Code, Cursor u otro editor de IA?

Cherry MCP le brinda a su editor de IA la estructura y los nombres exactos de las clases Cortina a la italiana según sea necesario. No más clases alucinadas.

Pruebe Cherry MCP