1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
|
[[!meta title="Animated Card Tiles"]]
[[!meta date="2019-02-27"]]
*The design trend of using "cards" or "tiles" to display interactive* sections/article headings in an app or website remains a popular choice among designers. So, let's build a set of animated cards with only HTML & CSS.
## What we will be building (live demo)
This is the set of animated card tiles we will be creating:
*(try hovering)*
[Live CodePen](https://codepen.io/bradleytaunt/pen/rNjBpob)
## The HTML
For the base skeleton of these cards we only need:
- a `flexbox` main container to hold everything
- a `.card-tile` parent element
- the inner child element that will display on `:hover`
- proper `h4` and `p` tags inside that child element
---
<div class="card-tiles-container">
<div class="card-tile">
<div class="text-content">
<h4>Card Title</h4>
<p>Inner card content text</p>
</div>
</div>
</div>
That's all that is needed - for now. We will be returning to this code shortly to add some extra classes to make our lives easier.
## The CSS
First we set the main housing container to use `flex` so we save ourselves the headache of aligning all the cards in a nice row:
.card-tiles-container {
display: flex;
font-size: 14px;
margin: 20px 0;
}
Next we create the default styling for our tile cards and set the `transform` property to scale the card on `:hover`:
/* Default card tile styles */
.card-tile {
border: 1px solid;
border-radius: 10px;
cursor: pointer;
height: 150px;
margin: 0 10px;
overflow: hidden;
position: relative;
width: 33.33%;
}
.card-tile:hover {
transform: scale(1.1);
}
### Where are my cards?!
Don't panic if you can't *visually* see any card elements in your demo yet - that's to be expected. We will be styling these card elements momentarily.
Our next step is to hide the default inner `text-content` and only show it on hover. We achieve this by setting it's position to `absolute`, placing it's opacity at 0 and pushing it's z-index back to -1.
When the user hovers over a main card tile, we change the `text-content` values of both the opacity and z-index to 1.
/* Card tile text content */
.card-tile .text-content {
background: linear-gradient(rgba(0,0,0,0.4) 0%, rgba(0,0,0,0.6) 100%);
bottom: 10px;
border: 1px solid rgba(0,0,0,0.4);
border-radius: 5px;
box-shadow: inset 0 1px 1px rgba(255,255,255,0.8),
0 2px 4px rgba(0,0,0,0.5);
height: 65px;
left: 10px;
opacity: 0;
padding: 10px;
position: absolute;
width: calc(100% - 20px);
z-index: -1;
}
.card-tile:hover .text-content {
opacity: 1;
z-index: 1;
}
Finally we add some minor styling for the inner header and paragraph tags:
.card-tile .text-content h4,
.card-tile .text-content p {
color: #fff;
margin: 0;
text-shadow: 1px 1px 1px rgba(0,0,0,0.6);
}
### Don't forget mobile
We want out UI to stack the cards if users are viewing them on smaller devices:
@media(max-width: 600px) {
.card-tiles-container {
flex-direction: column;
}
.card-tile {
margin: 0 0 10px 0;
width: 100%;
}
}
## Customizing each card
Remember how I mentioned that we would be adding more classes to the original HTML? Now is the time. We will be including a simple class on each card tile to provide it's own custom coloring:
<div class="card-tiles-container">
<!-- `Blue` class -->
<div class="card-tile blue">
<div class="text-content">
<h4>Card Title</h4>
<p>Inner card content text</p>
</div>
</div>
<!-- `Orange` class -->
<div class="card-tile orange">
<div class="text-content">
<h4>Card Title</h4>
<p>Inner card content text</p>
</div>
</div>
<!-- `Green` class -->
<div class="card-tile green">
<div class="text-content">
<h4>Card Title</h4>
<p>Inner card content text</p>
</div>
</div>
</div>
And these color classes correlate to some new CSS styling:
/* Blue Card */
.card-tile.blue {
background-color: #0093E9;
background-image: linear-gradient(0deg, #0093E9 0%, #80D0C7 100%);
border-color: #0093E9;
box-shadow: 0 4px 12px rgba(128,208,199,0.7),
inset 0 2px 1px rgba(255,255,255,0.6);
}
.card-tile.blue:hover {
box-shadow: 0 8px 18px rgba(128,208,199,0.4),
inset 0 2px 1px rgba(255,255,255,0.6);
}
/* Orange Card */
.card-tile.orange {
background-color: #FAD961;
background-image: linear-gradient(180deg, #FAD961 0%, #F76B1C 100%);
border-color: #F76B1C;
box-shadow: 0 4px 12px rgba(247,107,28,0.7),
inset 0 2px 1px rgba(255,255,255,0.6);
}
.card-tile.orange:hover {
box-shadow: 0 8px 18px rgba(247,107,28,0.4),
inset 0 2px 1px rgba(255,255,255,0.6);
}
/* Green Card */
.card-tile.green {
background-color: #096e40;
background-image: linear-gradient(0deg, #096e40 0%, #2AF598 100%);
border-color: #096e40;
box-shadow: 0 4px 12px rgba(9,110,64,0.7),
inset 0 2px 1px rgba(255,255,255,0.6);
}
.card-tile.green:hover {
box-shadow: 0 8px 18px rgba(9,110,64,0.4),
inset 0 2px 1px rgba(255,255,255,0.6);
}
### Adding transitions
We can now see the actual cards visually and have the ability to interact with them, but there is a problem - they don't animate.
Lucky we can target all elements we wish to animate with the `transition` property, like so:
/* Shared transitions */
.card-tile,
.card-tile .text-content {
transition: .3s ease all;
}
Done and done.
## The final code
To make things easier for reference, I have included all the `html` and `css` below. Please feel free to use these cards anywhere you like and change them as you see fit!
### HTML
<div class="card-tiles-container">
<div class="card-tile blue">
<div class="text-content">
<h4>Card Title</h4>
<p>Inner card content text</p>
</div>
</div>
<div class="card-tile orange">
<div class="text-content">
<h4>Card Title</h4>
<p>Inner card content text</p>
</div>
</div>
<div class="card-tile green">
<div class="text-content">
<h4>Card Title</h4>
<p>Inner card content text</p>
</div>
</div>
</div>
### CSS
.card-tiles-container {
display: flex;
font-size: 14px;
margin: 20px 0;
}
/* Shared transitions */
.card-tile,
.card-tile .text-content {
transition: .3s ease all;
}
/* Default card tile styles */
.card-tile {
border: 1px solid;
border-radius: 10px;
cursor: pointer;
height: 150px;
margin: 0 10px;
overflow: hidden;
position: relative;
width: 33.33%;
}
/* Blue Card */
.card-tile.blue {
background-color: #0093E9;
background-image: linear-gradient(0deg, #0093E9 0%, #80D0C7 100%);
border-color: #0093E9;
box-shadow: 0 4px 12px rgba(128,208,199,0.7),
inset 0 2px 1px rgba(255,255,255,0.6);
}
.card-tile.blue:hover {
box-shadow: 0 8px 18px rgba(128,208,199,0.4),
inset 0 2px 1px rgba(255,255,255,0.6);
}
/* Orange Card */
.card-tile.orange {
background-color: #FAD961;
background-image: linear-gradient(180deg, #FAD961 0%, #F76B1C 100%);
border-color: #F76B1C;
box-shadow: 0 4px 12px rgba(247,107,28,0.7),
inset 0 2px 1px rgba(255,255,255,0.6);
}
.card-tile.orange:hover {
box-shadow: 0 8px 18px rgba(247,107,28,0.4),
inset 0 2px 1px rgba(255,255,255,0.6);
}
/* Green Card */
.card-tile.green {
background-color: #096e40;
background-image: linear-gradient(0deg, #096e40 0%, #2AF598 100%);
border-color: #096e40;
box-shadow: 0 4px 12px rgba(9,110,64,0.7),
inset 0 2px 1px rgba(255,255,255,0.6);
}
.card-tile.green:hover {
box-shadow: 0 8px 18px rgba(9,110,64,0.4),
inset 0 2px 1px rgba(255,255,255,0.6);
}
/* Card tile text content */
.card-tile .text-content {
background: linear-gradient(rgba(0,0,0,0.4) 0%, rgba(0,0,0,0.6) 100%);
bottom: 10px;
border: 1px solid rgba(0,0,0,0.4);
border-radius: 5px;
box-shadow: inset 0 1px 1px rgba(255,255,255,0.8),
0 2px 4px rgba(0,0,0,0.5);
height: 65px;
left: 10px;
opacity: 0;
padding: 10px;
position: absolute;
width: calc(100% - 20px);
z-index: -1;
}
.card-tile .text-content h4,
.card-tile .text-content p {
color: #fff;
margin: 0;
text-shadow: 1px 1px 1px rgba(0,0,0,0.6);
}
/* All animations on hover */
.card-tile:hover {
transform: scale(1.1);
}
.card-tile:hover .text-content {
opacity: 1;
z-index: 1;
}
@media(max-width: 600px) {
.card-tiles-container {
flex-direction: column;
}
.card-tile {
margin: 0 0 10px 0;
width: 100%;
}
}
|