28 CSS Stacked Card Designs 28 / 28
Scratch Cards
A stack of lottery-style scratch cards where the top one has a real scratch-off canvas you drag to reveal the prize; the others fan aside on hover.
The code
<div class="scd-scratch">
<div class="scd-scratch__stage">
<div class="scd-scratch__scratch scd-scratch__scratch--s3"><div class="scd-scratch__prize"><span class="scd-scratch__lbl">PRIZE</span><span class="scd-scratch__amt">$5</span></div></div>
<div class="scd-scratch__scratch scd-scratch__scratch--s2"><div class="scd-scratch__prize"><span class="scd-scratch__lbl">PRIZE</span><span class="scd-scratch__amt">$20</span></div></div>
<div class="scd-scratch__scratch scd-scratch__scratch--s1"><div class="scd-scratch__prize"><span class="scd-scratch__lbl">WINNER</span><span class="scd-scratch__amt">$100</span></div><canvas data-scd-scratch="canvas"></canvas></div>
</div>
</div> <div class="scd-scratch">
<div class="scd-scratch__stage">
<div class="scd-scratch__scratch scd-scratch__scratch--s3"><div class="scd-scratch__prize"><span class="scd-scratch__lbl">PRIZE</span><span class="scd-scratch__amt">$5</span></div></div>
<div class="scd-scratch__scratch scd-scratch__scratch--s2"><div class="scd-scratch__prize"><span class="scd-scratch__lbl">PRIZE</span><span class="scd-scratch__amt">$20</span></div></div>
<div class="scd-scratch__scratch scd-scratch__scratch--s1"><div class="scd-scratch__prize"><span class="scd-scratch__lbl">WINNER</span><span class="scd-scratch__amt">$100</span></div><canvas data-scd-scratch="canvas"></canvas></div>
</div>
</div>@import url('https://fonts.googleapis.com/css2?family=Bungee&family=Nunito:wght@600;800&display=swap');
.scd-scratch, .scd-scratch *, .scd-scratch *::before, .scd-scratch *::after { box-sizing: border-box; margin: 0; padding: 0; }
.scd-scratch {
min-height: 460px;
display: grid;
place-items: center;
background: linear-gradient(135deg,#f12711,#f5af19);
font-family: 'Nunito', sans-serif;
}
.scd-scratch__stage { position: relative; width: 240px; height: 320px; }
.scd-scratch__scratch {
position: absolute; inset: 0;
border-radius: 20px;
box-shadow: 0 14px 30px rgba(120,40,0,.4);
transition: transform .5s cubic-bezier(.3,.9,.3,1);
overflow: hidden;
}
.scd-scratch__prize {
position: absolute; inset: 0;
background: linear-gradient(150deg,#fffbe6,#ffe9a8);
display: flex; flex-direction: column; align-items: center; justify-content: center;
color: #c0392b;
}
.scd-scratch__amt { font-family: 'Bungee', sans-serif; font-size: 3rem; }
.scd-scratch__lbl { font-weight: 800; letter-spacing: .1em; color: #e67e22; }
.scd-scratch__scratch canvas {
position: absolute; inset: 0;
width: 100%; height: 100%;
border-radius: 20px;
cursor: grab;
touch-action: none;
}
.scd-scratch__scratch--s1 { z-index: 3; }
.scd-scratch__scratch--s2 { z-index: 2; transform: translate(10px,12px) scale(.96) rotate(3deg); }
.scd-scratch__scratch--s3 { z-index: 1; transform: translate(20px,24px) scale(.92) rotate(6deg); }
.scd-scratch__stage:hover .scd-scratch__scratch--s2 { transform: translate(-110px,18px) scale(.96) rotate(-6deg); }
.scd-scratch__stage:hover .scd-scratch__scratch--s3 { transform: translate(120px,18px) scale(.96) rotate(8deg); }
@media (prefers-reduced-motion: reduce) {
.scd-scratch__scratch { transition: none !important; }
} @import url('https://fonts.googleapis.com/css2?family=Bungee&family=Nunito:wght@600;800&display=swap');
.scd-scratch, .scd-scratch *, .scd-scratch *::before, .scd-scratch *::after { box-sizing: border-box; margin: 0; padding: 0; }
.scd-scratch {
min-height: 460px;
display: grid;
place-items: center;
background: linear-gradient(135deg,#f12711,#f5af19);
font-family: 'Nunito', sans-serif;
}
.scd-scratch__stage { position: relative; width: 240px; height: 320px; }
.scd-scratch__scratch {
position: absolute; inset: 0;
border-radius: 20px;
box-shadow: 0 14px 30px rgba(120,40,0,.4);
transition: transform .5s cubic-bezier(.3,.9,.3,1);
overflow: hidden;
}
.scd-scratch__prize {
position: absolute; inset: 0;
background: linear-gradient(150deg,#fffbe6,#ffe9a8);
display: flex; flex-direction: column; align-items: center; justify-content: center;
color: #c0392b;
}
.scd-scratch__amt { font-family: 'Bungee', sans-serif; font-size: 3rem; }
.scd-scratch__lbl { font-weight: 800; letter-spacing: .1em; color: #e67e22; }
.scd-scratch__scratch canvas {
position: absolute; inset: 0;
width: 100%; height: 100%;
border-radius: 20px;
cursor: grab;
touch-action: none;
}
.scd-scratch__scratch--s1 { z-index: 3; }
.scd-scratch__scratch--s2 { z-index: 2; transform: translate(10px,12px) scale(.96) rotate(3deg); }
.scd-scratch__scratch--s3 { z-index: 1; transform: translate(20px,24px) scale(.92) rotate(6deg); }
.scd-scratch__stage:hover .scd-scratch__scratch--s2 { transform: translate(-110px,18px) scale(.96) rotate(-6deg); }
.scd-scratch__stage:hover .scd-scratch__scratch--s3 { transform: translate(120px,18px) scale(.96) rotate(8deg); }
@media (prefers-reduced-motion: reduce) {
.scd-scratch__scratch { transition: none !important; }
}(() => {
const root = document.querySelector('.scd-scratch');
if (!root) return;
const cv = root.querySelector('[data-scd-scratch="canvas"]');
if (!cv) return;
const ctx = cv.getContext('2d');
function init() {
cv.width = 240;
cv.height = 320;
const g = ctx.createLinearGradient(0, 0, 240, 320);
g.addColorStop(0, '#9e9e9e');
g.addColorStop(1, '#cfcfcf');
ctx.fillStyle = g;
ctx.fillRect(0, 0, 240, 320);
ctx.fillStyle = '#7a7a7a';
ctx.font = 'bold 22px Nunito';
ctx.textAlign = 'center';
ctx.fillText('SCRATCH HERE', 120, 165);
ctx.globalCompositeOperation = 'destination-out';
}
init();
let drawing = false;
function pos(e) {
const r = cv.getBoundingClientRect();
const cx = (e.touches ? e.touches[0].clientX : e.clientX) - r.left;
const cy = (e.touches ? e.touches[0].clientY : e.clientY) - r.top;
return [cx * 240 / r.width, cy * 320 / r.height];
}
function scratch(e) {
if (!drawing) return;
const [x, y] = pos(e);
ctx.beginPath();
ctx.arc(x, y, 22, 0, 7);
ctx.fill();
}
cv.addEventListener('mousedown', () => { drawing = true; });
cv.addEventListener('mouseup', () => { drawing = false; });
cv.addEventListener('mouseleave', () => { drawing = false; });
cv.addEventListener('mousemove', scratch);
cv.addEventListener('touchstart', () => { drawing = true; });
cv.addEventListener('touchend', () => { drawing = false; });
cv.addEventListener('touchmove', (e) => { e.preventDefault(); scratch(e); }, { passive: false });
})(); (() => {
const root = document.querySelector('.scd-scratch');
if (!root) return;
const cv = root.querySelector('[data-scd-scratch="canvas"]');
if (!cv) return;
const ctx = cv.getContext('2d');
function init() {
cv.width = 240;
cv.height = 320;
const g = ctx.createLinearGradient(0, 0, 240, 320);
g.addColorStop(0, '#9e9e9e');
g.addColorStop(1, '#cfcfcf');
ctx.fillStyle = g;
ctx.fillRect(0, 0, 240, 320);
ctx.fillStyle = '#7a7a7a';
ctx.font = 'bold 22px Nunito';
ctx.textAlign = 'center';
ctx.fillText('SCRATCH HERE', 120, 165);
ctx.globalCompositeOperation = 'destination-out';
}
init();
let drawing = false;
function pos(e) {
const r = cv.getBoundingClientRect();
const cx = (e.touches ? e.touches[0].clientX : e.clientX) - r.left;
const cy = (e.touches ? e.touches[0].clientY : e.clientY) - r.top;
return [cx * 240 / r.width, cy * 320 / r.height];
}
function scratch(e) {
if (!drawing) return;
const [x, y] = pos(e);
ctx.beginPath();
ctx.arc(x, y, 22, 0, 7);
ctx.fill();
}
cv.addEventListener('mousedown', () => { drawing = true; });
cv.addEventListener('mouseup', () => { drawing = false; });
cv.addEventListener('mouseleave', () => { drawing = false; });
cv.addEventListener('mousemove', scratch);
cv.addEventListener('touchstart', () => { drawing = true; });
cv.addEventListener('touchend', () => { drawing = false; });
cv.addEventListener('touchmove', (e) => { e.preventDefault(); scratch(e); }, { passive: false });
})();More from 28 CSS Stacked Card Designs
Scroll-Activated Stacked Cards (Sticky Stack)Swipeable / Click-to-Front Stacked CardsShuffle RevealSwipe StackAccordion Card3D Flip StackTilt on HoverCSS Stacked Cards Hover RevealPure CSS Stacked Card Testimonial Slider3D Overlapping Stacked Cards (Isometric View)Minimalist Bento Grid Stacked CardsClassic Deck
View the full collection →