Modern CSS can handle many interactive patterns that previously required JavaScript. Here are production-ready animated components.
1. Animated Accordion
<details class="accordion">
<summary>How does billing work?</summary>
<div class="accordion-content">
<p>We bill monthly based on your plan. You can upgrade or downgrade at any time.</p>
</div>
</details>
.accordion {
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
overflow: hidden;
}
.accordion summary {
padding: 1rem;
cursor: pointer;
font-weight: 500;
list-style: none;
display: flex;
justify-content: space-between;
align-items: center;
}
.accordion summary::after {
content: "+";
font-size: 1.25rem;
transition: transform 0.2s ease;
}
.accordion[open] summary::after {
transform: rotate(45deg);
}
.accordion-content {
padding: 0 1rem 1rem;
animation: slideDown 0.2s ease;
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-0.5rem);
}
to {
opacity: 1;
transform: translateY(0);
}
}
2. CSS-Only Modal with :target
<a href="#modal">Open Modal</a>
<div id="modal" class="modal-backdrop">
<div class="modal">
<h2>Modal Title</h2>
<p>This modal is built with pure CSS using the :target pseudo-class.</p>
<a href="#" class="modal-close">Close</a>
</div>
</div>
.modal-backdrop {
position: fixed;
inset: 0;
background: rgb(0 0 0 / 0);
display: grid;
place-items: center;
pointer-events: none;
transition: background 0.3s ease;
z-index: 50;
}
.modal-backdrop:target {
background: rgb(0 0 0 / 0.5);
pointer-events: auto;
}
.modal {
background: white;
border-radius: 0.75rem;
padding: 2rem;
max-width: 28rem;
width: 90%;
transform: scale(0.95) translateY(1rem);
opacity: 0;
transition: all 0.3s ease;
}
.modal-backdrop:target .modal {
transform: scale(1) translateY(0);
opacity: 1;
}
.modal-close {
display: inline-block;
margin-top: 1rem;
color: #6b7280;
text-decoration: none;
}
3. Animated Tooltip
<span class="tooltip-wrapper">
Hover me
<span class="tooltip">This is a tooltip</span>
</span>
.tooltip-wrapper {
position: relative;
cursor: help;
}
.tooltip {
position: absolute;
bottom: calc(100% + 0.5rem);
left: 50%;
transform: translateX(-50%) translateY(0.25rem);
background: #1f2937;
color: white;
padding: 0.375rem 0.75rem;
border-radius: 0.375rem;
font-size: 0.75rem;
white-space: nowrap;
opacity: 0;
pointer-events: none;
transition: all 0.2s ease;
}
.tooltip::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
transform: translateX(-50%);
border: 4px solid transparent;
border-top-color: #1f2937;
}
.tooltip-wrapper:hover .tooltip {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
4. Animated Tab Navigation
<div class="tabs">
<input type="radio" name="tab" id="tab1" checked />
<input type="radio" name="tab" id="tab2" />
<input type="radio" name="tab" id="tab3" />
<nav class="tab-nav">
<label for="tab1">Overview</label>
<label for="tab2">Features</label>
<label for="tab3">Pricing</label>
<div class="tab-indicator"></div>
</nav>
<div class="tab-panels">
<div class="tab-panel">Overview content here.</div>
<div class="tab-panel">Features content here.</div>
<div class="tab-panel">Pricing content here.</div>
</div>
</div>
.tabs {
width: 100%;
}
.tabs input[type="radio"] {
display: none;
}
.tab-nav {
display: flex;
position: relative;
border-bottom: 2px solid #e5e7eb;
}
.tab-nav label {
flex: 1;
padding: 0.75rem;
text-align: center;
cursor: pointer;
font-weight: 500;
color: #6b7280;
transition: color 0.2s;
}
.tab-indicator {
position: absolute;
bottom: -2px;
height: 2px;
width: calc(100% / 3);
background: #2563eb;
transition: transform 0.3s ease;
}
#tab1:checked ~ .tab-nav .tab-indicator { transform: translateX(0); }
#tab2:checked ~ .tab-nav .tab-indicator { transform: translateX(100%); }
#tab3:checked ~ .tab-nav .tab-indicator { transform: translateX(200%); }
#tab1:checked ~ .tab-nav label[for="tab1"],
#tab2:checked ~ .tab-nav label[for="tab2"],
#tab3:checked ~ .tab-nav label[for="tab3"] {
color: #2563eb;
}
.tab-panels {
overflow: hidden;
}
.tab-panel {
display: none;
padding: 1.5rem 0;
animation: fadeIn 0.3s ease;
}
#tab1:checked ~ .tab-panels .tab-panel:nth-child(1),
#tab2:checked ~ .tab-panels .tab-panel:nth-child(2),
#tab3:checked ~ .tab-panels .tab-panel:nth-child(3) {
display: block;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(0.5rem); }
to { opacity: 1; transform: translateY(0); }
}
5. Staggered List Animation
.stagger-list li {
opacity: 0;
transform: translateY(1rem);
animation: slideUp 0.4s ease forwards;
}
.stagger-list li:nth-child(1) { animation-delay: 0s; }
.stagger-list li:nth-child(2) { animation-delay: 0.05s; }
.stagger-list li:nth-child(3) { animation-delay: 0.1s; }
.stagger-list li:nth-child(4) { animation-delay: 0.15s; }
.stagger-list li:nth-child(5) { animation-delay: 0.2s; }
.stagger-list li:nth-child(6) { animation-delay: 0.25s; }
@keyframes slideUp {
to {
opacity: 1;
transform: translateY(0);
}
}
6. Scroll-Driven Progress Bar
.progress-bar {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 3px;
background: #2563eb;
transform-origin: left;
animation: scaleProgress auto linear;
animation-timeline: scroll();
}
@keyframes scaleProgress {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
7. Animated Gradient Border
.gradient-border {
position: relative;
border-radius: 0.75rem;
padding: 2px;
background: linear-gradient(
var(--angle, 0deg),
#3b82f6,
#8b5cf6,
#ec4899,
#3b82f6
);
animation: rotate 3s linear infinite;
}
.gradient-border > * {
background: white;
border-radius: calc(0.75rem - 2px);
padding: 1.5rem;
}
@property --angle {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
@keyframes rotate {
to { --angle: 360deg; }
}
8. Animated Card Hover
.card-hover {
border: 1px solid #e5e7eb;
border-radius: 0.75rem;
padding: 1.5rem;
transition: all 0.3s ease;
cursor: pointer;
}
.card-hover:hover {
transform: translateY(-4px);
box-shadow: 0 12px 24px -8px rgb(0 0 0 / 0.1);
border-color: #3b82f6;
}
.card-hover h3 {
transition: color 0.2s ease;
}
.card-hover:hover h3 {
color: #2563eb;
}
9. Loading Skeleton
.skeleton {
background: linear-gradient(
90deg,
#f3f4f6 25%,
#e5e7eb 50%,
#f3f4f6 75%
);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
border-radius: 0.375rem;
}
.skeleton-text {
height: 1rem;
margin-bottom: 0.5rem;
}
.skeleton-text:last-child {
width: 60%;
}
.skeleton-avatar {
width: 3rem;
height: 3rem;
border-radius: 50%;
}
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
10. View Transition for Page Navigation
@view-transition {
navigation: auto;
}
::view-transition-old(root) {
animation: fadeOut 0.2s ease;
}
::view-transition-new(root) {
animation: fadeIn 0.3s ease;
}
@keyframes fadeOut {
to { opacity: 0; }
}
@keyframes fadeIn {
from { opacity: 0; }
}
Need Polished UI Design?
We create beautiful, performant interfaces with smooth animations and modern CSS. Contact us to elevate your design.