আগের পর্বে আমরা BEM দিয়ে CSS সংগঠিত রাখা শিখেছিলাম। এই পর্বে আমরা দেখব কীভাবে অ্যানিমেশনকে আরও প্রফেশনাল আর প্রাণবন্ত বানানো যায় — keyframes বিস্তারিতভাবে আর cubic-bezier কার্ভ দিয়ে।
@keyframes রিক্যাপ ও বিস্তারিত
@keyframes দিয়ে একটা অ্যানিমেশনের একাধিক ধাপ (from-to না, শতাংশ দিয়ে) নির্ধারণ করা যায় — এতে জটিল, বহু-ধাপের অ্যানিমেশন বানানো সহজ হয়।
@keyframes bounce {
0% {
transform: translateY(0);
}
30% {
transform: translateY(-30px);
}
50% {
transform: translateY(0);
}
70% {
transform: translateY(-15px);
}
100% {
transform: translateY(0);
}
}
.ball {
animation: bounce 1s ease-in-out infinite;
}
শতাংশ (0%, 30%, 100%) দিয়ে অ্যানিমেশনের প্রতিটা মুহূর্তে কী হবে সেটা নিয়ন্ত্রণ করা যায় — শুধু শুরু আর শেষ না, মাঝের যেকোনো পয়েন্টে।
| animation প্রপার্টি | কাজ |
|---|---|
animation-duration |
কতক্ষণ ধরে চলবে |
animation-timing-function |
গতির ধরন (ease, linear, cubic-bezier) |
animation-delay |
শুরু হওয়ার আগে কত অপেক্ষা করবে |
animation-iteration-count |
কতবার চলবে (সংখ্যা বা infinite) |
animation-fill-mode |
শেষ হওয়ার পর কোন অবস্থায় থাকবে |
animation-direction |
normal, reverse, alternate |
cubic-bezier কী?
ব্রাউজারের ডিফল্ট টাইমিং ফাংশনগুলো (ease, ease-in-out) দিয়ে বেশিরভাগ কাজ চলে যায়, কিন্তু নিজের মতো করে গতির "ফিল" ঠিক করতে চাইলে cubic-bezier(x1, y1, x2, y2) ব্যবহার করা হয় — এটা একটা গাণিতিক কার্ভ যেটা নির্ধারণ করে অ্যানিমেশন কখন দ্রুত, কখন ধীরে চলবে।
.smooth {
transition: transform 0.5s cubic-bezier(0.25, 0.1, 0.25, 1);
}
.bouncy {
transition: transform 0.6s cubic-bezier(0.68, -0.55, 0.27, 1.55);
}
.snappy {
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
| ডিফল্ট নাম | সমতুল্য cubic-bezier |
|---|---|
ease |
cubic-bezier(0.25, 0.1, 0.25, 1) |
linear |
cubic-bezier(0, 0, 1, 1) |
ease-in-out |
cubic-bezier(0.42, 0, 0.58, 1) |
টিপস: কার্ভের মান y1 বা y2 ১-এর বেশি বা ০-এর কম হলে অ্যানিমেশন সীমা ছাড়িয়ে "ওভারশুট" করে — এতেই বাউন্সি বা স্প্রিং-এর মতো ইফেক্ট পাওয়া যায় (উপরের .bouncy ক্লাসে যেমন হয়েছে)।
লাইভ ডেমো — বিভিন্ন টাইমিং ফাংশনের পার্থক্য
নিচের বাটনে চাপো — তিনটা বল একই সময়ে চলবে, কিন্তু ভিন্ন টাইমিং ফাংশন দিয়ে। পার্থক্যটা লক্ষ্য করো।
linear
ease
cubic-bezier bouncy
একাধিক অ্যানিমেশন একসাথে
একটা এলিমেন্টে একাধিক অ্যানিমেশন কমা দিয়ে আলাদা করে একসাথে চালানো যায়:
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes slideUp {
from { transform: translateY(20px); }
to { transform: translateY(0); }
}
.card {
animation:
fadeIn 0.5s ease-out,
slideUp 0.5s ease-out;
}
এখানে fadeIn আর slideUp একসাথে চলবে — কার্ড একইসাথে স্বচ্ছ থেকে দৃশ্যমান হবে আর নিচ থেকে উপরে উঠবে।
SCSS দিয়ে অ্যানিমেশন ভ্যারিয়েবল
আগের পর্বগুলোতে শেখা SCSS ভ্যারিয়েবল দিয়ে অ্যানিমেশনের টাইমিংও পুনর্ব্যবহারযোগ্য করা যায়:
$ease-bounce: cubic-bezier(0.68, -0.55, 0.27, 1.55);
$ease-smooth: cubic-bezier(0.25, 0.1, 0.25, 1);
$duration-fast: 0.2s;
$duration-normal: 0.4s;
.modal {
transition: transform $duration-normal $ease-bounce;
}
.tooltip {
transition: opacity $duration-fast $ease-smooth;
}
পারফরম্যান্স টিপস
সব CSS প্রপার্টি সমানভাবে দ্রুত অ্যানিমেট হয় না। ব্রাউজার transform আর opacity-কে GPU দিয়ে দ্রুত হ্যান্ডেল করতে পারে, কিন্তু width, top, margin অ্যানিমেট করলে পেজের পুরো লেআউট বারবার হিসাব করতে হয় — এতে অ্যানিমেশন কাঁপা কাঁপা (janky) লাগে।
/* ❌ ধীর — লেআউট বারবার হিসাব হয় */
.box:hover {
width: 200px;
margin-left: 20px;
}
/* ✅ দ্রুত — GPU-accelerated */
.box:hover {
transform: scale(1.1) translateX(20px);
}
একটা সম্পূর্ণ উদাহরণ — লোডিং স্পিনার
চলো একটা প্রফেশনাল-লুকিং লোডিং স্পিনার বানাই, keyframes আর cubic-bezier মিলিয়ে।
<!DOCTYPE html>
<html lang="bn">
<head>
<meta charset="UTF-8" />
<title>লোডিং স্পিনার</title>
<style>
@keyframes pulse-ring {
0% {
transform: scale(0.8);
opacity: 1;
}
100% {
transform: scale(1.5);
opacity: 0;
}
}
.spinner-wrap {
position: relative;
width: 60px;
height: 60px;
margin: 60px auto;
}
.spinner-dot {
width: 60px;
height: 60px;
border-radius: 50%;
background: #2563eb;
position: absolute;
}
.spinner-ring {
position: absolute;
width: 60px;
height: 60px;
border-radius: 50%;
border: 3px solid #2563eb;
animation: pulse-ring 1.2s cubic-bezier(0.25, 0.1, 0.25, 1) infinite;
}
</style>
</head>
<body>
<div class="spinner-wrap">
<div class="spinner-dot"></div>
<div class="spinner-ring"></div>
</div>
</body>
</html>
এই ডিজাইনে একটা স্থির বিন্দুর চারপাশে pulse-ring অ্যানিমেশন দিয়ে একটা রিং বড় হতে হতে মিলিয়ে যায় — এটাই "pulse" ইফেক্টের বেসিক টেকনিক, যা অনেক মডার্ন অ্যাপে নোটিফিকেশন বা লাইভ স্ট্যাটাস দেখাতে ব্যবহার হয়।
নিজে চেষ্টা করো
Exercise:
- উপরের বাউন্স ডেমো নিজে বানাও, কিন্তু
cubic-bezier-এর মান পাল্টে নিজের মতো একটা "ফিল" তৈরি করো। - একটা বাটনে হোভার করলে
transform: scale()আরbox-shadowএকসাথে অ্যানিমেট করো। - Pulse ring স্পিনারটা রঙ পাল্টে নিজের ব্র্যান্ড কালার (Pathok Ghor বা ArifStack-এর থিম কালার) দিয়ে বানাও।
- একটা এলিমেন্টে
widthআরtransform: scaleX()দুই রকম দিয়ে একই ভিজুয়াল ইফেক্ট বানিয়ে DevTools-এর Performance ট্যাবে পার্থক্য দেখো।
পরের পর্বে যা থাকছে
পরের পর্বে আমরা শিখব CSS Grid এডভান্সড প্যাটার্ন — grid-template-areas দিয়ে কীভাবে জটিল লেআউট সহজে সংজ্ঞায়িত করা যায়।