How to create a layered card stack カードスタックレイアウトの作り方
Stacked cards that float on hover with offsets controlled by a custom property. ずらしたカードを重ねてホバー時に浮かせるレイアウト。カスタムプロパティでオフセット量を調整できます。
ライブデモ Live Demo
Advanced Analytics
Deep insights into user behavior patterns with real-time tracking and custom dashboards.
Team Collaboration
Enhanced workflow tools for seamless team communication and project management.
Essential Features
Core functionality to get started with powerful automation and integrations.
概要・用途・特徴Overview, Usage & Features
何ができるかWhat it does
Stacked cards that float on hover with offsets controlled by a custom property.
ずらしたカードを重ねてホバー時に浮かせるレイアウト。カスタムプロパティでオフセット量を調整できます。
どこで使うかWhere to use
landing page, marketing site, portfolio, product page
NFTコレクション、写真ギャラリープレビュー、タスクグループ、ドキュメントスタック
特徴Key features
Stacked card effect using CSS transform: translateY and z-index. Simulates a physical deck of cards. Hover fans out the stack for preview. Clickable to select/bring to front. Fully CSS-driven visual with minimal JavaScript.
CSS transform:translateYとz-indexによるスタックカードエフェクト。物理的なカードデッキをシミュレート。ホバーでプレビューのためにスタックを扇状に広げる。クリックで選択/前面に表示。最小限のJavaScriptによる完全CSS駆動のビジュアル。
調整可能パラメータ Adjustable Parameters
| Parameter | Default | Description |
|---|---|---|
--stack-offset | 8px | vertical offset distance between layers |
--stack-scale | 0.95 | scale ratio for background cards |
--stack-spread | 16px | horizontal spread distance used in spread mode |
stack mode | lift | switch between lift and spread hover behavior |
実装コード Implementation Code
// react/L-002.jsx
import "./L-002.css";
const cards = [
{ badge: "New", title: "Analytics", desc: "Deep insights..." },
{ badge: "Pro", title: "Collaboration", desc: "Team tools..." },
{ badge: "Basic", title: "Essentials", desc: "Core features..." },
];
export default function LayeredCardStack({ offset = 8 }) {
return (
<div className="card-stack" style={{ ["--stack-offset"]: `${offset}px` }}>
{cards.map((card) => (
<div key={card.title} className="stack-card">
<span className="card-badge">{card.badge}</span>
<h3>{card.title}</h3>
<p>{card.desc}</p>
</div>
))}
</div>
);
}
/* react/L-002.css */
.card-stack {
position: relative;
max-width: 400px;
padding-top: calc(var(--stack-offset) * 2);
}
.stack-card {
position: relative;
background: linear-gradient(135deg, #1a1f3a, #2a3256);
border-radius: 20px;
padding: 24px;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.stack-card:nth-child(2) {
transform: scale(0.98) translateY(calc(var(--stack-offset) * -1));
margin-top: calc(var(--stack-offset) * -1);
}
.stack-card:nth-child(3) {
transform: scale(0.96) translateY(calc(var(--stack-offset) * -2));
margin-top: calc(var(--stack-offset) * -1);
opacity: 0.8;
}
.stack-card:hover {
transform: scale(1.02) translateY(-8px);
box-shadow: 0 20px 40px rgba(92, 106, 196, 0.3);
z-index: 10;
}
import { useState } from "react";
import "./L-002.css";
const items = [
{ title: "Research", body: "Collect customer signals." },
{ title: "Design", body: "Craft flows and prototypes." },
{ title: "Launch", body: "Ship incremental releases." },
];
export default function LayeredCardStack() {
const [gap, setGap] = useState(18);
return (
<div className="card-stack" style={{ "--stack-gap": `${gap}px` }}>
{items.map((item, index) => (
<article key={item.title} style={{ zIndex: index + 1 }}>
<h4>{item.title}</h4>
<p>{item.body}</p>
</article>
))}
<input
className="card-stack__slider"
type="range"
min="8"
max="28"
value={gap}
onChange={(event) => setGap(Number(event.target.value))}
/>
</div>
);
}
:root {
--stack-gap: 18px;
}
.card-stack {
position: relative;
width: min(360px, 100%);
height: 260px;
margin: 0 auto;
}
.card-stack article {
position: absolute;
inset: 0;
border-radius: 20px;
padding: 24px;
background: linear-gradient(150deg, #111632, #1c2450);
border: 1px solid rgba(255, 255, 255, 0.08);
color: #f7f8ff;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card-stack article:nth-child(1) {
transform: translate(calc(var(--stack-gap) * -1), var(--stack-gap));
}
.card-stack article:nth-child(2) {
transform: translate(calc(var(--stack-gap) * -0.3), calc(var(--stack-gap) * 0.2));
}
.card-stack article:nth-child(3) {
transform: translate(calc(var(--stack-gap) * 0.5), calc(var(--stack-gap) * -0.6));
background: linear-gradient(150deg, #5c6ac4, #22d3ee);
}
.card-stack article:hover {
transform: translate(0, -10px);
box-shadow: 0 30px 60px rgba(5, 7, 18, 0.6);
}
.card-stack__slider {
position: absolute;
bottom: -48px;
left: 0;
width: 100%;
}
仕組みとカスタマイズHow It Works & Customization
仕組みHow it works
Cards are absolutely positioned within a relative container. Each card gets a progressively increasing translateY (or rotate) offset and decreasing z-index to create the stacking illusion. On :hover of the container, CSS or JavaScript fans the cards out by updating their transforms to distinct positions, revealing all cards in the stack.
カードはrelativeコンテナ内に絶対配置。各カードはスタックイリュージョンを作るために徐々に増加するtranslateY(またはrotate)オフセットと減少するz-indexを持ちます。コンテナの:hoverで、CSSまたはJavaScriptがカードのトランスフォームを異なる位置に更新し、スタック内のすべてのカードを明示するよう扇状に広げます。
カスタマイズ方法Customization
Replace translateY with rotate for a fan-out spread instead of a vertical stack. Add a perspective transform on the container for a 3D deck effect. Implement click-to-bring-front by updating z-index on click.
translateYをrotateに置き換えて縦積みでなく扇状の広がりに。コンテナにperspectiveトランスフォームを追加して3Dデッキエフェクトに。クリック時にz-indexを更新するクリックで前面表示を実装。
注意点Caveats
Overlapping cards can create confusing tab order. Use inert or tabindex="-1" on non-top cards to prevent keyboard users from focusing hidden cards. Announce the active card to screen readers via aria-live when it changes.
重なったカードは混乱したタブ順序を作る可能性があります。キーボードユーザーが非表示カードにフォーカスしないよう、トップでないカードにinertまたはtabindex="-1"を使用してください。変更時にaria-liveでアクティブカードをスクリーンリーダーにアナウンスしてください。
よくある質問 Frequently Asked Questions
How to customize the layered card stack? Layered Card Stackをカスタマイズするには?
Modify the CSS custom properties and class styles defined in the code section. Key adjustable values include colors, sizes, durations, and spacing. See the Adjustable Parameters section for specific variables.
コードセクションで定義されているCSSカスタムプロパティとクラススタイルを変更してください。色、サイズ、時間、間隔が主な調整可能値です。具体的な変数は調整可能パラメータセクションを参照してください。
How to use the layered card stack in React? ReactでLayered Card Stackを使うには?
Import the provided React component and its CSS file. The component accepts props for customization. Check the React code section for the full implementation and available props.
提供されているReactコンポーネントとCSSファイルをインポートしてください。コンポーネントのpropsでカスタマイズできます。完全な実装と利用可能なpropsはReactコードセクションを参照してください。
What are the performance implications of layered card stack? Layered Card Stackのパフォーマンスへの影響は?
This implementation uses CSS transforms and opacity for animations, which are GPU-accelerated. It's lightweight and doesn't cause layout thrashing. Consider using prefers-reduced-motion for accessibility.
この実装はCSSのtransformとopacityを使用しており、GPUアクセラレーションされます。軽量でレイアウトスラッシングを引き起こしません。アクセシビリティのためにprefers-reduced-motionの使用を検討してください。
AIへの指示テンプレート AI Prompt Template
以下をAIに貼り付けると実装を依頼できます。 Paste the following into your AI assistant to request implementation.