Skip to content

BeforeAfter 对比滑块 ​

新粗野主义风格的图片滑动对比组件。用于直观比对同一张图在修改前 (Before) 与修改后 (After) 的视觉差异。基于原生 <input type="range"> 结合 CSS clip-path 遮罩构建,零依赖、触控友好。

预览 ​

Preview

水平方向

之前
之后

垂直方向

之前
之后

提示:拖拽滑块的位置过渡尊重系统的「减少动态效果」设置。启用后分割线与裁剪区域将即时跟随,不再带有缓动动画。

安装 ​

pnpm dlx brutx-vue@latest add before-after

用法 ​

vue
<script setup>
import { BeforeAfter } from 'brutx-ui-vue'

const original = '/images/before.jpg'
const modified = '/images/after.jpg'
</script>

<template>
    <BeforeAfter
        :before="original"
        :after="modified"
        :default-value="50"
    />
</template>

垂直方向 ​

通过 orientation 属性切换分割线方向。默认 horizontal 为左右拖拽;设置为 vertical 时,分割线变为水平方向上下拖拽,裁剪从下到上进行(clip-path: inset(0 0 ...)),手柄图标自动旋转 90 度。

vue
<BeforeAfter
    :before="original"
    :after="modified"
    orientation="vertical"
    :default-value="50"
/>

浏览器兼容提示:垂直模式下分割线/手柄位置(top: <value>%,值大靠下)与原生垂直 range 的 value 递增方向在 Chromium 中一致;WebKit(Safari)下垂直滑块的递增方向可能相反(向下拖 value 减小、分割线反而上移),orient 属性在部分浏览器不被支持。跨浏览器场景建议实测验证。

变体 ​

变体说明
horizontal默认方向,左右拖拽分割线
vertical垂直方向,上下拖拽分割线,裁剪从下到上进行

API 参考 ​

BeforeAfter — 属性
名称类型默认值说明
before
必填
string
—
对比底层的 before 图片 URL。
详情

声明类型

string

默认值详情

未声明默认值
—

来源

BeforeAfter.vue:13

packages/ui/src/components/before-after/BeforeAfter.vue

after
必填
string
—
对比上层的 after 图片 URL。
详情

声明类型

string

默认值详情

未声明默认值
—

来源

BeforeAfter.vue:14

packages/ui/src/components/before-after/BeforeAfter.vue

beforeAlt
string | undefined
undefined

运行时回退:之前

底层 before 图片的替代文本;未设置时使用本地化默认值。
详情

声明类型

string | undefined

默认值详情

解析值
undefined
运行时回退
之前

组件在说明的运行条件下采用此回退值。

来源

BeforeAfter.vue:15

packages/ui/src/components/before-after/BeforeAfter.vue

afterAlt
string | undefined
undefined

运行时回退:之后

上层 after 图片的替代文本;未设置时使用本地化默认值。
详情

声明类型

string | undefined

默认值详情

解析值
undefined
运行时回退
之后

组件在说明的运行条件下采用此回退值。

来源

BeforeAfter.vue:16

packages/ui/src/components/before-after/BeforeAfter.vue

modelValue
number | undefined
undefined
当前分割位置百分比,支持 v-model;写入和交互值都会限制在 0 到 100。
详情

声明类型

number | undefined

默认值详情

解析值
undefined

来源

BeforeAfter.vue:17

packages/ui/src/components/before-after/BeforeAfter.vue

defaultValue
number | undefined
50
非受控模式的初始分割位置百分比;仅初始化时读取,默认 50。
详情

声明类型

number | undefined

默认值详情

声明
DEFAULT_SLIDER_POSITION

来源: packages/ui/src/components/before-after/BeforeAfter.vue

解析值
50

来源

BeforeAfter.vue:18

packages/ui/src/components/before-after/BeforeAfter.vue

disabled
boolean | undefined
false
禁用原生范围滑块的拖动交互。
详情

声明类型

boolean | undefined

字面量

  • false
  • true

默认值详情

解析值
false

来源

BeforeAfter.vue:19

packages/ui/src/components/before-after/BeforeAfter.vue

orientation
"vertical" | "horizontal" | undefined
"horizontal"
选择分割线方向;horizontal 显示竖直分割线,vertical 显示水平分割线。
详情

声明类型

"vertical" | "horizontal" | undefined

字面量

  • "horizontal"
  • "vertical"

默认值详情

解析值
"horizontal"

来源

BeforeAfter.vue:20

packages/ui/src/components/before-after/BeforeAfter.vue

class
string | undefined
undefined
追加到对比容器根元素的自定义 CSS 类。
详情

声明类型

string | undefined

默认值详情

解析值
undefined

来源

BeforeAfter.vue:21

packages/ui/src/components/before-after/BeforeAfter.vue

iconSize
IconSize | undefined
"md"
设置分割手柄图标尺寸。
详情

声明类型

IconSize | undefined

字面量

  • "2xl"
  • "lg"
  • "md"
  • "sm"
  • "xl"
  • "xs"

关联类型

IconSize
类型定义 — IconSize
export type IconSize = NonNullable<VariantProps<typeof iconSizeVariants>['size']>

默认值详情

解析值
"md"

来源

BeforeAfter.vue:22

packages/ui/src/components/before-after/BeforeAfter.vue

BeforeAfter — 事件
名称签名或类型说明
@update:modelValue
[value: number]
拖动滑块导致位置改变时发出限制在 0 到 100 的新百分比。
详情

声明类型

[value: number]

来源

BeforeAfter.vue

packages/ui/src/components/before-after/BeforeAfter.vue

可访问性 ​

  • 键盘操作:支持键盘方向键控制分割线位置;disabled 状态下禁用键盘交互
  • 焦点指示:透明 range input 自身无可见焦点,键盘焦点态经 has-[:focus-visible] 变体呈现在容器外环(ring-brutal-ring),Tab 聚焦时可感知当前位置
  • 动效降级:组件尊重 prefers-reduced-motion 系统设置。当用户启用"减少动态效果"时(通过 useReducedMotion 监听 prefers-reduced-motion: reduce):
    • 移除滑块过渡:分割线、拖拽手柄以及 clip-path 裁剪层不再应用过渡样式,拖动时位置变化即时生效,不带有缓动动画
    • 交互能力保留:拖拽、键盘方向键、disabled 等行为完全不受影响,仅去除视觉过渡
    • 实时响应:偏好切换后立即生效,无需重新挂载组件
    • 该机制通过一个响应式的 motionTransition 计算属性实现:在动效降级模式下返回空字符串,从而让相关元素跳过过渡样式

常见问题 ​

Q: 组件的技术方案是什么?

A: 本组件基于原生浏览器 <input type="range"> 结合 CSS 的 clip-path 遮罩构建,具有以下优势:

  1. 触控友好:在手机、平板等移动端设备上完美适配滑动手势
  2. 零依赖:不需要额外加载任何外部手势交互 JS 库,包体积近乎于零
  3. 完美排版:底层的 clip-path: inset(...) 裁剪方式不会破坏图片的宽高比,确保布局在多端始终对齐
  4. 自适应比例:容器根据图片实际尺寸自动计算 aspect-ratio,无需手动指定比例。图片加载前使用默认比例(水平 16:9,垂直 9:16)作为占位

蛮力铸就。