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