Skip to content

Commit 4c8b8ed

Browse files
authored
add flip grid animation (#798)
1 parent 2b63785 commit 4c8b8ed

4 files changed

Lines changed: 330 additions & 0 deletions

File tree

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ Please be aware that the demos may exhibit significant accessibility issues, suc
5252
- [Dynamic Image Colorizing](#dynamic-image-colorizing)
5353
- [Enable Dark Mode](#darkmode)
5454
- [Fancy Menu](#fancy-menu)
55+
- [Flip the grid](#flip-grid)
5556
- [Flip on Click](#flip-on-click)
5657
- [Floating Label on Textfield](#floating-label-on-textfield)
5758
- [Floating Labels V2](#floating-labelv2)
@@ -522,6 +523,14 @@ Please be aware that the demos may exhibit significant accessibility issues, suc
522523

523524
---
524525

526+
## <a id="flip-grid"></a>Flip grid
527+
528+
[<img src="flip grid animation/flip.gif" height="230" title="Demo">](https://codepen.io/Rajat-Hegde/pen/bNEqjRp)
529+
530+
**[⬆ back to top](#quick-links)**
531+
532+
---
533+
525534
## <a id="Todo"></a>Todo List
526535

527536
[<img src="images/Todo List.png" height="230" title="Demo">](https://codepen.io/SamsShow/pen/NWeerXr)

flip grid animation/flip.gif

257 KB
Loading

flip grid animation/index.html

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width,initial-scale=1" />
6+
<title>CSS Flip Grid (hover / focus)</title>
7+
<link rel="stylesheet" href="style.css">
8+
</head>
9+
<body>
10+
<main class="wrap" aria-label="Flip grid demo">
11+
<h1 class="sr-only">Flip Grid Demo</h1>
12+
13+
<section class="grid" role="list">
14+
<!-- Repeatable card -->
15+
<div class="card" role="listitem" tabindex="0" aria-label="Card 1">
16+
<div class="card__inner">
17+
<div class="card__face card__face--front">
18+
<div class="badge">1</div>
19+
<h2 class="card__title">Front</h2>
20+
<p class="card__meta">Hover or focus to flip</p>
21+
</div>
22+
<div class="card__face card__face--back">
23+
<h3>Back content</h3>
24+
<p>Extra details go here. This side is revealed on hover/focus.</p>
25+
</div>
26+
</div>
27+
</div>
28+
29+
<div class="card" role="listitem" tabindex="0" aria-label="Card 2">
30+
<div class="card__inner">
31+
<div class="card__face card__face--front">
32+
<div class="badge">2</div>
33+
<h2 class="card__title">Design</h2>
34+
<p class="card__meta">Pure CSS flip</p>
35+
</div>
36+
<div class="card__face card__face--back">
37+
<h3>Details</h3>
38+
<p>Accessible via keyboard: Tab then Enter/Space to interact with content.</p>
39+
</div>
40+
</div>
41+
</div>
42+
43+
<div class="card" role="listitem" tabindex="0" aria-label="Card 3">
44+
<div class="card__inner">
45+
<div class="card__face card__face--front">
46+
<div class="badge">3</div>
47+
<h2 class="card__title">Animation</h2>
48+
<p class="card__meta">Smooth and performant</p>
49+
</div>
50+
<div class="card__face card__face--back">
51+
<h3>Notes</h3>
52+
<p>Uses transform/opacity for best GPU performance.</p>
53+
</div>
54+
</div>
55+
</div>
56+
57+
<!-- add more cards as needed -->
58+
</section>
59+
</main>
60+
</body>
61+
</html>

flip grid animation/style.css

Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
:root{
2+
--bg: #0b1220;
3+
--card-bg: linear-gradient(180deg,#0f1724 0%, #0b1220 100%);
4+
--accent: #7dd3fc;
5+
--accent-2: #f472b6;
6+
--gap: 1rem;
7+
--card-w: 260px;
8+
--card-h: 320px;
9+
--radius: 12px;
10+
--shadow: 0 10px 30px rgba(2,6,23,0.6);
11+
--focus-ring: 3px solid rgba(125,211,252,0.14);
12+
}
13+
14+
*{box-sizing:border-box}
15+
html,body{height:100%;margin:0;font-family:Inter,system-ui,-apple-system,Segoe UI,Roboto,"Helvetica Neue",Arial;background:var(--bg);color:#e6eef8}
16+
.wrap{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:3rem}
17+
18+
/* visually-hidden helper */
19+
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
20+
21+
/* grid */
22+
.grid{
23+
display:grid;
24+
gap:var(--gap);
25+
grid-template-columns:repeat(auto-fit,minmax(200px,1fr));
26+
width:min(1100px,100%);
27+
align-items:center;
28+
}
29+
30+
/* card base */
31+
.card{
32+
width:var(--card-w);
33+
height:var(--card-h);
34+
perspective: 1200px; /* required for 3D flip */
35+
margin:auto;
36+
outline: none;
37+
}
38+
39+
/* focus ring for keyboard users */
40+
.card:focus{
41+
box-shadow: var(--focus-ring);
42+
border-radius: var(--radius);
43+
}
44+
45+
/* inner wrapper that does the flip */
46+
.card__inner{
47+
position:relative;
48+
width:100%;
49+
height:100%;
50+
transform-style: preserve-3d;
51+
transition: transform 600ms cubic-bezier(.2,.9,.3,1);
52+
border-radius: var(--radius);
53+
box-shadow: var(--shadow);
54+
}
55+
56+
/* flip on hover OR when focused (keyboard) */
57+
.card:hover .card__inner,
58+
.card:focus .card__inner,
59+
.card:focus-within .card__inner{
60+
transform: rotateY(180deg);
61+
}
62+
63+
/* faces */
64+
.card__face{
65+
position:absolute;
66+
inset:0;
67+
border-radius:var(--radius);
68+
backface-visibility: hidden;
69+
-webkit-backface-visibility: hidden;
70+
display:flex;
71+
flex-direction:column;
72+
align-items:center;
73+
justify-content:center;
74+
padding:1.25rem;
75+
text-align:center;
76+
color: #e6eef8;
77+
transform-origin: center;
78+
}
79+
80+
/* front styling */
81+
.card__face--front{
82+
background:
83+
radial-gradient(1200px 400px at 10% 10%, rgba(255,255,255,0.02), transparent 10%),
84+
linear-gradient(180deg, rgba(255,255,255,0.02), transparent),
85+
var(--card-bg);
86+
box-shadow: inset 0 -6px 18px rgba(0,0,0,0.35);
87+
font-weight:600;
88+
}
89+
90+
/* back styling */
91+
.card__face--back{
92+
background: linear-gradient(180deg, rgba(255,255,255,0.03), rgba(0,0,0,0.12)), linear-gradient(135deg, var(--accent), var(--accent-2));
93+
transform: rotateY(180deg);
94+
color:#051025;
95+
padding:1.25rem;
96+
}
97+
98+
/* small badge */
99+
.badge{
100+
position:absolute;
101+
left:1rem;
102+
top:1rem;
103+
width:36px;height:36px;border-radius:8px;
104+
background:linear-gradient(180deg,#fff8 0%,#ffffff22 100%);
105+
color:#fff;font-weight:700;display:grid;place-items:center;font-size:.95rem;
106+
backdrop-filter: blur(4px);
107+
}
108+
109+
/* text */
110+
.card__title{margin:0;font-size:1.35rem}
111+
.card__meta{margin:.5rem 0 0;font-size:.9rem;color:rgba(230,238,248,0.8)}
112+
.card__face--back h3{margin:0 0 .4rem}
113+
.card__face--back p{margin:0;color:rgba(5,16,37,0.9)}
114+
115+
/* slight hover lift */
116+
.card:hover .card__inner,
117+
.card:focus .card__inner{
118+
box-shadow: 0 18px 40px rgba(1,6,20,0.6);
119+
}
120+
121+
/* reduce motion preference */
122+
@media (prefers-reduced-motion: reduce) {
123+
.card__inner { transition: none; }
124+
}
125+
126+
/* responsive adjustments */
127+
@media (max-width:520px){
128+
:root{--card-w: 92vw; --card-h: 360px}
129+
.grid{grid-template-columns: 1fr}
130+
}
131+
:root{
132+
--bg: #0b1220;
133+
--card-bg: linear-gradient(180deg,#0f1724 0%, #0b1220 100%);
134+
--accent: #7dd3fc;
135+
--accent-2: #f472b6;
136+
--gap: 1rem;
137+
--card-w: 260px;
138+
--card-h: 320px;
139+
--radius: 12px;
140+
--shadow: 0 10px 30px rgba(2,6,23,0.6);
141+
--focus-ring: 3px solid rgba(125,211,252,0.14);
142+
}
143+
144+
*{box-sizing:border-box}
145+
html,body{height:100%;margin:0;font-family:Inter,system-ui,-apple-system,Segoe UI,Roboto,"Helvetica Neue",Arial;background:var(--bg);color:#e6eef8}
146+
.wrap{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:3rem}
147+
148+
/* visually-hidden helper */
149+
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
150+
151+
/* grid */
152+
.grid{
153+
display:grid;
154+
gap:var(--gap);
155+
grid-template-columns:repeat(auto-fit,minmax(200px,1fr));
156+
width:min(1100px,100%);
157+
align-items:center;
158+
}
159+
160+
/* card base */
161+
.card{
162+
width:var(--card-w);
163+
height:var(--card-h);
164+
perspective: 1200px; /* required for 3D flip */
165+
margin:auto;
166+
outline: none;
167+
}
168+
169+
/* focus ring for keyboard users */
170+
.card:focus{
171+
box-shadow: var(--focus-ring);
172+
border-radius: var(--radius);
173+
}
174+
175+
/* inner wrapper that does the flip */
176+
.card__inner{
177+
position:relative;
178+
width:100%;
179+
height:100%;
180+
transform-style: preserve-3d;
181+
transition: transform 600ms cubic-bezier(.2,.9,.3,1);
182+
border-radius: var(--radius);
183+
box-shadow: var(--shadow);
184+
}
185+
186+
/* flip on hover OR when focused (keyboard) */
187+
.card:hover .card__inner,
188+
.card:focus .card__inner,
189+
.card:focus-within .card__inner{
190+
transform: rotateY(180deg);
191+
}
192+
193+
/* faces */
194+
.card__face{
195+
position:absolute;
196+
inset:0;
197+
border-radius:var(--radius);
198+
backface-visibility: hidden;
199+
-webkit-backface-visibility: hidden;
200+
display:flex;
201+
flex-direction:column;
202+
align-items:center;
203+
justify-content:center;
204+
padding:1.25rem;
205+
text-align:center;
206+
color: #e6eef8;
207+
transform-origin: center;
208+
}
209+
210+
/* front styling */
211+
.card__face--front{
212+
background:
213+
radial-gradient(1200px 400px at 10% 10%, rgba(255,255,255,0.02), transparent 10%),
214+
linear-gradient(180deg, rgba(255,255,255,0.02), transparent),
215+
var(--card-bg);
216+
box-shadow: inset 0 -6px 18px rgba(0,0,0,0.35);
217+
font-weight:600;
218+
}
219+
220+
/* back styling */
221+
.card__face--back{
222+
background: linear-gradient(180deg, rgba(255,255,255,0.03), rgba(0,0,0,0.12)), linear-gradient(135deg, var(--accent), var(--accent-2));
223+
transform: rotateY(180deg);
224+
color:#051025;
225+
padding:1.25rem;
226+
}
227+
228+
/* small badge */
229+
.badge{
230+
position:absolute;
231+
left:1rem;
232+
top:1rem;
233+
width:36px;height:36px;border-radius:8px;
234+
background:linear-gradient(180deg,#fff8 0%,#ffffff22 100%);
235+
color:#fff;font-weight:700;display:grid;place-items:center;font-size:.95rem;
236+
backdrop-filter: blur(4px);
237+
}
238+
239+
/* text */
240+
.card__title{margin:0;font-size:1.35rem}
241+
.card__meta{margin:.5rem 0 0;font-size:.9rem;color:rgba(230,238,248,0.8)}
242+
.card__face--back h3{margin:0 0 .4rem}
243+
.card__face--back p{margin:0;color:rgba(5,16,37,0.9)}
244+
245+
/* slight hover lift */
246+
.card:hover .card__inner,
247+
.card:focus .card__inner{
248+
box-shadow: 0 18px 40px rgba(1,6,20,0.6);
249+
}
250+
251+
/* reduce motion preference */
252+
@media (prefers-reduced-motion: reduce) {
253+
.card__inner { transition: none; }
254+
}
255+
256+
/* responsive adjustments */
257+
@media (max-width:520px){
258+
:root{--card-w: 92vw; --card-h: 360px}
259+
.grid{grid-template-columns: 1fr}
260+
}

0 commit comments

Comments
 (0)