Skip to content

Badge ​

17:06

Description ​

Overlays a numeric or dot badge on the top-right corner of a host element. When content is passed through the default slot the component supplies its own positioning anchor and pins the badge to the top-right; with no content it acts as a standalone badge overlaid on a relatively positioned host. A count above overflow-count renders as the cap plus + (e.g. 99+), and a count of 0 is hidden unless show-zero is set.

Compatibility ​

PlatformSupport
App✅ Supported
H5✅ Supported
WeChat Mini Program✅ Supported

Examples ​

Basic Usage ​

Pass a number to count; values above the cap render as 99+ according to overflow-count.

View source
vue
<template>
    <view class="row">
        <ux-badge :count="5" custom-class="badge-item">
            <view class="box"><text class="text">消息</text></view>
        </ux-badge>
        <ux-badge :count="99" custom-class="badge-item">
            <view class="box"><text class="text">消息</text></view>
        </ux-badge>
        <ux-badge :count="200" custom-class="badge-item">
            <view class="box"><text class="text">消息</text></view>
        </ux-badge>
    </view>
</template>

<style scoped>
.row {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    overflow: visible;
}
.badge-item {
    margin-right: 20px;
    margin-bottom: 15px;
}
.box {
    width: 60px;
    height: 60px;
    background-color: #f7f8fa;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.text {
    font-size: 13px;
    color: #909399;
}
</style>

Preset Types (type) ​

type switches the preset background: error (default) / primary / success / warning / info.

View source
vue
<template>
    <view class="row">
        <ux-badge
            v-for="(item, index) in typeList"
            :key="index"
            :type="item.type"
            :count="8"
            custom-class="badge-item"
        >
            <view class="box"><text class="text">{{ item.label }}</text></view>
        </ux-badge>
    </view>
</template>

<script setup lang="uts">
const typeList = [
    { type: 'error', label: 'error' },
    { type: 'primary', label: 'primary' },
    { type: 'success', label: 'success' },
    { type: 'warning', label: 'warning' },
    { type: 'info', label: 'info' }
];
</script>

<style scoped>
.row {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    overflow: visible;
}
.badge-item {
    margin-right: 20px;
    margin-bottom: 15px;
}
.box {
    width: 60px;
    height: 60px;
    background-color: #f7f8fa;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.text {
    font-size: 13px;
    color: #909399;
}
</style>

Dot Mode (is-dot) ​

is-dot shows only a small dot instead of a number, often paired with is-center for message reminders.

View source
vue
<template>
    <view class="row">
        <ux-badge :is-dot="true" is-center custom-class="badge-item">
            <view class="box"><text class="text">消息</text></view>
        </ux-badge>
        <ux-badge :is-dot="true" type="primary" is-center custom-class="badge-item">
            <view class="box"><text class="text">通知</text></view>
        </ux-badge>
        <ux-badge :is-dot="true" type="warning" is-center custom-class="badge-item">
            <view class="box"><text class="text">提醒</text></view>
        </ux-badge>
    </view>
</template>

<style scoped>
.row {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    overflow: visible;
}
.badge-item {
    margin-right: 20px;
    margin-bottom: 15px;
}
.box {
    width: 60px;
    height: 60px;
    background-color: #f7f8fa;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.text {
    font-size: 13px;
    color: #909399;
}
</style>

Mini Size (size="mini") ​

size="mini" renders a smaller badge (scaled to 0.8).

View source
vue
<template>
    <view class="row">
        <ux-badge :count="5" custom-class="badge-item">
            <view class="box"><text class="text">默认</text></view>
        </ux-badge>
        <ux-badge :count="5" size="mini" custom-class="badge-item">
            <view class="box"><text class="text">mini</text></view>
        </ux-badge>
    </view>
</template>

<style scoped>
.row {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    overflow: visible;
}
.badge-item {
    margin-right: 20px;
    margin-bottom: 15px;
}
.box {
    width: 60px;
    height: 60px;
    background-color: #f7f8fa;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.text {
    font-size: 13px;
    color: #909399;
}
</style>

Overflow Count (overflow-count) ​

overflow-count sets a custom cap; values above it render as the cap plus +.

View source
vue
<template>
    <view class="row">
        <ux-badge :count="100" :overflow-count="99" custom-class="badge-item">
            <view class="box"><text class="text">99+</text></view>
        </ux-badge>
        <ux-badge :count="10" :overflow-count="9" custom-class="badge-item">
            <view class="box"><text class="text">9+</text></view>
        </ux-badge>
        <ux-badge :count="1000" :overflow-count="999" custom-class="badge-item">
            <view class="box"><text class="text">999+</text></view>
        </ux-badge>
    </view>
</template>

<style scoped>
.row {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    overflow: visible;
}
.badge-item {
    margin-right: 20px;
    margin-bottom: 15px;
}
.box {
    width: 60px;
    height: 60px;
    background-color: #f7f8fa;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.text {
    font-size: 13px;
    color: #909399;
}
</style>

Show Zero (show-zero) ​

With count=0 and show-zero=false (default) the badge is hidden; set it to true to show 0.

View source
vue
<template>
    <view class="row">
        <ux-badge :count="0" :show-zero="false" custom-class="badge-item">
            <view class="box"><text class="text">隐藏0</text></view>
        </ux-badge>
        <ux-badge :count="0" :show-zero="true" custom-class="badge-item">
            <view class="box"><text class="text">显示0</text></view>
        </ux-badge>
    </view>
</template>

<style scoped>
.row {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    overflow: visible;
}
.badge-item {
    margin-right: 20px;
    margin-bottom: 15px;
}
.box {
    width: 60px;
    height: 60px;
    background-color: #f7f8fa;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.text {
    font-size: 13px;
    color: #909399;
}
</style>

Custom Color ​

bg-color / color / font-size override the badge background, text color, and font size; bg-color takes precedence over type.

View source
vue
<template>
    <view class="row">
        <ux-badge :count="8" bg-color="#7232dd" color="#ffffff" custom-class="badge-item">
            <view class="box"><text class="text">自定义</text></view>
        </ux-badge>
        <ux-badge :count="16" bg-color="#19be6b" color="#ffffff" custom-class="badge-item">
            <view class="box"><text class="text">自定义</text></view>
        </ux-badge>
        <ux-badge :count="3" bg-color="#ff9900" color="#ffffff" font-size="16" custom-class="badge-item">
            <view class="box"><text class="text">自定义</text></view>
        </ux-badge>
    </view>
</template>

<style scoped>
.row {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    overflow: visible;
}
.badge-item {
    margin-right: 20px;
    margin-bottom: 15px;
}
.box {
    width: 60px;
    height: 60px;
    background-color: #f7f8fa;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.text {
    font-size: 13px;
    color: #909399;
}
</style>

Position Offset (offset) ​

offset is [top, right] in px, positioning the badge relative to its host.

View source
vue
<template>
    <view class="row">
        <view class="demo">
            <ux-badge :count="5" :offset="[0, 0]">
                <view class="box"><text class="text">基准</text></view>
            </ux-badge>
            <text class="label">[0, 0]</text>
        </view>
        <view class="demo">
            <ux-badge :count="5" :offset="[-5, -5]">
                <view class="box"><text class="text">凸出</text></view>
            </ux-badge>
            <text class="label">[-10, -10]</text>
        </view>
        <view class="demo">
            <ux-badge :count="5" :offset="[8, 15]">
                <view class="box"><text class="text">向内</text></view>
            </ux-badge>
            <text class="label">[15, 30]</text>
        </view>
    </view>
</template>

<style scoped>
.row {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    overflow: visible;
}
.demo {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-right: 25px;
    margin-bottom: 15px;
    flex-shrink: 0;
    overflow: visible;
}
.label {
    font-size: 11px;
    color: #c8c9cc;
    margin-top: 10px;
}
.box {
    width: 60px;
    height: 60px;
    background-color: #f7f8fa;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.text {
    font-size: 13px;
    color: #909399;
    white-space: nowrap;
}
</style>

Center Overlap (is-center) ​

is-center aligns the badge center with the parent's top-right corner, making offset ineffective.

View source
vue
<template>
    <view class="row">
        <ux-badge :count="5" :offset="[-5, -5]" custom-class="badge-item">
            <view class="box"><text class="text">普通</text></view>
        </ux-badge>
        <ux-badge :count="5" :is-center="true" custom-class="badge-item">
            <view class="box"><text class="text">居中</text></view>
        </ux-badge>
        <ux-badge :is-dot="true" :is-center="true" type="primary" custom-class="badge-item">
            <view class="box"><text class="text">圆点</text></view>
        </ux-badge>
    </view>
</template>

<style scoped>
.row {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    overflow: visible;
}
.badge-item {
    margin-right: 20px;
    margin-bottom: 15px;
}
.box {
    width: 60px;
    height: 60px;
    background-color: #f7f8fa;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.text {
    font-size: 13px;
    color: #909399;
}
</style>

Dual Modes ​

With the default slot the badge pins itself to the top-right; without content it acts as a standalone badge over a relatively positioned host.

View source
vue
<template>
    <view class="dual">
        <view class="card">
            <text class="mode">包裹模式</text>
            <ux-badge :count="3" :offset="[-5, -5]">
                <view class="box"><text class="text">消息</text></view>
            </ux-badge>
            <text class="desc">内容放默认插槽,组件自带定位锚点,角标自动置于右上角,宿主零配置</text>
        </view>
        <view class="card">
            <text class="mode">单用模式</text>
            <view class="host">
                <view class="box"><text class="text">消息</text></view>
                <ux-badge :count="3" :offset="[-5, -5]"></ux-badge>
            </view>
            <text class="desc">不传内容,作为独立角标叠加到宿主的相对定位右上角</text>
        </view>
    </view>
</template>

<style scoped>
.dual {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    overflow: visible;
}
.card {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    margin-right: 25px;
    margin-bottom: 15px;
    flex-shrink: 0;
    overflow: visible;
}
.mode {
    font-size: 12px;
    color: #606266;
    margin-bottom: 8px;
}
.desc {
    font-size: 11px;
    color: #c8c9cc;
    margin-top: 8px;
}
.box {
    width: 60px;
    height: 60px;
    background-color: #f7f8fa;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.text {
    font-size: 13px;
    color: #909399;
    white-space: nowrap;
}
.host {
    /* 单用模式需宿主自行提供定位锚点 */
    position: relative;
    overflow: visible;
}
</style>

Non-Absolute Positioning (absolute=false) ​

absolute=false disables absolute positioning so the badge flows inline and offset no longer applies.

View source
vue
<template>
    <view class="inline-row">
        <text>未读消息</text>
        <ux-badge :count="12" :absolute="false" custom-class="badge-inline"></ux-badge>
    </view>
    <view class="inline-row">
        <text>新通知</text>
        <ux-badge :is-dot="true" :absolute="false" type="success" custom-class="badge-inline"></ux-badge>
    </view>
</template>

<style scoped>
.inline-row {
    display: flex;
    flex-direction: row;
    align-items: center;
    margin-bottom: 10px;
}
.badge-inline {
    margin-left: 8px;
}
</style>

API ​

Props ​

PropertyDescriptionTypeDefaultVersion
customStyleCustom root element stylestring | UTSJSONObject--
customClassCustom root element style classstring''-
typePreset background color: primary / warning / success / error / infoThemeType'error'-
sizeBadge size: default / miniBadgeSize'default'-
isDotWhether to show a dot instead of a numberbooleanfalse-
countValue to display; above overflow-count it renders as the cap plus +, and 0 is hidden unless show-zero is setstring | numbernull-
overflowCountCapping value; counts above it render as the cap plus +number99-
showZeroWhether to show the badge when the value is 0booleanfalse-
offsetPosition offset [number, number] (top, right)number[]--
absoluteWhether to use absolute positioning; offset only works when enabledbooleantrue-
fontSizeFont sizestring | numberDEFAULT_FONT_SIZE-
colorFont colorstring''-
bgColorBadge background color (takes precedence over type)string''-
isCenterWhether the badge center overlaps the parent's top-right corner; when set, offset is ignoredbooleanfalse-

Events ​

ux-badge has no events.

Slots ​

SlotDescriptionVersion
defaultWrapping mode: host content the badge annotates (when provided, the component supplies its own anchor and pins the badge to the top-right)-
contentCustom badge inner content, replacing the default count text-

Notes ​

  1. Two usages: with the default slot it is "wrapping mode" — the component supplies its own relative + overflow: visible anchor and pins the badge to the top-right; without it, it is "standalone/overlay mode" and the host must provide position: relative as the anchor.
  2. is-center takes precedence over offset: when true the badge center overlaps the parent's top-right corner and offset is ignored.
  3. bg-color takes precedence over type, so the type preset background is ignored once it is set.
  4. is-dot=true keeps the badge always visible and ignores count / overflow-count; with count 0 and show-zero=false the badge is hidden entirely.
  5. A count above overflow-count (default 99) renders as the cap plus + (e.g. 99+).
  6. With absolute=false (and no default slot) the badge is not absolutely positioned, offset no longer applies, and the badge flows inline with the content.
  7. A badge protruding beyond its host relies on overflow: visible: the component declares it on both the wrapping layer and the badge node, but in standalone mode a host container that clips will still cut the badge off.