Skip to content

Tab - Vant 4

Tab

Intro

Used to switch between different content areas.

Install

Register component globally via app.use, refer to Component Registration for more registration ways.

js
import { createApp } from'vue'; import { Tab, Tabs } from'vant'; const app = createApp(); app.use(Tab); app.use(Tabs);

Usage

Basic Usage

The first tab is active by default, you can set v-model:active to active specified tab.

html
js
import { ref } from'vue'; exportdefault { setup() { const active = ref(0); return { active }; }, };

Match By Name

html
js
import { ref } from'vue'; exportdefault { setup() { const activeName = ref('b'); return { activeName }; }, };

Swipe Tabs

By default more than 5 tabs, you can scroll through the tabs. You can set swipe-threshold attribute to customize threshold number.

html

Disabled Tab

Use disabled prop to disable a tab.

html

Card Style

Tabs styled as cards.

html

Click Event

html
js
import { showToast } from'vant'; exportdefault { setup() { constonClickTab = ({ title }) => showToast(title); return { onClickTab, }; }, };

Sticky

In sticky mode, the tab nav will be fixed to top when scroll to top.

html

Shrink

In shrink mode, the tabs will be shrinked to the left.

html

Custom Tab

Use title slot to custom tab title.

html

Switch Animation

Use animated props to change tabs with animation.

html

Swipeable

In swipeable mode, you can switch tabs with swipe gesture in the content.

html

Scrollspy

In scrollspy mode, the list of content will be tiled.

html

Before Change

html
js
import { ref } from'vue'; exportdefault { setup() { const active = ref(0); constbeforeChange = (index) => { // prevent changeif (index === 1) { returnfalse; } // asyncreturnnewPromise((resolve) => { setTimeout(() =>resolve(index !== 3), 1000); }); }; return { active, beforeChange, }; }, };

Tips: The before-change callback will not be triggered by swiping gesture.

Hide Header

By setting the showHeader prop to false, the title bar of the Tabs component can be hidden. In this case, you can control the active prop of the Tabs using custom components.

html

API

Tabs Props

AttributeDescriptionTypeDefault
v-model:activeIndex of active tab*numberstring*
typeCan be set to line``cardstringline
colorTab colorstring#1989fa

| background | Background color | string | white | | duration | Toggle tab's animation time | number | string | 0.3 | | line-width | Width of tab line | number | string | 40px | | line-height | Height of tab line | number | string | 3px | | animated | Whether to change tabs with animation (After enabling this attribute, if there is a sticky layout in the content area, it will not meet expectations) | boolean | false | | border | Whether to show border when type="line" | boolean | false | | ellipsis | Whether to ellipsis too long title (Takes effect only if shrink is false and the number of tabs is less than or equal to swipe-threshold) | boolean | true | | sticky | Whether to use sticky mode | boolean | false | | shrink | Whether to shrink the the tabs to the left | boolean | false | | swipeable | Whether to enable gestures to slide left and right (After enabling this attribute, if there is a sticky layout in the content area, it will not meet expectations) | boolean | false | | lazy-render | Whether to enable tab content lazy render | boolean | true | | scrollspy | Whether to use scrollspy mode | boolean | false | | show-header v4.7.3 | Whether to show title bar | boolean | true | | offset-top | Sticky offset top , supports px``vw``vh``rem unit, default px | number | string | 0 | | swipe-threshold | Set swipe tabs threshold (Takes effect only when shrink is false and ellipsis is true) | number | string | 5 | | title-active-color | Title active color | string | - | | title-inactive-color | Title inactive color | string | - | | before-change | Callback function before changing tabs, return false to prevent change, support return Promise | (name: number | string) => boolean | Promise<boolean> | - |

Tab Props

AttributeDescriptionTypeDefault
titleTitlestring-
disabledWhether to disable tabbooleanfalse
dotWhether to show red dot on the titlebooleanfalse
badgeContent of the badge on the title (Effective when dot is false)*numberstring*
nameIdentifier*numberstring*
urlLinkstring-
toThe target route should navigate to when clicked on, same as the to prop of Vue Router*stringobject*

| replace | If true, the navigation will not leave a history record | boolean | false | | title-style | Custom title style | string | Array | object | - | | title-class | Custom title class name | string | Array | object | - | | show-zero-badge | Whether to show badge when the value is zero | boolean | true |

Tabs Events

EventDescriptionArguments
click-tabEmitted when a tab is clicked*{ name: string
changeEmitted when active tab changed*name: string
renderedEmitted when content first rendered in lazy-render mode*name: string
scrollEmitted when tab scrolling in sticky mode{ scrollTop: number, isFixed: boolean }

Tabs Methods

Use ref to get Tabs instance and call instance methods.

NameDescriptionAttributeReturn value
resizeResize Tabs when container element resized or visibility changed--
scrollToGo to specified tab in scrollspy mode*name: stringnumber*

Types

The component exports the following type definitions:

ts
importtype { TabProps, TabsType, TabsProps, TabsInstance } from'vant';

TabsInstance is the type of component instance:

ts
import { ref } from'vue'; importtype { TabsInstance } from'vant'; const tabsRef = ref<TabsInstance>(); tabsRef.value?.scrollTo(0);

Tabs Slots

NameDescription
nav-leftCustom nav left content
nav-rightCustom nav right content
nav-bottomCustom nav bottom content

Tab Slots

NameDescription
defaultContent of tab
titleCustom tab title

Theming

CSS Variables

The component provides the following CSS variables, which can be used to customize styles. Please refer to ConfigProvider component.

NameDefault ValueDescription
--van-tab-text-colorvar(--van-gray-7)-
--van-tab-active-text-colorvar(--van-text-color)-
--van-tab-disabled-text-colorvar(--van-text-color-3)-
--van-tab-font-sizevar(--van-font-size-md)-
--van-tab-line-heightvar(--van-line-height-md)-
--van-tabs-default-colorvar(--van-primary-color)-
--van-tabs-line-height44px-
--van-tabs-card-height30px-
--van-tabs-nav-backgroundvar(--van-background-2)-
--van-tabs-bottom-bar-width40px-
--van-tabs-bottom-bar-height3px-
--van-tabs-bottom-bar-colorvar(--van-primary-color)-

FAQ

After Tabs enable the swipeable or animated attribute, the sticky function of content area elements will not meet expectations

When the swipeable or animated attribute is enabled for Tabs, the content area will be wrapped by an element with the transform attribute, and if the sticky function is enabled for the element in the content area, the function will take effect, but the display position will not be as expected.

For example, the following code:

html

This is because the fixed positioning inside the transform element is computed relative to that element, not relative to the entire document, resulting in layout exceptions.

How to determine if the current component is inside an active Tab?

In a child component, you can use useTabStatus or useAllTabStatus to check whether the component is inside an active Tab.

  • useTabStatus: Returns whether the current component's parent Tab is active. Returns null if the component is not inside a Tab.
  • useAllTabStatus: In nested Tab scenarios, returns whether all parent Tabs are active. Returns null if the component is not inside a Tab.
js
const isActive = useTabStatus(); // For nested Tab scenariosconst isAllActive = useAllTabStatus();

Enterprise-level mobile solution based on Vant