Skip to content

Card3D

A neo-brutalist 3D interactive card that captures pointer offset relative to the card center to produce smooth 3D rotation deflection, with the shadow layer shifting in the opposite direction for a solid three-dimensional feel.

Demo

Preview

3D 悬浮卡片

将鼠标移入卡片,体验 3D 物理偏转与反向阴影投影效果。

大阴影变体

shadow="lg" 提供更大的偏移阴影。

超大阴影变体

shadow="xl" 提供最大的偏移阴影。

最大旋转角度 (maxRotation=30)

更大的旋转幅度,偏转效果更夸张。

透视距离 (perspective=500)

更近的透视距离,3D 纵深感更强。

缩放比例 (scale=1.1)

悬停时放大至 1.1 倍,视觉冲击更强。

禁用状态 (disabled=true)

禁用 3D 效果,卡片不会响应鼠标移动。

颜色变体

主色 (primary)

强调 (accent)

静音 (muted)

可点击

点击我

clickable=true,点击触发 click 事件。已点击 0 次。

Installation

pnpm dlx brutx-vue@latest add card-3d

Usage

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

<template>
    <Card3D class="w-full max-w-sm">
        <div class="p-6">
            <h3 class="text-lg font-black mb-2">3D Floating Card</h3>
            <p class="text-sm">Move your mouse over the card to experience the 3D physics deflection effect.</p>
        </div>
    </Card3D>
</template>

Variants

Shadow Variants

VariantDescription
defaultStandard shadow offset
lgLarge shadow offset
xlExtra-large shadow offset

Color Variants

Control the card background and text color via the variant prop.

VariantDescription
defaultBackground-colored background, dark text
primaryPrimary (coral red) background
accentAccent (yellow) background
mutedMuted (gray) background
vue
<Card3D variant="primary" class="w-full max-w-sm">
    <div class="p-6">
        <h3 class="text-lg font-black mb-2">Primary Card</h3>
    </div>
</Card3D>

Clickable

Setting clickable to true changes the card cursor to pointer, adds role="button", tabindex="0" and Enter/Space key support, and triggers a click event. Each Enter press or Space release triggers a single click event without duplicates; long-press repeat does not re-trigger. Real mouse clicks are unaffected, and programmatic el.click() no longer triggers the click event.

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

function handleClick(event) {
    console.log('Card clicked', event)
}
</script>

<template>
    <Card3D clickable class="w-full max-w-sm" @click="handleClick">
        <div class="p-6">Click me</div>
    </Card3D>
</template>

Props

PropTypeDefaultDescription
maxRotationnumber15Maximum deflection angle (degrees)
perspectivenumber10003D perspective depth (px)
scalenumber1.02Scale ratio on hover
shadowOffsetnumber10Maximum shadow physical displacement in pixels (px)
shadow'default' | 'lg' | 'xl''default'Shadow size variant
variant'default' | 'primary' | 'accent' | 'muted''default'Card background color variant
disabledbooleanfalseDisables 3D effect, card stays static
clickablebooleanfalseEnables click; when true, adds role="button", tabindex="0", keyboard support and triggers click events
ariaLabelstringAccessible name for clickable cards; sets aria-label only when explicitly provided, otherwise the slot content serves as the accessible name
classstringExternal class override

Events

EventPayloadDescription
clickMouseEvent | KeyboardEventTriggered only when clickable is true and disabled is false; pointer click emits MouseEvent, Enter/Space keyboard activation emits KeyboardEvent

Slots

SlotScopeDescription
defaultCard content, supports any custom content

Accessibility

  • The component sets role="group" and provides aria-label via i18n (Chinese: "3D Interactive Card", English: "3D Interactive Card")
  • For clickable cards, aria-label is set only when ariaLabel is explicitly provided; otherwise the slot content serves as the accessible name. A clickable card with an empty slot and no ariaLabel has no accessible name — pass ariaLabel in that case
  • When the user prefers prefers-reduced-motion: reduce, the 3D deflection effect is automatically disabled
  • The 3D effect can be fully disabled via the disabled prop

Brute force builds.