CSS Animations & Transitions: دليل شامل للحركات والانتقالات في الويب
الدليل الاحترافي من إعداد علاء عامر - خبير تطوير الويب والتصميم
CSS Animations تضفي الحياة على واجهات الويب. تعلم كيفية إنشاء تأثيرات حركية سلسة وجذابة تحسن تجربة المستخدم.
1️⃣ CSS Transitions Basics
Understanding Transitions
/* Basic transition syntax */
.transition-example {
/* Properties to animate */
background-color: #3498db;
transform: scale(1);
opacity: 1;
/* Transition configuration */
transition-property: all; /* which properties to animate */
transition-duration: 0.3s; /* animation duration */
transition-timing-function: ease; /* animation curve */
transition-delay: 0s; /* delay before starting */
/* Shorthand syntax */
transition: all 0.3s ease 0s;
}
.transition-example:hover {
background-color: #e74c3c;
transform: scale(1.1);
opacity: 0.8;
}
/* Multiple property transitions */
.multi-transition {
background: #2ecc71;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
/* Different transitions for different properties */
transition:
background-color 0.3s ease,
transform 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55),
box-shadow 0.2s ease-out;
}
.multi-transition:hover {
background: #27ae60;
transform: translateY(-5px) rotate(2deg);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.2);
}
2️⃣ Timing Functions and Easing
/* Built-in timing functions */
.timing-examples {
transition-duration: 0.5s;
}
.linear {
transition-timing-function: linear;
}
.ease {
transition-timing-function: ease;
}
.ease-in {
transition-timing-function: ease-in;
}
.ease-out {
transition-timing-function: ease-out;
}
.ease-in-out {
transition-timing-function: ease-in-out;
}
/* Custom cubic-bezier curves */
.custom-ease-1 {
transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.custom-ease-2 {
transition-timing-function: cubic-bezier(
0.68,
-0.55,
0.265,
1.55
); /* bouncy */
}
.custom-ease-3 {
transition-timing-function: cubic-bezier(
0.95,
0.05,
0.795,
0.035
); /* dramatic */
}
/* Steps timing function */
.steps-animation {
transition: transform 1s steps(4, end);
}
.steps-animation:hover {
transform: translateX(200px);
/* Animation will happen in 4 discrete steps */
}
/* Practical button transitions */
.button {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 12px 24px;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: all 0.3s cubic-bezier(0.23, 1, 0.32, 1);
}
.button::before {
content: "";
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(
90deg,
transparent,
rgba(255, 255, 255, 0.2),
transparent
);
transition: left 0.5s ease;
}
.button:hover {
transform: translateY(-2px);
box-shadow: 0 7px 14px rgba(102, 126, 234, 0.4);
}
.button:hover::before {
left: 100%;
}
.button:active {
transform: translateY(0);
transition-duration: 0.1s;
}
3️⃣ CSS Keyframe Animations
/* Basic keyframe syntax */
@keyframes slideInFromLeft {
0% {
transform: translateX(-100%);
opacity: 0;
}
100% {
transform: translateX(0);
opacity: 1;
}
}
/* Using the animation */
.slide-in {
animation-name: slideInFromLeft;
animation-duration: 0.8s;
animation-timing-function: ease-out;
animation-delay: 0s;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: both;
animation-play-state: running;
/* Shorthand syntax */
/* animation: slideInFromLeft 0.8s ease-out both; */
}
/* Complex multi-step animation */
@keyframes complexMove {
0% {
transform: translateX(0) rotate(0deg);
background: #3498db;
border-radius: 4px;
}
25% {
transform: translateX(100px) rotate(90deg);
background: #e74c3c;
border-radius: 50%;
}
50% {
transform: translateX(100px) translateY(-50px) rotate(180deg);
background: #2ecc71;
border-radius: 4px;
}
75% {
transform: translateX(0) translateY(-50px) rotate(270deg);
background: #f39c12;
border-radius: 50%;
}
100% {
transform: translateX(0) translateY(0) rotate(360deg);
background: #9b59b6;
border-radius: 4px;
}
}
.complex-animation {
width: 50px;
height: 50px;
animation: complexMove 3s ease-in-out infinite;
}
/* Practical animations library */
/* Fade animations */
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeInDown {
from {
opacity: 0;
transform: translateY(-30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Scale animations */
@keyframes zoomIn {
from {
opacity: 0;
transform: scale(0.3);
}
to {
opacity: 1;
transform: scale(1);
}
}
@keyframes pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
100% {
transform: scale(1);
}
}
/* Bounce animation */
@keyframes bounce {
0%,
20%,
53%,
80%,
100% {
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
transform: translate3d(0, 0, 0);
}
40%,
43% {
animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
transform: translate3d(0, -30px, 0);
}
70% {
animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
transform: translate3d(0, -15px, 0);
}
90% {
transform: translate3d(0, -4px, 0);
}
}
/* Shake animation */
@keyframes shake {
0%,
100% {
transform: translateX(0);
}
10%,
30%,
50%,
70%,
90% {
transform: translateX(-10px);
}
20%,
40%,
60%,
80% {
transform: translateX(10px);
}
}
/* Rotation animations */
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@keyframes flip {
from {
transform: perspective(400px) rotateY(0);
}
to {
transform: perspective(400px) rotateY(180deg);
}
}
4️⃣ Advanced Animation Effects
/* Loading animations */
@keyframes spinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.loading-spinner {
width: 40px;
height: 40px;
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
animation: spinner 1s linear infinite;
}
/* Dots loading animation */
@keyframes dotsBounce {
0%,
80%,
100% {
transform: scale(0);
}
40% {
transform: scale(1);
}
}
.loading-dots {
display: inline-block;
position: relative;
width: 80px;
height: 80px;
}
.loading-dots div {
position: absolute;
top: 33px;
width: 13px;
height: 13px;
border-radius: 50%;
background: #3498db;
animation: dotsBounce 1.4s infinite ease-in-out both;
}
.loading-dots div:nth-child(1) {
left: 8px;
animation-delay: -0.32s;
}
.loading-dots div:nth-child(2) {
left: 32px;
animation-delay: -0.16s;
}
.loading-dots div:nth-child(3) {
left: 56px;
animation-delay: 0s;
}
/* Typing animation */
@keyframes typing {
from {
width: 0;
}
to {
width: 100%;
}
}
@keyframes blinkCaret {
from,
to {
border-color: transparent;
}
50% {
border-color: #333;
}
}
.typewriter {
overflow: hidden;
border-right: 2px solid #333;
white-space: nowrap;
margin: 0 auto;
animation:
typing 3.5s steps(40, end),
blinkCaret 0.75s step-end infinite;
}
/* Floating animation */
@keyframes float {
0% {
transform: translateY(0px);
}
50% {
transform: translateY(-20px);
}
100% {
transform: translateY(0px);
}
}
.floating-element {
animation: float 3s ease-in-out infinite;
}
/* Morphing button */
.morph-button {
background: #3498db;
color: white;
border: none;
padding: 12px 24px;
border-radius: 25px;
cursor: pointer;
transition: all 0.3s ease;
overflow: hidden;
position: relative;
}
.morph-button:hover {
border-radius: 4px;
padding: 12px 40px;
background: #2980b9;
}
.morph-button::after {
content: "→";
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%) translateX(20px);
opacity: 0;
transition: all 0.3s ease;
}
.morph-button:hover::after {
transform: translateY(-50%) translateX(0);
opacity: 1;
}
/* Staggered animations */
.stagger-container {
display: flex;
gap: 10px;
}
.stagger-item {
width: 20px;
height: 20px;
background: #e74c3c;
border-radius: 50%;
animation: bounce 0.6s ease-in-out infinite alternate;
}
.stagger-item:nth-child(1) {
animation-delay: 0s;
}
.stagger-item:nth-child(2) {
animation-delay: 0.1s;
}
.stagger-item:nth-child(3) {
animation-delay: 0.2s;
}
.stagger-item:nth-child(4) {
animation-delay: 0.3s;
}
.stagger-item:nth-child(5) {
animation-delay: 0.4s;
}
5️⃣ Transform Property Deep Dive
/* 2D Transforms */
.transform-examples {
/* Translation */
transform: translateX(50px); /* Move horizontally */
transform: translateY(-20px); /* Move vertically */
transform: translate(50px, -20px); /* Move both directions */
/* Scaling */
transform: scaleX(1.5); /* Scale horizontally */
transform: scaleY(0.8); /* Scale vertically */
transform: scale(1.2); /* Scale uniformly */
transform: scale(1.5, 0.8); /* Scale both directions */
/* Rotation */
transform: rotate(45deg); /* Rotate clockwise */
transform: rotate(-30deg); /* Rotate counterclockwise */
/* Skewing */
transform: skewX(20deg); /* Skew horizontally */
transform: skewY(-10deg); /* Skew vertically */
transform: skew(20deg, -10deg); /* Skew both directions */
/* Combined transforms */
transform: translate(50px, 100px) rotate(45deg) scale(1.2);
}
/* 3D Transforms */
.transform-3d {
/* 3D Translation */
transform: translateZ(50px); /* Move in Z axis */
transform: translate3d(50px, 100px, 25px); /* 3D translation */
/* 3D Rotation */
transform: rotateX(45deg); /* Rotate around X axis */
transform: rotateY(60deg); /* Rotate around Y axis */
transform: rotateZ(30deg); /* Rotate around Z axis */
transform: rotate3d(1, 1, 0, 45deg); /* Rotate around custom axis */
/* 3D Scaling */
transform: scaleZ(2); /* Scale in Z direction */
transform: scale3d(1.5, 1.2, 2); /* 3D scaling */
/* Perspective */
perspective: 1000px; /* Set 3D perspective */
transform-style: preserve-3d; /* Preserve 3D for children */
}
/* Transform origin */
.transform-origin-examples {
/* Default origin is center center */
transform-origin: center center;
/* Other origin points */
transform-origin: top left;
transform-origin: bottom right;
transform-origin: 50% 25%;
transform-origin: 10px 20px;
/* 3D origin */
transform-origin: center center 50px;
}
/* Practical 3D card flip */
.flip-card {
background-color: transparent;
width: 300px;
height: 200px;
perspective: 1000px;
}
.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
text-align: center;
transition: transform 0.6s;
transform-style: preserve-3d;
}
.flip-card:hover .flip-card-inner {
transform: rotateY(180deg);
}
.flip-card-front,
.flip-card-back {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
color: white;
}
.flip-card-front {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.flip-card-back {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
transform: rotateY(180deg);
}
/* 3D cube animation */
@keyframes rotateCube {
0% {
transform: rotateX(0deg) rotateY(0deg);
}
25% {
transform: rotateX(90deg) rotateY(0deg);
}
50% {
transform: rotateX(90deg) rotateY(90deg);
}
75% {
transform: rotateX(0deg) rotateY(90deg);
}
100% {
transform: rotateX(0deg) rotateY(0deg);
}
}
.cube-container {
perspective: 800px;
width: 200px;
height: 200px;
margin: 100px auto;
}
.cube {
position: relative;
width: 200px;
height: 200px;
transform-style: preserve-3d;
animation: rotateCube 4s infinite linear;
}
.cube-face {
position: absolute;
width: 200px;
height: 200px;
border: 2px solid #333;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
font-weight: bold;
}
.cube-face.front {
background: rgba(255, 0, 0, 0.7);
transform: translateZ(100px);
}
.cube-face.back {
background: rgba(0, 255, 0, 0.7);
transform: rotateY(180deg) translateZ(100px);
}
.cube-face.right {
background: rgba(0, 0, 255, 0.7);
transform: rotateY(90deg) translateZ(100px);
}
.cube-face.left {
background: rgba(255, 255, 0, 0.7);
transform: rotateY(-90deg) translateZ(100px);
}
.cube-face.top {
background: rgba(255, 0, 255, 0.7);
transform: rotateX(90deg) translateZ(100px);
}
.cube-face.bottom {
background: rgba(0, 255, 255, 0.7);
transform: rotateX(-90deg) translateZ(100px);
}
6️⃣ Animation Performance and Best Practices
/* Hardware acceleration */
.gpu-accelerated {
/* These properties trigger hardware acceleration */
transform: translateZ(0);
will-change: transform, opacity;
/* Or use transform3d for the same effect */
transform: translate3d(0, 0, 0);
}
/* Optimized animations - use transform and opacity */
.optimized-animation {
/* ✅ Good - animates well */
transition:
transform 0.3s ease,
opacity 0.3s ease;
}
.optimized-animation:hover {
transform: translateY(-5px) scale(1.02);
opacity: 0.9;
}
/* Avoid animating these properties */
.avoid-these {
/* ❌ Bad - causes layout recalculation */
/* transition: width 0.3s ease, height 0.3s ease; */
/* transition: top 0.3s ease, left 0.3s ease; */
/* transition: margin 0.3s ease, padding 0.3s ease; */
}
/* Use will-change for complex animations */
.complex-hover-card {
will-change: transform;
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.complex-hover-card:hover {
transform: translateY(-8px) rotateX(15deg) rotateY(5deg);
}
/* Remove will-change after animation */
.animation-complete {
will-change: auto;
}
/* Reduced motion accessibility */
@media (prefers-reduced-motion: reduce) {
.respectful-animation {
animation: none;
transition: none;
}
/* Provide alternative static states */
.respectful-animation:hover {
background-color: #e3f2fd;
border-color: #2196f3;
}
}
/* Container queries for responsive animations */
@container (min-width: 400px) {
.container-aware-animation {
animation-duration: 2s;
}
}
@container (max-width: 399px) {
.container-aware-animation {
animation-duration: 1s;
}
}
7️⃣ Complete Interactive Dashboard Project
This project demonstrates all the animation concepts in a practical, modern dashboard interface.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Animated Dashboard - CSS Animations Showcase</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family:
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.dashboard {
max-width: 1200px;
margin: 0 auto;
animation: fadeInUp 1s ease both;
}
.header {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border-radius: 15px;
padding: 25px;
margin-bottom: 30px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}
.header h1 {
color: #333;
font-size: 2rem;
margin-bottom: 10px;
animation: slideInFromLeft 0.8s ease 0.2s both;
}
.header p {
color: #666;
animation: slideInFromLeft 0.8s ease 0.4s both;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 25px;
margin-bottom: 30px;
}
.stat-card {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border-radius: 15px;
padding: 25px;
text-align: center;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: hidden;
animation: zoomIn 0.6s ease both;
}
.stat-card:nth-child(1) {
animation-delay: 0.1s;
}
.stat-card:nth-child(2) {
animation-delay: 0.2s;
}
.stat-card:nth-child(3) {
animation-delay: 0.3s;
}
.stat-card:nth-child(4) {
animation-delay: 0.4s;
}
.stat-card::before {
content: "";
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(
90deg,
transparent,
rgba(255, 255, 255, 0.4),
transparent
);
transition: left 0.6s ease;
}
.stat-card:hover {
transform: translateY(-10px) scale(1.02);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
}
.stat-card:hover::before {
left: 100%;
}
.stat-icon {
width: 60px;
height: 60px;
margin: 0 auto 15px;
background: linear-gradient(135deg, #667eea, #764ba2);
border-radius: 15px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
color: white;
animation: pulse 2s infinite;
}
.stat-number {
font-size: 2.5rem;
font-weight: bold;
color: #333;
margin-bottom: 5px;
counter-reset: number-counter;
animation: countUp 2s ease-in-out;
}
.stat-label {
color: #666;
font-size: 0.9rem;
text-transform: uppercase;
letter-spacing: 1px;
}
.charts-section {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 25px;
margin-bottom: 30px;
}
.chart-card {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border-radius: 15px;
padding: 25px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
animation: slideInFromBottom 0.8s ease 0.6s both;
}
.chart-title {
font-size: 1.2rem;
color: #333;
margin-bottom: 20px;
display: flex;
align-items: center;
gap: 10px;
}
.progress-bars {
space-y: 15px;
}
.progress-item {
margin-bottom: 20px;
}
.progress-label {
display: flex;
justify-content: space-between;
margin-bottom: 8px;
font-size: 0.9rem;
color: #666;
}
.progress-bar {
height: 8px;
background: #e0e7ff;
border-radius: 4px;
overflow: hidden;
position: relative;
}
.progress-fill {
height: 100%;
border-radius: 4px;
position: relative;
animation: progressLoad 2s ease-in-out;
}
.progress-fill::after {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(
90deg,
transparent,
rgba(255, 255, 255, 0.6),
transparent
);
animation: progressShine 2s ease-in-out infinite;
}
.progress-fill.blue {
background: linear-gradient(90deg, #3b82f6, #1d4ed8);
}
.progress-fill.green {
background: linear-gradient(90deg, #10b981, #047857);
}
.progress-fill.purple {
background: linear-gradient(90deg, #8b5cf6, #5b21b6);
}
.progress-fill.orange {
background: linear-gradient(90deg, #f59e0b, #d97706);
}
.recent-activity {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border-radius: 15px;
padding: 25px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
animation: slideInFromRight 0.8s ease 0.8s both;
}
.activity-item {
display: flex;
align-items: center;
gap: 15px;
padding: 15px 0;
border-bottom: 1px solid #f1f5f9;
animation: fadeInLeft 0.6s ease both;
}
.activity-item:last-child {
border-bottom: none;
}
.activity-item:nth-child(1) {
animation-delay: 1s;
}
.activity-item:nth-child(2) {
animation-delay: 1.1s;
}
.activity-item:nth-child(3) {
animation-delay: 1.2s;
}
.activity-item:nth-child(4) {
animation-delay: 1.3s;
}
.activity-icon {
width: 40px;
height: 40px;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 16px;
}
.activity-icon.success {
background: linear-gradient(135deg, #10b981, #047857);
}
.activity-icon.warning {
background: linear-gradient(135deg, #f59e0b, #d97706);
}
.activity-icon.info {
background: linear-gradient(135deg, #3b82f6, #1d4ed8);
}
.activity-icon.error {
background: linear-gradient(135deg, #ef4444, #dc2626);
}
.activity-content {
flex: 1;
}
.activity-text {
color: #333;
font-size: 0.9rem;
margin-bottom: 2px;
}
.activity-time {
color: #666;
font-size: 0.8rem;
}
.floating-action {
position: fixed;
bottom: 30px;
right: 30px;
width: 60px;
height: 60px;
background: linear-gradient(135deg, #667eea, #764ba2);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 24px;
cursor: pointer;
box-shadow: 0 8px 32px rgba(102, 126, 234, 0.3);
animation: float 3s ease-in-out infinite;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.floating-action:hover {
transform: scale(1.1);
box-shadow: 0 12px 40px rgba(102, 126, 234, 0.4);
}
/* Keyframe Animations */
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes slideInFromLeft {
from {
opacity: 0;
transform: translateX(-50px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes slideInFromRight {
from {
opacity: 0;
transform: translateX(50px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes slideInFromBottom {
from {
opacity: 0;
transform: translateY(50px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes zoomIn {
from {
opacity: 0;
transform: scale(0.3);
}
to {
opacity: 1;
transform: scale(1);
}
}
@keyframes fadeInLeft {
from {
opacity: 0;
transform: translateX(-30px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes pulse {
0%,
100% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
}
@keyframes float {
0%,
100% {
transform: translateY(0px);
}
50% {
transform: translateY(-10px);
}
}
@keyframes progressLoad {
from {
width: 0%;
}
to {
width: var(--progress-width);
}
}
@keyframes progressShine {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
}
}
@keyframes countUp {
from {
transform: scale(0.5);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
}
/* Responsive Design */
@media (max-width: 768px) {
.charts-section {
grid-template-columns: 1fr;
}
.stats-grid {
grid-template-columns: 1fr;
}
.header h1 {
font-size: 1.5rem;
}
.stat-number {
font-size: 2rem;
}
}
/* Reduced Motion */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
</style>
</head>
<body>
<div class="dashboard">
<!-- Header -->
<div class="header">
<h1>Analytics Dashboard</h1>
<p>Welcome back! Here's what's happening with your projects today.</p>
</div>
<!-- Statistics Cards -->
<div class="stats-grid">
<div class="stat-card">
<div class="stat-icon">📊</div>
<div class="stat-number">15,847</div>
<div class="stat-label">Total Views</div>
</div>
<div class="stat-card">
<div class="stat-icon">👥</div>
<div class="stat-number">3,296</div>
<div class="stat-label">Active Users</div>
</div>
<div class="stat-card">
<div class="stat-icon">💰</div>
<div class="stat-number">$12,847</div>
<div class="stat-label">Revenue</div>
</div>
<div class="stat-card">
<div class="stat-icon">📈</div>
<div class="stat-number">23.5%</div>
<div class="stat-label">Growth Rate</div>
</div>
</div>
<!-- Charts Section -->
<div class="charts-section">
<div class="chart-card">
<div class="chart-title">📊 Performance Metrics</div>
<div class="progress-bars">
<div class="progress-item">
<div class="progress-label">
<span>Website Traffic</span>
<span>85%</span>
</div>
<div class="progress-bar">
<div
class="progress-fill blue"
style="--progress-width: 85%;"
></div>
</div>
</div>
<div class="progress-item">
<div class="progress-label">
<span>User Engagement</span>
<span>72%</span>
</div>
<div class="progress-bar">
<div
class="progress-fill green"
style="--progress-width: 72%;"
></div>
</div>
</div>
<div class="progress-item">
<div class="progress-label">
<span>Conversion Rate</span>
<span>91%</span>
</div>
<div class="progress-bar">
<div
class="progress-fill purple"
style="--progress-width: 91%;"
></div>
</div>
</div>
<div class="progress-item">
<div class="progress-label">
<span>Customer Satisfaction</span>
<span>68%</span>
</div>
<div class="progress-bar">
<div
class="progress-fill orange"
style="--progress-width: 68%;"
></div>
</div>
</div>
</div>
</div>
<div class="recent-activity">
<div class="chart-title">🔔 Recent Activity</div>
<div class="activity-item">
<div class="activity-icon success">✓</div>
<div class="activity-content">
<div class="activity-text">New user registered</div>
<div class="activity-time">2 minutes ago</div>
</div>
</div>
<div class="activity-item">
<div class="activity-icon warning">⚠</div>
<div class="activity-content">
<div class="activity-text">Server load high</div>
<div class="activity-time">5 minutes ago</div>
</div>
</div>
<div class="activity-item">
<div class="activity-icon info">ℹ</div>
<div class="activity-content">
<div class="activity-text">Database backup completed</div>
<div class="activity-time">1 hour ago</div>
</div>
</div>
<div class="activity-item">
<div class="activity-icon error">✕</div>
<div class="activity-content">
<div class="activity-text">Payment failed</div>
<div class="activity-time">2 hours ago</div>
</div>
</div>
</div>
</div>
</div>
<!-- Floating Action Button -->
<div class="floating-action">+</div>
<script>
// Add interactive functionality
document.addEventListener("DOMContentLoaded", function () {
// Animate numbers counting up
const numbers = document.querySelectorAll(".stat-number");
numbers.forEach((number) => {
const finalValue = number.textContent.replace(/[^0-9.]/g, "");
if (!isNaN(finalValue)) {
animateNumber(number, 0, parseFloat(finalValue), 2000);
}
});
// Add click interactions
const statCards = document.querySelectorAll(".stat-card");
statCards.forEach((card) => {
card.addEventListener("click", function () {
this.style.animation = "pulse 0.6s ease";
setTimeout(() => {
this.style.animation = "";
}, 600);
});
});
// Floating action button interaction
const fab = document.querySelector(".floating-action");
fab.addEventListener("click", function () {
this.style.animation = "bounce 0.6s ease";
setTimeout(() => {
this.style.animation = "float 3s ease-in-out infinite";
}, 600);
});
});
function animateNumber(element, start, end, duration) {
const startTime = performance.now();
const originalText = element.textContent;
function updateNumber(currentTime) {
const elapsed = currentTime - startTime;
const progress = Math.min(elapsed / duration, 1);
const currentValue = start + (end - start) * easeOutQuart(progress);
element.textContent = originalText.replace(
/[0-9.]+/,
Math.floor(currentValue).toLocaleString()
);
if (progress < 1) {
requestAnimationFrame(updateNumber);
}
}
requestAnimationFrame(updateNumber);
}
function easeOutQuart(t) {
return 1 - Math.pow(1 - t, 4);
}
</script>
</body>
</html>
Summary
In this lesson we learned:
✅ CSS Transitions fundamentals ✅ Keyframe Animations and timing functions ✅ Transform properties and 3D effects ✅ Advanced animation techniques ✅ Performance optimization best practices ✅ Complete interactive dashboard project
In the next lesson we'll study CSS Grid Advanced Techniques and Complex Layouts.