আগের পর্বে আমরা CSS Grid দিয়ে বড় লেআউট সাজিয়েছিলাম। এই পর্বে আমরা ফিরছি Flexbox-এ — বেসিক justify-content/align-items ছাড়িয়ে বাস্তব জগতের জটিল প্যাটার্ন — কার্ড গ্রিড, স্টিকি ফুটার, আর নেভিগেশন বার।
Grid বনাম Flexbox — কখন কোনটা?
দুটোই লেআউট টুল, কিন্তু ভিন্ন কাজের জন্য উপযুক্ত।
| পরিস্থিতি | উপযুক্ত টুল |
|---|---|
| একমুখী সারি/কলাম (নেভবার, বাটন গ্রুপ) | Flexbox |
| দ্বিমুখী পুরো পেজ লেআউট | Grid |
| কন্টেন্টের সাইজ অনুযায়ী পরিবর্তনশীল আইটেম | Flexbox |
| নির্দিষ্ট গ্রিড কাঠামো (সমান কলাম) | Grid |
প্যাটার্ন ১ — নেভিগেশন বার (স্পেস-বিটুইন + র্যাপিং)
লোগো বাঁয়ে, মেনু ডানে, আর ছোট স্ক্রিনে মেনু নিচে চলে যাওয়া — এটা খুবই সাধারণ একটা প্যাটার্ন।
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 12px;
padding: 16px;
}
.navbar__menu {
display: flex;
gap: 20px;
list-style: none;
}
flex-wrap: wrap খুব গুরুত্বপূর্ণ — এটা না দিলে স্ক্রিন ছোট হয়ে গেলে মেনু আইটেমগুলো ভেঙে/চাপা পড়ে যাবে, wrap দিলে সেগুলো পরের লাইনে চলে যাবে।
প্যাটার্ন ২ — কার্ড গ্রিড (flex-wrap + flex-basis)
Grid ছাড়াই Flexbox দিয়ে রেসপনসিভ কার্ড গ্রিড বানানো যায় — flex-basis দিয়ে প্রতিটা কার্ডের ন্যূনতম প্রস্থ ঠিক করে দিলে, বাকিটা flex-wrap সামলে নেয়।
.card-container {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.card {
flex: 1 1 250px; /* grow: 1, shrink: 1, basis: 250px */
background: white;
border-radius: 8px;
padding: 16px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
flex: 1 1 250px মানে — কার্ডগুলো কমপক্ষে ২৫০px চওড়া থাকবে (basis), জায়গা থাকলে বড় হবে (grow), জায়গা কম থাকলে ছোট হবে (shrink)। ফলাফল: স্ক্রিন যত চওড়া, তত বেশি কলাম, কোনো মিডিয়া কোয়েরি ছাড়াই।
লাইভ ডেমো — উইন্ডো সাইজ পাল্টালে কলাম বদলায়
ব্রাউজার সরু-চওড়া করে দেখো — কোনো মিডিয়া কোয়েরি ছাড়াই কলাম সংখ্যা বদলে যাবে।
প্রতিটা কার্ড flex: 1 1 120px — স্ক্রিন সরু হলে কম কলাম, চওড়া হলে বেশি কলাম
প্যাটার্ন ৩ — স্টিকি ফুটার
পেজের কন্টেন্ট কম থাকলেও ফুটার সবসময় স্ক্রিনের নিচে থাকা (মাঝখানে ঝুলে না থেকে) — এটা Flexbox দিয়ে মাত্র কয়েক লাইনে সমাধান করা যায়।
html, body {
height: 100%;
margin: 0;
}
.page-wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.main-content {
flex: 1; /* বাকি সব জায়গা দখল করে নেবে */
}
.footer {
/* কন্টেন্ট যতই কম হোক, ফুটার সবসময় নিচে থাকবে */
}
এখানে মূল কৌশল হলো .main-content { flex: 1; } — এটা বলে দেয় "যত জায়গা বেঁচে আছে সব নাও", ফলে ফুটার স্বয়ংক্রিয়ভাবে নিচে ঠেলে যায়, কন্টেন্ট কম থাকলেও।
প্যাটার্ন ৪ — আইকন + টেক্সট সেন্টার অ্যালাইনমেন্ট
আইকন আর টেক্সট একই লাইনে, ভার্টিক্যালি ঠিকমতো সেন্টার করা — এটা Flexbox ছাড়া বিরক্তিকর, Flexbox দিয়ে তুচ্ছ।
.badge {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 4px 10px;
border-radius: 999px;
background: #dcfce7;
color: #166534;
font-size: 13px;
}
order দিয়ে ভিজ্যুয়াল ক্রম পাল্টানো
order প্রপার্টি দিয়ে HTML-এর ক্রম না পাল্টেই ভিজ্যুয়াল ক্রম বদলানো যায় — মোবাইলে কোনো এলিমেন্ট আগে দেখাতে চাইলে খুব কাজে লাগে।
.hero {
display: flex;
flex-wrap: wrap;
}
.hero__image { order: 1; }
.hero__text { order: 2; }
@media (max-width: 600px) {
/* মোবাইলে টেক্সট আগে, ছবি পরে দেখাতে চাইলে */
.hero__text { order: 1; }
.hero__image { order: 2; }
}
সতর্কতা: order শুধু ভিজ্যুয়াল ক্রম পাল্টায়, DOM-এর আসল ক্রম না — স্ক্রিন রিডার আর Tab-নেভিগেশন এখনো HTML-এর আসল ক্রম অনুসরণ করে, তাই এটা বেশি ব্যবহার করলে অ্যাক্সেসিবিলিটি সমস্যা হতে পারে (আগের পর্বে শেখা Accessibility মনে আছে তো!)।
একটা সম্পূর্ণ উদাহরণ — প্রাইসিং কার্ড সেকশন
চলো এই পর্বের সব প্যাটার্ন মিলিয়ে একটা প্রাইসিং সেকশন বানাই।
<!DOCTYPE html>
<html lang="bn">
<head>
<meta charset="UTF-8" />
<title>প্রাইসিং সেকশন</title>
<style>
body { display: flex; flex-direction: column; min-height: 100vh; margin: 0; font-family: sans-serif; }
.pricing {
display: flex;
flex-wrap: wrap;
gap: 20px;
padding: 40px 20px;
justify-content: center;
flex: 1;
}
.pricing__card {
flex: 1 1 260px;
max-width: 300px;
display: flex;
flex-direction: column;
background: white;
border-radius: 10px;
padding: 24px;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
}
.pricing__card--featured {
border: 2px solid #2563eb;
transform: scale(1.03);
}
.pricing__features {
list-style: none;
padding: 0;
flex: 1; /* বাটন সবসময় নিচে থাকবে */
}
.pricing__button {
background: #2563eb;
color: white;
border: none;
padding: 10px;
border-radius: 6px;
}
footer {
display: flex;
justify-content: center;
align-items: center;
padding: 16px;
background: #f1f5f9;
}
</style>
</head>
<body>
<section class="pricing">
<div class="pricing__card">
<h3>বেসিক</h3>
<ul class="pricing__features">
<li>৫টা প্রজেক্ট</li>
<li>বেসিক সাপোর্ট</li>
</ul>
<button class="pricing__button">বাছাই করো</button>
</div>
<div class="pricing__card pricing__card--featured">
<h3>প্রো</h3>
<ul class="pricing__features">
<li>আনলিমিটেড প্রজেক্ট</li>
<li>২৪/৭ সাপোর্ট</li>
<li>প্রায়োরিটি সাপোর্ট</li>
</ul>
<button class="pricing__button">বাছাই করো</button>
</div>
</section>
<footer>© ২০২৬ ArifStack</footer>
</body>
</html>
খেয়াল করো — .pricing__features { flex: 1; } দিয়ে ফিচার লিস্ট যতই ছোট-বড় হোক, বাটন সবসময় কার্ডের একদম নিচে সমান লাইনে থাকবে। এটাই স্টিকি ফুটার প্যাটার্নের একটা "মিনি" ভার্সন, কার্ডের ভেতরে প্রয়োগ করা।
নিজে চেষ্টা করো
Exercise:
- উপরের প্রাইসিং সেকশনে একটা তৃতীয় কার্ড ("এন্টারপ্রাইজ") যোগ করো।
- একটা নেভবার বানাও যেটা লোগো বাঁয়ে, মেনু ডানে, আর মোবাইলে মেনু নিচে wrap হয়ে যায়।
- স্টিকি ফুটার প্যাটার্নটা নিজে বানাও, খুব কম কন্টেন্ট দিয়ে টেস্ট করো ফুটার সত্যিই নিচে থাকছে কিনা।
orderব্যবহার করে একটা সেকশনে মোবাইলে ছবি আর টেক্সটের ক্রম পাল্টে দেখাও, তারপর Tab চেপে দেখো ফোকাসের ক্রম কী হয়।
পরের পর্বে যা থাকছে
পরের পর্বে আমরা শিখব CSS Custom Properties দিয়ে থিমিং সিস্টেম — কীভাবে --variable ব্যবহার করে লাইট/ডার্ক মোডের মতো ডাইনামিক থিম বানানো যায়।