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>

API Reference ​

Card3D — Props
NameTypeDefaultDescription
maxRotation
number | undefined
15
Limits the maximum 3D tilt produced by pointer movement, in degrees.
Details

Declared type

number | undefined

Default value details

Resolved value
15

Source

Card3D.vue:14

packages/ui/src/components/card-3d/Card3D.vue

perspective
number | undefined
1000
Sets the 3D perspective depth in pixels; smaller values produce stronger perspective.
Details

Declared type

number | undefined

Default value details

Declaration
CARD_3D_DEFAULT_PERSPECTIVE_PX

Source: packages/ui/src/components/card-3d/Card3D.vue

Resolved value
1000

Source

Card3D.vue:15

packages/ui/src/components/card-3d/Card3D.vue

scale
number | undefined
1.02
The scale applied to the card while hovered.
Details

Declared type

number | undefined

Default value details

Resolved value
1.02

Source

Card3D.vue:16

packages/ui/src/components/card-3d/Card3D.vue

shadowOffset
number | undefined
10
Controls the maximum pointer-driven shadow offset in pixels.
Details

Declared type

number | undefined

Default value details

Resolved value
10

Source

Card3D.vue:17

packages/ui/src/components/card-3d/Card3D.vue

shadow
"default" | "lg" | "xl" | undefined
"default"
Sets the default, large, or extra-large shadow treatment.
Details

Declared type

NonNullable<"default" | "lg" | "xl" | null | undefined> | undefined

Literal values

  • "default"
  • "lg"
  • "xl"

Default value details

Resolved value
"default"

Source

Card3D.vue:18

packages/ui/src/components/card-3d/Card3D.vue

variant
"accent" | "default" | "muted" | "primary" | undefined
"default"
Sets the card background to the default, primary, accent, or muted variant.
Details

Declared type

NonNullable<"default" | "primary" | "accent" | "muted" | null | undefined> | undefined

Literal values

  • "accent"
  • "default"
  • "muted"
  • "primary"

Default value details

Resolved value
"default"

Source

Card3D.vue:19

packages/ui/src/components/card-3d/Card3D.vue

disabled
boolean | undefined
false
Disables pointer-driven 3D effects and keeps the card static.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Resolved value
false

Source

Card3D.vue:20

packages/ui/src/components/card-3d/Card3D.vue

clickable
boolean | undefined
false
Enables button-like click interaction, keyboard activation, and the click event.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Resolved value
false

Source

Card3D.vue:21

packages/ui/src/components/card-3d/Card3D.vue

ariaLabel
string | undefined
undefined
Sets the accessible name of a clickable card; when omitted, its slot content supplies the name.
Details

Declared type

string | undefined

Default value details

Resolved value
undefined

Source

Card3D.vue:22

packages/ui/src/components/card-3d/Card3D.vue

class
string | undefined
undefined
Custom CSS classes added to the card root element.
Details

Declared type

string | undefined

Default value details

Resolved value
undefined

Source

Card3D.vue:23

packages/ui/src/components/card-3d/Card3D.vue

Card3D — Events
NameSignature or typeDescription
@click
[event: MouseEvent | KeyboardEvent]
Emits the corresponding event object after a pointer click or Enter/Space activation when clickable and enabled.
Details

Declared type

[event: MouseEvent | KeyboardEvent]

Source

Card3D.vue

packages/ui/src/components/card-3d/Card3D.vue

Card3D — Slots
NameSignature or typeDescription
#default
{}
Renders the card body and can contain arbitrary custom content.
Details

Declared type

{}

Source

Card3D.vue

packages/ui/src/components/card-3d/Card3D.vue

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.