আগের পর্বে আমরা CSS Custom Properties দিয়ে থিমিং শিখেছিলাম। এই পর্বে আমরা দেখব রেসপনসিভ ডিজাইনের একটা আধুনিক টুল — Container Queries। এতদিন আমরা @media দিয়ে পুরো স্ক্রিনের সাইজ দেখে স্টাইল পাল্টেছি, এবার শিখব একটা এলিমেন্ট নিজের সাইজ দেখেই কীভাবে স্টাইল পাল্টাতে পারে।
Media Query-র সীমাবদ্ধতা
@media শুধু ব্রাউজার উইন্ডোর সাইজ দেখে — এটা কোনো নির্দিষ্ট এলিমেন্টের সাইজ সম্পর্কে কিছু জানে না। সমস্যা হয় তখন, যখন একই কম্পোনেন্ট (যেমন একটা কার্ড) পেজের বিভিন্ন জায়গায় ভিন্ন ভিন্ন প্রস্থে বসে — একবার সরু সাইডবারে, একবার চওড়া মেইন এরিয়ায়।
/* সমস্যা: এই @media শুধু পুরো স্ক্রিনের সাইজ জানে,
কার্ডটা সাইডবারে সরু জায়গায় বসলেও একই স্টাইল প্রয়োগ হবে */
@media (min-width: 768px) {
.card {
display: flex; /* সাইডবারে সরু জায়গায় বসলেও flex হয়ে যাবে, যা ভালো দেখাবে না */
}
}
Container Queries এই সমস্যার সমাধান দেয় — এখন এলিমেন্ট নিজের প্যারেন্ট কন্টেইনারের সাইজ দেখে স্টাইল ঠিক করতে পারে, স্ক্রিনের সাইজ যাই হোক না কেন।
Container Query কীভাবে ব্যবহার করে?
দুইটা ধাপ লাগে — প্রথমে একটা এলিমেন্টকে "কন্টেইনার" হিসেবে ঘোষণা করতে হয়, তারপর তার চাইল্ড এলিমেন্টে @container কোয়েরি লেখা হয়।
/* ধাপ ১: প্যারেন্টকে কন্টেইনার বানানো */
.card-wrapper {
container-type: inline-size;
container-name: card-container;
}
/* ধাপ ২: কন্টেইনারের প্রস্থ অনুযায়ী চাইল্ডের স্টাইল */
.card {
display: block;
}
@container card-container (min-width: 400px) {
.card {
display: flex;
gap: 16px;
}
}
| প্রপার্টি | কাজ |
|---|---|
container-type: inline-size |
শুধু প্রস্থ (width) অনুযায়ী কোয়েরি করা যাবে |
container-name |
কন্টেইনারের নাম (একাধিক কন্টেইনার আলাদা করতে) |
container |
শর্টহ্যান্ড (নাম / টাইপ একসাথে লেখা) |
শর্টহ্যান্ড দিয়ে লিখলে:
.card-wrapper {
container: card-container / inline-size;
}
নাম না দিলেও চলে
একটা মাত্র কন্টেইনার লেভেল থাকলে নাম না দিয়েও কাজ চলে — শুধু নিকটতম প্যারেন্ট কন্টেইনার হিসেবে ধরে নেওয়া হয়।
.card-wrapper {
container-type: inline-size;
}
@container (min-width: 400px) {
.card {
display: flex;
}
}
লাইভ ডেমো — একই কার্ড, দুই ভিন্ন জায়গায়
নিচে একই কার্ড কম্পোনেন্ট দুটো ভিন্ন প্রস্থের কন্টেইনারে বসানো আছে — সরু কন্টেইনারে কার্ডটা উপর-নিচে সাজানো (stacked), চওড়া কন্টেইনারে পাশাপাশি (side-by-side)। কোনো মিডিয়া কোয়েরি ছাড়াই, শুধু কন্টেইনারের প্রস্থের উপর ভিত্তি করে।
সরু কন্টেইনার (২২০px):
উপর-নিচে সাজানো
চওড়া কন্টেইনার (৫০০px):
একই CSS, শুধু কন্টেইনার চওড়া হওয়ায় পাশাপাশি সাজানো হয়ে গেছে
Container Query Units
Container Query-র সাথে নতুন কিছু ইউনিটও এসেছে — এগুলো viewport-এর বদলে কন্টেইনারের সাইজ অনুযায়ী হিসাব হয়।
| ইউনিট | মানে |
|---|---|
cqw |
কন্টেইনারের প্রস্থের ১% |
cqh |
কন্টেইনারের উচ্চতার ১% |
cqi |
কন্টেইনারের inline সাইজের ১% |
.card__title {
/* কন্টেইনার বড় হলে টেক্সটও বড় হবে */
font-size: clamp(14px, 5cqw, 24px);
}
clamp() — আরেকটা আধুনিক টেকনিক
Container Queries না হলেও, clamp(min, preferred, max) দিয়ে অনেক ক্ষেত্রে মিডিয়া কোয়েরি ছাড়াই ফ্লুইড (স্বয়ংক্রিয়ভাবে স্কেল হওয়া) টাইপোগ্রাফি বানানো যায়।
h1 {
/* কমপক্ষে 24px, viewport-এর 5% (পছন্দসই), সর্বোচ্চ 48px */
font-size: clamp(24px, 5vw, 48px);
}
এতে ছোট স্ক্রিনে হেডিং ২৪px-এর নিচে যাবে না, বড় স্ক্রিনে ৪৮px-এর বেশি হবে না, আর মাঝখানে স্ক্রিনের সাথে স্বয়ংক্রিয়ভাবে স্কেল হতে থাকবে।
ব্রাউজার সাপোর্ট
Container Queries এখন সব মডার্ন ব্রাউজারে (Chrome, Firefox, Safari, Edge) সাপোর্ট করে। তবে পুরনো ব্রাউজার সাপোর্ট করতে হলে @supports দিয়ে ফলব্যাক রাখা ভালো অভ্যাস:
.card {
display: block; /* ফলব্যাক */
}
@supports (container-type: inline-size) {
.card-wrapper {
container-type: inline-size;
}
@container (min-width: 400px) {
.card {
display: flex;
}
}
}
একটা সম্পূর্ণ উদাহরণ — সত্যিকারের রিইউজেবল কার্ড কম্পোনেন্ট
চলো একটা "বুক কার্ড" বানাই (Pathok Ghor-এর জন্য প্রাসঙ্গিক!) যেটা যেখানেই বসুক — গ্রিডে, সাইডবারে — নিজে থেকেই মানানসই লেআউট নেবে।
<!DOCTYPE html>
<html lang="bn">
<head>
<meta charset="UTF-8" />
<title>বুক কার্ড</title>
<style>
.book-slot {
container-type: inline-size;
}
.book-card {
display: flex;
flex-direction: column;
gap: 8px;
background: white;
border-radius: 8px;
padding: 12px;
border: 1px solid #e5e7eb;
}
.book-card__cover {
width: 100%;
aspect-ratio: 2 / 3;
background: #cbd5e1;
border-radius: 6px;
}
/* কন্টেইনার ৩০০px-এর বেশি চওড়া হলে — পাশাপাশি লেআউট */
@container (min-width: 300px) {
.book-card {
flex-direction: row;
}
.book-card__cover {
width: 100px;
flex-shrink: 0;
}
}
</style>
</head>
<body>
<div class="book-slot" style="width: 200px;">
<div class="book-card">
<div class="book-card__cover"></div>
<div>
<h4>বইয়ের নাম</h4>
<p>লেখকের নাম</p>
</div>
</div>
</div>
</body>
</html>
একই .book-card কম্পোনেন্ট এখন হোমপেজের চওড়া গ্রিডে পাশাপাশি লেআউটে দেখাবে, আবার সরু সাইডবার "সাম্প্রতিক পড়া বই" সেকশনে স্বয়ংক্রিয়ভাবে উপর-নিচে সাজানো হয়ে যাবে — কোনো আলাদা CSS ক্লাস ছাড়াই।
নিজে চেষ্টা করো
Exercise:
- উপরের বুক কার্ড উদাহরণটা নিজে বানাও, তারপর
.book-slot-এর width পাল্টে দেখো লেআউট কীভাবে বদলায়। - একটা প্রোফাইল কার্ড বানাও যেটা কন্টেইনার ২৫০px-এর কম হলে শুধু অ্যাভাটার আর নাম দেখাবে, বেশি হলে বায়ো-ও দেখাবে।
clamp()দিয়ে একটা হেডিং বানাও যেটা ২০px থেকে ৪০px-এর মধ্যে স্বয়ংক্রিয়ভাবে স্কেল হয়।- Pathok Ghor-এর বুক কার্ড কম্পোনেন্টে (যদি থাকে) Container Query প্রয়োগ করার সম্ভাবনা যাচাই করো — কোথায় এটা কাজে লাগতে পারে?
পরের পর্বে যা থাকছে
এটাই ছিল Advanced CSS সিরিজের শেষ থিওরি পর্ব। পরের পর্বে (সিরিজের শেষ পর্ব) আমরা SCSS, BEM, Grid, Flexbox, থিমিং, আর Container Queries — সব মিলিয়ে একটা Mini Project: এডভান্সড অ্যানিমেশন ও থিমসহ ল্যান্ডিং পেজ বানাব।