এই পর্বে যা শিখবেন
- রেসপন্সিভ ডিজাইন কোন সমস্যার সমাধান, আর m. সাইট থেকে আজকের ভাবনায় আসার ইতিহাস
- viewport meta না থাকলে ফোন ঠিক কী করে, আর media query তখন কেন ভুল মাপ দেখে
- fluid layout আর নমনীয় ছবির নিয়ম — px-এর বদলে অনুপাতে ভাবা
- মোবাইল-ফার্স্ট CSS, min-width query আর content দেখে breakpoint বাছাই
- touch target, hover বনাম touch, আর রেসপন্সিভ পাতা পরীক্ষার পেশাদার পদ্ধতি
১ · রেসপন্সিভ ডিজাইন কেন — একই পাতা, হাজার রকম পর্দা
বাসে বসে কেউ খবর পড়ছেন ফোনে, অফিসে কেউ একই খবর খুলেছেন বড় মনিটরে, আর বাড়িতে কেউ ট্যাবলেটে। বাংলাদেশে বেশিরভাগ মানুষ ইন্টারনেট ব্যবহার করেন মূলত ফোনেই — অনেকের কাছে ফোনই একমাত্র কম্পিউটার। তাই একটি অনলাইন দোকান, চাকরির বিজ্ঞপ্তি বা সরকারি সেবার পাতা যদি ফোনে ঠিকমতো না খোলে, সেই মানুষটির কাছে পাতাটি কার্যত নেই।
সমস্যাটা হলো পর্দার মাপ কোনো নির্দিষ্ট সংখ্যা নয়। ছোট ফোন, বড় ফোন, ভাঁজ করা ফোন, ট্যাবলেট, ল্যাপটপ, চওড়া মনিটর, এমনকি টিভি — আর প্রতিটি আবার খাড়া বা আড়াআড়ি ধরা যায়। প্রতিটির জন্য আলাদা পাতা বানানো অসম্ভব। Responsive web design-এর উত্তর: একটিই HTML, আর এমন CSS যা নিয়ম দেয়, মাপ মুখস্থ করে না।
পানির কথা ভাবুন। গ্লাসে ঢাললে গ্লাসের আকার, বোতলে ঢাললে বোতলের, কলসিতে কলসির — পানি নিজে বদলায় না, শুধু পাত্রের সাথে মানিয়ে নেয়। ভালো ওয়েবপাতাও তাই: লেখা আর ছবি একই, কিন্তু সাজানোটা পাত্রের (পর্দার) মাপ অনুযায়ী। উল্টো দিকে, ছাপা পত্রিকা হলো বরফের টুকরো — একটি নির্দিষ্ট আকার, ছোট পাত্রে ঢুকবেই না।
রেসপন্সিভ ডিজাইনে আপনি ব্রাউজারকে বলেন কী চান — “লেখার লাইন খুব লম্বা হবে না”, “কার্ড অন্তত এত চওড়া”, “জায়গা থাকলে পাশাপাশি, না থাকলে ওপর-নিচে” — আর ব্রাউজার যেকোনো চওড়ায় নিজেই হিসাব করে। পর্দা মাপার কাজটা ব্রাউজারের, নিয়ম লেখার কাজটা আপনার।
এটি শুধু সুন্দর দেখানোর ব্যাপার নয়। ফোনে পাশে স্ক্রল করতে হলে, লেখা চিমটি দিয়ে বড় করতে হলে, বা বোতাম এত ছোট যে আঙুলে লাগে না — মানুষ পাতা ছেড়ে চলে যান। কম দৃষ্টিশক্তির মানুষ বড় পর্দাতেও লেখা বড় করে পড়েন, আর তখন তাঁর কাছে চওড়া মনিটরও “ছোট পর্দা” হয়ে যায় — সেই গল্প অংশ ৯-এ। আর Google এখন মূলত সাইটের মোবাইল রূপ দেখেই সূচি তৈরি করে (mobile-first indexing), তাই SEO-র জন্যও মোবাইলে ঠিক থাকা জরুরি।
২ · ইতিহাস — নির্দিষ্ট চওড়ার পাতা থেকে রেসপন্সিভ ভাবনা
আজকের নিয়মগুলো কেন এমন, বুঝতে হলে একটু পেছনে তাকাতে হবে। প্রতিটি যুগ আগের যুগের একটি সমস্যা সমাধান করেছে — আর নতুন একটি তৈরিও করেছে। “পরে” চেপে এগোন:
- নির্দিষ্ট চওড়া
width: 960pxডেস্কটপই সব - আলাদা m. সাইট
m.example.comদুটি সাইট - রেসপন্সিভ
@mediaMarcotte, ২০১০ - মোবাইল-ফার্স্ট
min-widthWroblewski - Intrinsic
auto-fit, @container২০২০-এর দশক
- নির্দিষ্ট চওড়ার যুগ। ১৯৯০-এর দশক আর ২০০০-এর দশকের বেশিরভাগ সময় ডিজাইনাররা ধরে নিতেন সবার পর্দা মোটামুটি এক রকম। পাতা বানানো হতো 760px, পরে 960px চওড়া বাক্সে — প্রায়ই
<table>বা float দিয়ে। ছোট পর্দায় পাশে স্ক্রল, বড় পর্দায় দুই পাশে বিশাল ফাঁকা জায়গা। - আলাদা মোবাইল সাইট। ফোনে ইন্টারনেট আসার পর অনেক প্রতিষ্ঠান দ্বিতীয় একটি সাইট বানাল — সাধারণত
m.দিয়ে শুরু ঠিকানায় (m-dot site). সার্ভার ব্রাউজারের পরিচয় দেখে ফোনকে সেখানে পাঠাত। কাজ চলত, কিন্তু দুটি সাইট মানে দুই গুণ রক্ষণাবেক্ষণ, প্রায়ই মোবাইলে কম তথ্য, আর ট্যাবলেট কোন দিকে যাবে — কেউ জানত না। - রেসপন্সিভ ওয়েব ডিজাইন। ২০১০ সালের মে মাসে Ethan Marcotte A List Apart পত্রিকায় “Responsive Web Design” নামে একটি লেখা প্রকাশ করেন, পরের বছর একই নামে বই। তাঁর প্রস্তাব: একটিই সাইট, তিনটি উপাদান দিয়ে — fluid grid, flexible image আর media query. নামটি তিনি নেন স্থাপত্যের “responsive architecture” ধারণা থেকে, যেখানে ভবন মানুষের উপস্থিতি অনুযায়ী বদলায়।
- মোবাইল-ফার্স্ট। প্রায় একই সময়ে Luke Wroblewski বলেন, নকশা শুরুই করুন ছোট পর্দা থেকে (২০০৯ সালে লেখা, ২০১১ সালে “Mobile First” বই)। ছোট পর্দা আপনাকে বাধ্য করে বেছে নিতে কোনটা সত্যিই জরুরি। CSS-এ এর রূপ: আগে সরল নিয়ম, তারপর
min-widthquery দিয়ে বড় পর্দায় যোগ। - Intrinsic আর container-ভিত্তিক যুগ। Flexbox, Grid,
minmax(),clamp()আর container query আসার পর অনেক কম্পোনেন্ট এখন কোনো media query ছাড়াই নিজের জায়গা দেখে মানিয়ে নেয় (পর্ব ২৮–২৯)। media query এখনো আছে, কিন্তু শেষ অস্ত্র হিসেবে — প্রথম নয়।
Media query নিজে Marcotte-এর আবিষ্কার নয়। CSS2 (১৯৯৮) আগেই media="print" বা screen-এর মতো মিডিয়া ধরন চিনত; পর্দার চওড়ার মতো বৈশিষ্ট্য দেখে শর্ত দেওয়ার প্রস্তাব আসে পরে, “Media Queries” spec-এ, যা ২০১২ সালে W3C Recommendation হয়। Marcotte-এর কৃতিত্ব হলো তিনটি আলাদা জিনিসকে একটি পরিষ্কার পদ্ধতিতে জুড়ে নাম দেওয়া — আর নামটাই পুরো শিল্পের ভাবনা বদলে দিল।
৩ · viewport meta — ফোন কেন পাতাকে 980px ভাবে
পর্ব ১৩-এ দেখেছেন, head-এর দ্বিতীয় লাইনটি প্রায় বাধ্যতামূলক:
<meta name="viewport" content="width=device-width, initial-scale=1">এবার দেখি রেসপন্সিভ CSS-এর সাথে এর সম্পর্ক। প্রথম iPhone (২০০৭) আসার সময় প্রায় সব সাইট ছিল ডেস্কটপের জন্য। তাই মোবাইল ব্রাউজার ধরে নিত পাতাটি প্রায় 980px চওড়া একটি “কল্পিত জানালায়” সাজানো — একে বলে layout viewport — তারপর পুরো ছবিটা ছোট করে ফোনে বসাত। আজও viewport meta না থাকলে বেশিরভাগ মোবাইল ব্রাউজার এটাই করে। আর media query মাপে ঠিক এই layout viewport — আপনার ফোনের আসল চওড়া নয়। নিচের ধাপগুলোতে একটি ৩৬০ CSS px চওড়া ফোন ধরে দেখুন:
2.cards { display: grid; gap: 1rem; }3@media (min-width: 48em) { /* 768px */4 .cards { grid-template-columns: repeat(3, 1fr); }5}
| ডিভাইস | |
| layout viewport | |
| min-width: 48em মেলে? | |
| কার্ডের কলাম |
- viewport meta নেই। ব্রাউজার ধরে নিল এটা পুরোনো ডেস্কটপ সাইট, তাই layout viewport প্রায় 980px. আপনার media query জিজ্ঞেস করল “জানালা কি অন্তত 768px?” — উত্তর হ্যাঁ! ফলে ফোনেই তিন কলাম, তারপর পুরো পাতা ছোট করে বসানো। আপনার রেসপন্সিভ CSS ঠিকই লেখা, কিন্তু ভুল মাপ দেখছে।
width=device-widthদিলেন। এবার layout viewport = ফোনের চওড়া, 360 CSS px. Media query মেলে না, তাই এক কলাম — যা আপনি চেয়েছিলেন।initial-scale=1বলে শুরুতে zoom ১০০%, আর ফোন ঘোরালেও মাপ ঠিকঠাক নতুন করে হিসাব হয়।- ফোন আড়াআড়ি। একই ফোন ঘোরালে চওড়া হয় (ধরা যাক প্রায় 800 CSS px; আসল সংখ্যা ফোনভেদে আলাদা)। Viewport বদলাল, media query আবার হিসাব হলো, এবার তিন কলাম। CSS একবারই লেখা — ব্রাউজার প্রতিবার নতুন করে প্রশ্ন করে।
- ডেস্কটপে zoom. ডেস্কটপ ব্রাউজার viewport meta পড়েই না; সেখানে layout viewport = জানালার চওড়া। কিন্তু zoom ২০০% করলে প্রতিটি CSS px দ্বিগুণ বড় হয়, তাই 1280px জানালায় আঁটে মাত্র 640 CSS px — media query তখন ছোট পর্দার নিয়ম ধরে। অর্থাৎ zoom করা ডেস্কটপও “ছোট পর্দা” — অংশ ৯-এর reflow পরীক্ষার ভিত্তি এটাই।
এখানে “CSS px” কথাটা খেয়াল করুন। ফোনের পর্দায় হয়তো ১০৮০টি আসল বিন্দু, কিন্তু ব্রাউজার বলে চওড়া 360px — কারণ একটি CSS pixel পর্দার একটি বিন্দু নয়, বরং চোখে মোটামুটি একই আকারে দেখানোর একটি মাপ (পর্ব ২০)। এখানে device pixel ratio 3. রেসপন্সিভ CSS-এর সব সংখ্যা এই CSS px-এ — ফোনের বিজ্ঞাপনের “রেজোলিউশন” দিয়ে breakpoint ভাবলে ভুল হবে।
এই পাতার প্রিভিউ কত চওড়া? — একটি সৎ পরীক্ষা
এই কোর্সের প্রতিটি লাইভ এডিটরের প্রিভিউ আসলে একটি <iframe> — পাতার ভেতরে আরেকটি ছোট জানালা। iframe-এর নিজের viewport থাকে, আর তা iframe-এর বাক্সের সমান চওড়া; viewport meta সেখানে কোনো কাজ করে না। তাই প্রিভিউর ভেতরের @media আপনার পর্দা নয়, প্রিভিউ-জানালার চওড়া দেখে — যা এই পাতার লেখার কলামের সমান। নিজেই মেপে দেখুন:
<style>
.badge { padding: 12px; font-family: sans-serif; background: #fee2e2; }
@media (min-width: 30em) { .badge { background: #fef3c7; } } /* 480px */
@media (min-width: 48em) { .badge { background: #dcfce7; } } /* 768px */
</style>
<p class="badge">লাল = 480px-এর কম · হলুদ = 480–767px · সবুজ = 768px বা বেশি</p>
<p id="out">মাপা হচ্ছে…</p>
<script>
function show() {
document.getElementById('out').textContent =
'প্রিভিউ-জানালা: ' + innerWidth + 'px · আপনার পুরো পর্দা: ' + screen.width + 'px';
}
(function m() {
if (!document.body.offsetWidth) return setTimeout(m, 50);
show();
console.log('innerWidth =', innerWidth, '| 30em:', matchMedia('(min-width: 30em)').matches,
'| 48em:', matchMedia('(min-width: 48em)').matches);
})();
addEventListener('resize', show);
</script>দুটি সংখ্যা দেখবেন: প্রিভিউ-জানালার চওড়া (innerWidth) আর আপনার পুরো পর্দার চওড়া (screen.width). কম্পিউটারে প্রথমটি সাধারণত দ্বিতীয়টির চেয়ে অনেক কম, আর বাক্সের রং ঠিক হয় প্রথমটি দেখে — পর্দা নয়। ফোনে খুললে প্রিভিউ প্রায় পর্দার সমান, তাই সম্ভবত লাল দেখবেন। চেষ্টা করুন: কম্পিউটারে ব্রাউজারের জানালা ছোট-বড় করুন — লেখার কলাম বদলালে সংখ্যা আর রং দুটোই বদলাবে। তারপর 48em-কে 20em করুন — এবার প্রায় সব প্রিভিউতে সবুজ। এই কারণেই এই পর্বের ডেমোগুলো টেনে ছোট-বড় করা বাক্সে (resize: horizontal) সাজানো: বাক্স টানলে ভেতরের লেআউট বদলায়, কিন্তু প্রিভিউর @media বদলায় না।
৪ · Fluid layout — px নয়, অনুপাতে ভাবুন
Marcotte-এর প্রথম উপাদান fluid layout: বাক্সের মাপ নির্দিষ্ট px-এ নয়, পাত্রের অনুপাতে। দর্জির উদাহরণ নিন — “পাঞ্জাবির হাতা ২২ ইঞ্চি” সবার গায়ে লাগে না, কিন্তু “হাতা কাঁধ থেকে কবজি পর্যন্ত” সবার গায়েই মাপমতো। আজ এর জন্য তিনটি প্রধান হাতিয়ার:
| হাতিয়ার | কী বলে | উদাহরণ |
|---|---|---|
| % | পাত্রের চওড়ার এত ভাগ | width: 90% |
| max-width | বাড়ো, কিন্তু এর বেশি নয় | max-width: 40rem |
| fr | বাকি জায়গা এই অনুপাতে ভাগ করো | grid-template-columns: 1fr 3fr |
ch, rem | লেখার মাপে চওড়া — পাঠযোগ্য লাইন | max-width: 65ch |
Marcotte-এর সময়ে Grid ছিল না, তাই তিনি একটি সূত্র দেন: লক্ষ্য ÷ পাত্র = ফল. 960px নকশায় 300px কলাম হলে 300 ÷ 960 = 31.25%. আজ fr আর gap এই হিসাব ব্রাউজারকেই করতে দেয়। নিচের ডটেড বাক্সটি শুরুতে 360px — একটি ছোট ফোনের মতো। ডান-নিচের কোণ ধরে চওড়া করুন:
.fixed { width: 600px; background: #fee2e2; }
.fluid {
width: 90%;
max-width: 30rem;
margin-inline: auto;
background: #dcfce7;
}
.cols {
display: grid;
grid-template-columns: 1fr 3fr;
gap: 8px;
}
/* দেখানোর জন্য: কোণ টেনে চওড়া বদলানো যায় */
.frame { resize: horizontal; overflow: auto; width: 360px;
max-width: 100%; box-sizing: border-box;
border: 2px dashed #64748b; padding: 8px; font-family: sans-serif; }
.frame div { padding: 8px; margin-block: 6px; border-radius: 6px; }
.cols div { background: #e0f2fe; margin: 0; }লাল বাক্সটি 600px-এ অনড়, তাই 360px বাক্সের বাইরে বেরিয়ে যায় আর ডটেড বাক্সে পাশে স্ক্রলবার আসে — ফোনে ঠিক এভাবেই পুরো পাতা পাশে নড়ে। সবুজটি সবসময় ৯০%, কিন্তু 30rem (480px)-এর বেশি কখনো নয়, আর margin-inline: auto তাকে মাঝখানে রাখে। নীল সারির দুই কলাম সবসময় ১ : ৩ অনুপাতে। চেষ্টা করুন: .fixed-এর width: 600px-কে max-width: 600px করুন — এখন ছোট বাক্সে আর উপচে পড়ে না, অথচ বড় বাক্সে 600px-এর বেশি হয় না। তারপর 1fr 3fr-কে 12rem 1fr করে বাক্স সরু করুন — নির্দিষ্ট মাপের মেনু কেন ফোনে সমস্যা, দেখতে পাবেন।
width আর max-width-এর এই অদলবদলটি রেসপন্সিভ CSS-এর সবচেয়ে কাজের অভ্যাস। “এই বাক্স 600px” নয়, বলুন “এই বাক্স বড়জোর 600px.” উচ্চতার ক্ষেত্রেও একই কথা: লেখাওয়ালা বাক্সে height দিলে ছোট পর্দায় লেখা লম্বা হয়ে উপচে পড়ে; দরকার হলে min-height দিন।
৫ · নমনীয় ছবি — max-width: 100% আর height: auto
দ্বিতীয় উপাদান flexible image. একটি ছবি replaced element — তার নিজের একটি স্বাভাবিক মাপ আছে। 1280px চওড়া ছবি 360px ফোনে রাখলে সে নিজের মাপেই থাকতে চায়, আর পুরো পাতাকে পাশে ঠেলে দেয়। দুই লাইনের সমাধানটি প্রায় প্রতিটি CSS reset-এ থাকে:
img {
max-width: 100%; /* পাত্রের চেয়ে বড় হবে না */
height: auto; /* চওড়া কমলে উচ্চতাও অনুপাতে কমবে */
display: block;
}
/* দেখানোর জন্য */
.frame { resize: horizontal; overflow: auto; width: 320px;
max-width: 100%; box-sizing: border-box;
border: 2px dashed #64748b; padding: 8px; font-family: sans-serif; }ছবিটি পুরোপুরি বাক্সের ভেতরে, ঠিক অনুপাতে। বাক্স চওড়া করলে ছবিও বড় হয় — কিন্তু নিজের আসল 1280px-এর বেশি কখনো নয়, কারণ max-width শুধু ওপরের সীমা। চেষ্টা করুন: height: auto; লাইনটি মুছে দিন — ছবি চেপ্টা হয়ে লম্বাটে হবে, কারণ HTML-এর height="714" তখনো খাটছে কিন্তু চওড়া কমে গেছে। তারপর max-width: 100%; মুছে দিন — ছবি বাক্সের বাইরে বেরিয়ে যাবে, ডটেড বাক্সে পাশে স্ক্রল।
তাহলে HTML-এ width আর height লিখব কেন, যদি CSS মাপ বদলেই দেয়? কারণ আধুনিক ব্রাউজার এই দুটি সংখ্যা থেকে ছবির aspect ratio আগেই জেনে নেয়, আর ছবি ডাউনলোড হওয়ার আগেই ঠিক মাপের জায়গা রেখে দেয়। ফলে ছবি এসে লেখা নিচে ঠেলে দেয় না — layout shift কমে (পর্ব ৬)। ভিডিও বা iframe-এর জন্যও একই চিন্তা: width: 100%; height: auto; অথবা aspect-ratio: 16 / 9;.
তবে একটি প্রশ্ন থেকে যায়: ফোনে তো ছবিটি ৩২০px-এ দেখানো হচ্ছে, অথচ ডাউনলোড হচ্ছে পুরো 1280px-এর ফাইল — মোবাইল ডেটার অপচয়। ছোট পর্দায় ছোট ফাইল পাঠানোর কৌশল (srcset, sizes, <picture>) পর্ব ৩২-এর বিষয়। আজকের নিয়মটি শুধু নিশ্চিত করে যে ছবি লেআউট ভাঙবে না।
৬ · মোবাইল-ফার্স্ট CSS — ছোট থেকে বড়
তৃতীয় উপাদান media query — “এই শর্ত মিললে এই নিয়মগুলো খাটাও।” কিন্তু শর্ত কোন দিক থেকে লিখবেন, তা নিয়েই দুটি পদ্ধতি:
🔼 Mobile-first
query-র বাইরের নিয়ম ছোট পর্দার জন্য — সাধারণত এক কলাম, সরল। তারপর @media (min-width: …) দিয়ে চওড়া পর্দায় কলাম, sidebar ইত্যাদি যোগ হয়।
🔽 Desktop-first
বাইরের নিয়ম বড় পর্দার জন্য — কয়েক কলাম। তারপর @media (max-width: …) দিয়ে ছোট পর্দায় সেগুলো বাতিল করতে হয়।
পার্থক্যটা শুধু রুচির নয়। এক কলামের লেআউট HTML-এর normal flow-এ প্রায় বিনা খরচে পাওয়া যায় — block element এমনিতেই ওপর-নিচে বসে। তাই মোবাইল-ফার্স্ট CSS ছোট পর্দায় প্রায় কিছুই “উল্টাতে” হয় না। আর যে পুরোনো বা দুর্বল ব্রাউজার media query বোঝে না, সে অন্তত সরল, পড়ার উপযোগী এক কলামের পাতা পায় — এটাই progressive enhancement. ধাপে ধাপে দেখুন, তিন রকম চওড়ায় ব্রাউজার কোন নিয়মগুলো খাটায়:
1.page { padding: 1rem; }2.cards { display: grid; gap: 1rem; }3nav ul { display: flex; flex-wrap: wrap; }4@media (min-width: 30em) { /* 480px */5 .cards { grid-template-columns: 1fr 1fr; }6}7@media (min-width: 60em) { /* 960px */8 .page { display: grid; grid-template-columns: 15rem 1fr; }9 .cards { grid-template-columns: repeat(3, 1fr); }10}
| viewport | |
| কার্ডের কলাম | |
| পাশের মেনু | |
| বাতিল করা নিয়ম |
- ৩২০px — শুধু ভিত্তি। দুটি query-ই মেলে না। ব্রাউজার খাটায় কেবল প্রথম তিন লাইন: চারপাশে একটু ফাঁক, কার্ডগুলো এক কলামে ওপর-নিচে, মেনুর লিংক জায়গা না আঁটলে পরের লাইনে। ছোট পর্দার জন্য আলাদা কোনো কোড লাগেনি — এটাই ভিত্তি।
- ৬০০px — প্রথম যোগ।
min-width: 30emমিলল, তাই লাইন ৫ যোগ হলো: কার্ড দুই কলামে। ভিত্তির নিয়মগুলো যেমন ছিল তেমনই, কিছু বাতিল হয়নি। - ১১০০px — দুটোই মেলে। এবার দুটি query-ই সত্য। লাইন ৫ আর লাইন ৯ দুটোই
.cards-এর কলাম বলে; একই specificity, তাই পরে লেখা লাইন ৯ জেতে (পর্ব ১৮-এর cascade). এজন্যই মোবাইল-ফার্স্টে query লেখা হয় ছোট থেকে বড় ক্রমে। - উল্টো পথে হলে? Desktop-first-এ বাইরের নিয়মে থাকত তিন কলাম আর sidebar-ওয়ালা grid; তারপর
@media (max-width: 59.99em)-এ grid বন্ধ, sidebar সরানো, কলাম কমানো — অর্থাৎ ছোট পর্দাকে আগে জটিল নিয়ম পড়ে তারপর সেগুলো বাতিল করতে হতো। যত বড় সাইট, তত বেশি “উল্টানো” আর তত বেশি ভুলের সুযোগ।
কথায় না বলে নিজের হাতে দেখুন। নিচের এডিটরে “ফোন”-টি আসলে প্রিভিউর ভেতরে আরেকটি ছোট iframe — তাই তার ভেতরের @media সত্যিই ফোনের চওড়া দেখে, প্রিভিউর নয়। ডান-নিচের কোণ টেনে চওড়া করুন:
<style>
.device { resize: horizontal; overflow: auto; width: 320px; min-width: 240px;
max-width: 100%; border: 3px solid #334155; border-radius: 12px; }
.device iframe { display: block; width: 100%; height: 250px; border: 0; }
</style>
<div class="device"><iframe title="ছোট পর্দার নমুনা"></iframe></div>
<template id="shop">
<style>
body { margin: 0; font-family: sans-serif; }
nav { background: #0f766e; color: #fff; padding: 8px; }
nav::after { content: " · ছোট পর্দা"; }
.cards { display: grid; gap: 8px; padding: 8px; }
.cards p { margin: 0; padding: 12px; background: #dcfce7; border-radius: 8px; }
@media (min-width: 25em) {
.cards { grid-template-columns: 1fr 1fr; }
nav::after { content: " · মাঝারি"; } }
@media (min-width: 37.5em) {
.cards { grid-template-columns: repeat(3, 1fr); }
nav::after { content: " · বড় পর্দা"; } }
</style>
<nav>হাটবাজার (কাল্পনিক)</nav>
<div class="cards"><p>চাল</p><p>ডাল</p><p>তেল</p><p>পেঁয়াজ</p><p>আলু</p><p>লবণ</p></div>
</template>
<script>
document.querySelector('.device iframe').srcdoc = document.getElementById('shop').innerHTML;
</script>শুরুতে “ফোন” 320px: সবুজ কার্ডগুলো এক কলামে, ওপরের পট্টিতে লেখা “ছোট পর্দা”। কোণ টেনে চওড়া করুন — 400px (25em) পেরোলেই দুই কলাম আর “মাঝারি”, 600px (37.5em) পেরোলে তিন কলাম আর “বড় পর্দা”। (লেখার কলাম 600px-এর চেয়ে সরু হলে, যেমন ফোনে, শেষ ধাপটি দেখা যাবে না।) ভেতরের CSS-টি <template>-এর মধ্যে, বদলালেই ফোন নতুন করে আঁকা হয়। চেষ্টা করুন: দ্বিতীয় query-র 37.5em-কে 30em করুন — তিন কলাম আরও আগে আসবে। তারপর দুটি query-র জায়গা অদলবদল করুন — সবচেয়ে চওড়া অবস্থাতেও দুই কলাম থাকবে কেন, ওপরের ডায়াগ্রামের ধাপ ৩ মনে করুন।
আধুনিক লেখার রূপ — range syntax
Media Queries Level 4 শর্তটি গণিতের মতো লেখার সুযোগ দেয়: @media (width >= 30em), বা মাঝামাঝি পরিসরে @media (30em <= width < 60em). পুরোনো min-width/max-width রূপে “max-width: 59.99em” জাতীয় ভগ্নাংশের কৌশল লাগত, যাতে ঠিক 60em-এ দুটি নিয়ম একসাথে না মেলে; নতুন রূপে < আর <=-এর পার্থক্যই সেটা সামলায়। এই range syntax এখন Baseline Widely available; খুব পুরোনো ব্রাউজারের কথা ভাবতে হলে min-width রূপটিও পুরোপুরি বৈধ আর এখনো সবচেয়ে বেশি দেখা যায়। media query-র বাকি সব বৈশিষ্ট্য আর container query পর্ব ৩১-এ।
৭ · Breakpoint বাছুন content দেখে, ফোনের মডেল দেখে নয়
Breakpoint মানে যে চওড়ায় লেআউটের নিয়ম বদলায়। নতুনরা প্রায়ই জনপ্রিয় ডিভাইসের তালিকা থেকে সংখ্যা নেন — “iPhone 375, iPad 768, ল্যাপটপ 1024.” সমস্যা হলো বাজারে হাজারো মাপের ডিভাইস, প্রতি বছর নতুন আসে, আর ব্রাউজারের জানালা যেকোনো মাপে টেনে রাখা যায়। ডিভাইসের তালিকা কখনো সম্পূর্ণ হয় না।
পেশাদার পদ্ধতি উল্টো: সবচেয়ে সরু পর্দা থেকে শুরু করে পাতাটি ধীরে ধীরে চওড়া করুন। যেখানে নকশা “ভাঙে” — লাইন অস্বস্তিকর লম্বা, কার্ড অযথা বিশাল, অনেক ফাঁকা জায়গা — ঠিক সেখানে একটি breakpoint. ডিভাইস নয়, content ঠিক করে সংখ্যাটা:
আগামী তিন দিন উত্তরাঞ্চলের নদীগুলোর পানি বাড়তে পারে বলে জানানো হয়েছে।
আগামী তিন দিন উত্তরাঞ্চলের নদীগুলোর পানি বাড়তে পারে বলে জানানো হয়েছে।
আগামী তিন দিন উত্তরাঞ্চলের নদীগুলোর পানি বাড়তে পারে বলে জানানো হয়েছে। লাইন এত লম্বা যে চোখ পরের লাইনের শুরু খুঁজে পেতে কষ্ট পায়।
আগামী তিন দিন উত্তরাঞ্চলের নদীগুলোর পানি বাড়তে পারে।
- সবচেয়ে সরু থেকে শুরু। 320px-এ এক কলাম; এক লাইনে মোটামুটি ৩৫টি অক্ষর। ছবি পুরো চওড়া। এখানে কোনো সমস্যা নেই, breakpoint-এর দরকারও নেই।
- ধীরে চওড়া করুন। 560px-এ এক লাইনে প্রায় ৬৫ অক্ষর — ছাপাখানার পুরোনো অভিজ্ঞতায় পড়ার জন্য আরামদায়ক measure-এর কাছাকাছি। ছবিও বড় হয়েছে, সুন্দর দেখাচ্ছে। এখনো বদলানোর কিছু নেই।
- এখানে ভাঙল। 900px-এ লাইনে ১০০-এর বেশি অক্ষর; চোখ এক লাইন শেষ করে পরের লাইনের শুরু খুঁজতে হিমশিম খায়, ছবিও অকারণে বিশাল। কোনো ডিভাইসের নাম নেই — content নিজেই বলে দিল, এখানে কিছু করতে হবে।
- Breakpoint বসান — বা দরকারই নেই। দুটি পথ: ভাঙার জায়গার একটু আগে (ধরা যাক 48em) পাশে দ্বিতীয় কলাম যোগ করা, অথবা লেখার কলামে
max-width: 65chদিয়ে লাইনকে লম্বা হতেই না দেওয়া — তখন কোনো breakpoint-ই লাগে না। এক পাতায় সাধারণত দু-তিনটি “বড়” breakpoint যথেষ্ট; ছোটখাটো সমন্বয় কম্পোনেন্টের নিজের ভেতরে।
আরও গভীরে: media query-র শর্তে em বা rem লিখলে তা পাতার html-এর font-size নয়, ব্রাউজারের প্রাথমিক font-size (সাধারণত 16px) ধরে হিসাব হয় — কারণ media query কোনো element-এর ওপর বসে না, তাই কার font-size, সেই প্রশ্নই নেই। এর সুবিধা: কেউ ব্রাউজারের সেটিংসে ডিফল্ট লেখা বড় করলে 48em breakpoint-ও আনুপাতিকভাবে সরে যায়, ফলে বড় লেখার মানুষ আগেই সরল, এক কলামের লেআউট পান। px-এর breakpoint এই পছন্দ দেখে না। এজন্য অনেক অভিজ্ঞ ডেভেলপার breakpoint em-এ লেখেন।
media query ছাড়াই রেসপন্সিভ — আগে এগুলো চেষ্টা করুন
পর্ব ২৮ আর ২৯-এ দেখেছেন, অনেক কম্পোনেন্ট নিজের জায়গা দেখে নিজেই মানিয়ে নিতে পারে — একে বলে intrinsic layout. এর বড় সুবিধা: কার্ডের তালিকা চওড়া main-এ বসুক বা সরু sidebar-এ, একই কোড দুই জায়গাতেই ঠিক আচরণ করে, কারণ সিদ্ধান্ত নেয় পাত্র, পর্দা নয়। নিচের বাক্সটি টেনে দেখুন:
.tags {
display: flex;
flex-wrap: wrap; /* না আঁটলে পরের লাইনে */
gap: 6px;
list-style: none; padding: 0;
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(9rem, 100%), 1fr));
gap: 8px;
}
/* সাজসজ্জা আর টেনে বড়-ছোট করার বাক্স */
.tags li { background: #e0f2fe; border-radius: 999px; padding: 2px 10px; }
.grid p { margin: 0; padding: 14px; background: #dcfce7; border-radius: 8px; }
.frame { resize: horizontal; overflow: auto; width: 300px; max-width: 100%;
box-sizing: border-box; border: 2px dashed #64748b;
padding: 8px; font-family: sans-serif; }300px বাক্সে শহরের ট্যাগগুলো দুই লাইনে ভেঙেছে, আর টিকিটের কার্ড এক কলামে, ওপর-নিচে। কোণ টেনে চওড়া করুন — ট্যাগ এক লাইনে চলে আসবে, কার্ড দুই, তিন, তারপর চার কলামে; আবার সরু করলে এক কলামে ফিরবে। পুরো CSS-এ একটিও @media নেই: flex-wrap আর auto-fit + minmax() নিজেরাই হিসাব করছে। চেষ্টা করুন: 9rem-কে 14rem করুন — কলাম কমবে, কার্ড চওড়া হবে। তারপর min(9rem, 100%)-কে শুধু 9rem করে বাক্সটি খুব সরু করুন — কার্ড বাক্সের বাইরে বেরিয়ে যাবে; min() কেন দরকার, বুঝবেন।
৮ · আঙুলের জন্য নকশা — touch target আর hover
মাউসের ডগা এক বিন্দু; আঙুলের ডগা বেশ মোটা, আর যা চাপছেন সেটা আঙুলের নিচে ঢাকা পড়ে যায়। চলন্ত বাসে বা রিকশায় হাত কাঁপে। তাই ফোনের জন্য নকশায় দুটি প্রশ্ন জরুরি: চাপার জায়গা কত বড়, আর মাউসের hover-এর ওপর কতটা নির্ভর করছেন।
Touch target-এর মাপ
যে জায়গায় আঙুল বা মাউস দিয়ে চাপলে কাজ হয়, তা touch target. WCAG 2.2-এর success criterion 2.5.8 Target Size (Minimum) (AA স্তর) বলে: চাপার জায়গা অন্তত 24×24 CSS px হবে — অথবা ছোট হলে আশপাশে এমন ফাঁকা জায়গা থাকবে যাতে 24px ব্যাসের একটি বৃত্ত পাশের target-কে না ছোঁয়। কিছু ব্যতিক্রম আছে, যেমন বাক্যের ভেতরের লিংক। এটি সর্বনিম্ন সীমা। আরও কঠোর AAA শর্ত 2.5.5 চায় 44×44, আর Apple-এর নির্দেশিকা প্রায় 44pt, Google-এর Material Design প্রায় 48dp সুপারিশ করে। কাজের নিয়ম: প্রধান বোতাম আর মেনুর লিংক 44–48px উঁচু রাখুন।
<style>
body { font-family: sans-serif; }
nav a { color: #0f766e; }
.small a { font-size: 13px; margin-inline-end: 4px; }
.big { display: flex; flex-wrap: wrap; gap: 8px; }
.big a {
display: inline-flex; align-items: center;
min-block-size: 44px; padding-inline: 14px;
border: 1px solid #94a3b8; border-radius: 8px; text-decoration: none;
}
.status::after { content: "এই ডিভাইসে hover নেই — touch বা অন্য কিছু"; }
@media (hover: hover) and (pointer: fine) {
.big a:hover { background: #ccfbf1; }
.status::after { content: "এই ডিভাইসে মাউসের মতো hover আছে"; }
}
</style>
<nav class="small"><a href="#a">হোম</a><a href="#b">অফার</a><a href="#c">অর্ডার</a></nav>
<nav class="big"><a href="#a">হোম</a><a href="#b">অফার</a><a href="#c">অর্ডার</a></nav>
<p class="status"></p>ওপরের সারির লিংকগুলো খুদে আর গায়ে গায়ে লাগানো — ফোনে ভুল লিংকে চাপ পড়া খুব স্বাভাবিক। নিচের সারিতে প্রতিটি লিংক অন্তত 44px উঁচু, চারপাশে padding আর মাঝে ফাঁক; পুরো বাক্সটিই চাপার জায়গা। শেষ লাইনটি বলে দেয় আপনার ডিভাইসে মাউসের মতো hover আছে কি না — কম্পিউটারে আর ফোনে আলাদা লেখা দেখবেন, আর hover রং শুধু মাউসেই আসে। চেষ্টা করুন: min-block-size-কে 24px করুন — WCAG-এর সর্বনিম্ন সীমা; চোখে দেখুন কতটা ছোট। তারপর gap: 8px মুছে দিন — বোতামগুলো গায়ে লেগে গেলে ভুল চাপের ঝুঁকি কীভাবে বাড়ে, ভাবুন।
Hover বনাম touch
মাউসে কোনো কিছুর ওপর পয়েন্টার রাখলেই :hover হয়; touch-পর্দায় “ওপরে রাখা” বলে কিছু নেই। অনেক ফোন ব্রাউজার প্রথম চাপে hover দেখায়, দ্বিতীয় চাপে লিংক খোলে — বিভ্রান্তিকর। তাই দুটি নিয়ম:
- জরুরি কিছু hover-এ লুকাবেন না। দাম, মুছে ফেলার বোতাম, মেনু — hover ছাড়াও দেখা বা পাওয়া যেতে হবে। hover শুধু বাড়তি সাজ।
- hover-এর সাজ শর্ত দিয়ে দিন।
@media (hover: hover)মানে মূল পয়েন্টার দিয়ে সহজে hover করা যায়;(pointer: fine)মানে মূল পয়েন্টার সূক্ষ্ম (মাউস),(pointer: coarse)মানে মোটা (আঙুল)। এই interaction media feature-গুলো Baseline Widely available. কিন্তু “hover নেই” মানেই “ফোন” নয় — touch ল্যাপটপ, স্টাইলাস, টিভির রিমোট সবই আছে; পুরো ছবি পর্ব ৩১-এ।
৯ · পরীক্ষা — DevTools, আসল ফোন, ধীর নেটওয়ার্ক আর ৩২০px
রেসপন্সিভ পাতা “বানিয়েছি” বলা আর “পরীক্ষা করেছি” বলা এক কথা নয়। চারটি স্তরে পরীক্ষা করুন:
DevTools device toolbar
Chrome বা Edge-এ F12, তারপর Ctrl+Shift+M (Mac-এ Cmd+Shift+M). “Responsive” মোডে কিনারা টেনে 320px থেকে বড় পর্যন্ত ধীরে ধীরে চওড়া করুন — কোথায় ভাঙছে, দেখুন। Firefox-এ এর নাম Responsive Design Mode.
device toolbarআসল ফোন
DevTools পর্দার মাপ নকল করে, কিন্তু আঙুলের চাপ, on-screen কীবোর্ড, ঠিকানা-বারের ওঠানামা, ফোনের প্রসেসরের গতি নকল করতে পারে না। অন্তত একটি সস্তা Android ফোনে নিজের আঙুলে চালিয়ে দেখুন।
touch, কীবোর্ড, গতিধীর নেটওয়ার্ক
DevTools-এর Network panel-এ throttling মেনু থেকে “Slow 4G” বা “3G”-এর মতো একটি preset বেছে পাতা আবার লোড করুন। লোড-শেডিংয়ের সময় দুর্বল সংযোগে মানুষ কী দেখেন — খালি পাতা, না লেখা আগে? একে বলে network throttling.
Slow 4G, 3G320px আর ৪০০% zoom
WCAG 1.4.10 Reflow (AA): 320 CSS px চওড়ায় লেখা আর কাজ দুই দিকে স্ক্রল ছাড়া ব্যবহার করা যাবে। 1280px জানালায় ৪০০% zoom = 320 CSS px. ব্যতিক্রম শুধু মানচিত্র, বড় ডেটা টেবিলের মতো জিনিস, যার জন্য দুই দিকের লেআউট সত্যিই দরকার।
WCAG 1.4.10320px পরীক্ষায় পাতা পাশে নড়লে কোন বাক্সটি দায়ী, তা খুঁজতে Elements প্যানেলের Styles-এ একটি অস্থায়ী নিয়ম যোগ করুন — * { outline: 1px solid red; }. সব element-এর চারপাশে লাল দাগ পড়বে, আর যে বাক্সটি ডান কিনারা পেরিয়ে গেছে, সেটি সাথে সাথে চোখে পড়বে। সাধারণ অপরাধী: নির্দিষ্ট width, max-width ছাড়া ছবি, না ভাঙা লম্বা URL, আর padding-সহ width: 100%. overflow-x: hidden দিয়ে লুকাবেন না — তাতে সমস্যা কাটে না, শুধু কাটা পড়া অংশ অদৃশ্য হয় (পর্ব ২৩)।
পরীক্ষা ও ইন্টারভিউতে — বিশ্ববিদ্যালয়, চাকরি বা ফ্রন্ট-এন্ড ইন্টারভিউর পরীক্ষায় এ ধরনের প্রশ্ন প্রায়ই আসে:
- রেসপন্সিভ ওয়েব ডিজাইনের তিনটি মূল উপাদান কী? — fluid grid (অনুপাতে মাপা লেআউট), flexible image আর media query; Ethan Marcotte, ২০১০.
- viewport meta tag কী করে, না দিলে কী হয়? — layout viewport-কে ডিভাইসের চওড়ার সমান করে; না দিলে মোবাইল ব্রাউজার প্রায় 980px ধরে পাতা ছোট করে দেখায়, media query-ও সেই মাপ দেখে।
- Mobile-first আর desktop-first-এর পার্থক্য? — mobile-first-এ ভিত্তি ছোট পর্দার,
min-widthquery দিয়ে যোগ; desktop-first-এ ভিত্তি বড় পর্দার,max-widthquery দিয়ে বাতিল। - ছবি যেন পাত্র ছাড়িয়ে না যায়? —
img { max-width: 100%; height: auto; }, আর HTML-এwidth/heightattribute রাখুন যাতে layout shift না হয়। - Breakpoint কীভাবে বাছবেন? — জনপ্রিয় ডিভাইসের মাপ দেখে নয়; সরু থেকে চওড়া করে যেখানে content ভাঙে সেখানে, সম্ভব হলে em-এ।
১০ · AI-এর যুগে — রেসপন্সিভ কাজ AI-কে দিলে কী দেখবেন
AI টুল প্রায় সবসময় “রেসপন্সিভ” লেখা কোড দেয়, আর ল্যাপটপে খুললে ঠিকঠাক দেখায়ও। কিন্তু AI নিজে কোনো ফোনে পাতাটি খুলে দেখে না; সে ইন্টারনেটের নানা যুগের কোড মিলিয়ে লেখে — তাই পুরোনো টেমপ্লেটের অভ্যাস, ডিভাইসভিত্তিক breakpoint আর অ্যাক্সেসিবিলিটির ভুল প্রায়ই ঢুকে পড়ে।
AI সাধারণত যেসব রেসপন্সিভ-ভুল করে
| AI-এর ভুল | আপনি যা দেখবেন | ঠিক উপায় |
|---|---|---|
viewport-এ maximum-scale=1, user-scalable=no | ফোনে চিমটি দিয়ে বড় করা যায় না | শুধু width=device-width, initial-scale=1 |
desktop-first, অনেকগুলো max-width query | ছোট পর্দায় নিয়ম উল্টাতে উল্টাতে ভুল | ভিত্তি মোবাইলের, min-width দিয়ে যোগ |
| 320, 375, 414, 768, 1024… — ডিভাইসের তালিকা ধরে breakpoint | মাঝের মাপে হঠাৎ ভাঙা লেআউট | content দেখে দু-তিনটি breakpoint, বাকিটা intrinsic |
কন্টেইনারে width: 1200px | পাশে স্ক্রল | max-width + margin-inline: auto |
ছোট পর্দায় display: none দিয়ে content লুকানো | মোবাইলের মানুষ তথ্য পান না | সাজানো বদলান, তথ্য নয় |
| শুধু hover-এ খোলা মেনু, খুদে আইকন-বোতাম | ফোনে মেনু খোলে না, ভুল চাপ | চাপলে খোলে এমন বোতাম, 44px+ target |
body { overflow-x: hidden; } দিয়ে সমস্যা চাপা | লেখা বা বোতামের অংশ কাটা | যে বাক্স উপচে পড়ছে, সেটি ঠিক করুন |
AI-কে রেসপন্সিভ কাজ দেওয়ার সময় পদ্ধতি আর পরীক্ষার শর্ত আগেই বলে দিন। শেষের প্রশ্নটি খেয়াল করুন — AI-কে নিজের কোড ৩২০px-এ “মনে মনে চালাতে” বাধ্য করলে অনেক ভুল সে নিজেই ধরে ফেলে, আর আপনি জানেন কোথায় মিলিয়ে দেখতে হবে।
AI-এর দেওয়া রেসপন্সিভ কোড হাতে পেলে — যাচাইয়ের চেকলিস্ট
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন। এগুলোই আপনাকে CSS লেখক থেকে রেসপন্সিভ-চিন্তক বানাবে।
প্র ০১আলাদা m. সাইট রাখা, নাকি একটিই রেসপন্সিভ সাইট — বড় প্রতিষ্ঠান এখনো m. সাইট রাখে কেন, আর বেশিরভাগ সাইট সরে এলো কেন?
m. সাইটের যুক্তি একসময় খুব শক্ত ছিল। ২০০০-এর দশকের ফোনের ব্রাউজার দুর্বল, পর্দা ছোট, নেটওয়ার্ক ধীর আর দামি। সার্ভার যদি ব্রাউজারের পরিচয় (User-Agent) দেখে বুঝে নেয় “এটা ফোন”, তাহলে তাকে একেবারে হালকা, আলাদা করে বানানো পাতা পাঠানো যায় — কম ছবি, কম কোড, ছোট ফাইল। এখনো কয়েকটি বিশাল সোশ্যাল সাইট বা সংবাদ প্রতিষ্ঠান আলাদা মোবাইল সংস্করণ রাখে, কারণ তাদের দল বড়, আর খুব দুর্বল ফোন ও নেটওয়ার্কের মানুষদের জন্য আলাদাভাবে হালকা অভিজ্ঞতা বানানোর সামর্থ্য আছে।
কিন্তু বেশিরভাগের জন্য দাম অনেক বেশি:
- দুটি সাইট, দুই গুণ কাজ: প্রতিটি নতুন বৈশিষ্ট্য, প্রতিটি ভুল সংশোধন দুই জায়গায়। সময়ের সাথে দুটি সংস্করণ আলাদা হয়ে যায় — মোবাইলে “এই তথ্যটা নেই, ডেস্কটপ সংস্করণ দেখুন”।
- অনুমান ভুল হয়: User-Agent দেখে ডিভাইস চেনা অনির্ভরযোগ্য। ট্যাবলেট, ভাঁজ করা ফোন, ডেস্কটপ-মোড চালু করা ফোন — কোনটা কোথায় যাবে?
- লিংক আর SEO জটিল: কেউ ফোন থেকে m. লিংক শেয়ার করলে ডেস্কটপের বন্ধু ছোট পাতা পান। সার্চ ইঞ্জিনকে বোঝাতে দুই সংস্করণের মধ্যে বিশেষ সংযোগ (
rel="alternate"আর canonical) রাখতে হয়। Google নিজেই রেসপন্সিভ ডিজাইনকে সবচেয়ে সহজ পথ হিসেবে সুপারিশ করে।
রেসপন্সিভ ডিজাইনে একটি URL, একটি HTML, আর পর্দা অনুযায়ী CSS — সব মানুষ একই তথ্য পান। দুর্বল নেটওয়ার্কের সমস্যা এখন সমাধান হয় অন্য পথে: ছোট পর্দায় ছোট ছবি (পর্ব ৩২), কম JavaScript, ক্যাশিং আর পারফরম্যান্সের কৌশল (পর্ব ৪৯)।
মূল উপলব্ধি: “একই জিনিসের দুটি কপি” প্রায় সব প্রকৌশলে রক্ষণাবেক্ষণের দুঃস্বপ্ন। একটি উৎস রেখে উপস্থাপন বদলানো — HTML-এ অর্থ, CSS-এ সাজ — ওয়েবের মৌলিক নকশার সাথেই মেলে।
প্র ০২Ethan Marcotte-এর তিনটি উপাদান — fluid grid, flexible image, media query — আজকের CSS-এ কীভাবে বদলে গেছে?
২০১০ সালের লেখাটির মূল ভাবনা আজও খাঁটি, কিন্তু প্রতিটি উপাদানের হাতিয়ার অনেক উন্নত হয়েছে।
- Fluid grid → Flexbox, Grid, fr আর minmax(): Marcotte-কে float করা কলামের চওড়া হাতে হিসাব করে শতাংশে লিখতে হতো (লক্ষ্য ÷ পাত্র), আর gutter-এর জন্য আলাদা শতাংশ। আজ
grid-template-columns: 1fr 3frআরgapলিখলেই ব্রাউজার হিসাব করে;repeat(auto-fit, minmax(…))কলামের সংখ্যাও নিজে ঠিক করে। অর্থাৎ grid এখন শুধু fluid নয়, intrinsic. - Flexible image → srcset, sizes, picture, aspect-ratio:
max-width: 100%ছবিকে লেআউটে ধরে রাখে, কিন্তু ফোনেও বড় ফাইল নামায়। পরে HTML-এ এলো ছোট-বড় একাধিক ফাইল থেকে ব্রাউজারকে বাছতে দেওয়ার ব্যবস্থা, আরwidth/heightattribute থেকে অনুপাত জেনে জায়গা রাখার নিয়ম। “ছবি নমনীয়” এখন মানে লেআউট, ফাইলের মাপ আর লোড হওয়ার স্থিরতা — তিনটিই। - Media query → container query আর আরও অনেক শর্ত: media query পুরো viewport দেখে, কিন্তু একটি কার্ড জানতে চায় তার নিজের জায়গা কত।
@containerএখন Baseline, তাই কম্পোনেন্ট নিজের পাত্র দেখে সাজ বদলায়। আর media query নিজেও বড় হয়েছে: শুধু চওড়া নয়,hover,pointer,prefers-color-scheme,prefers-reduced-motion— ব্যবহারকারীর ডিভাইস আর পছন্দ দুটোই।
তার সাথে এসেছে clamp() দিয়ে লেখার আকার মসৃণভাবে বাড়ানো (পর্ব ৩৫) — breakpoint-এ হঠাৎ লাফ নয়, ক্রমশ বদল। ফলে আধুনিক রেসপন্সিভ পাতায় media query-র সংখ্যা প্রায়ই অনেক কমে গেছে।
মূল উপলব্ধি: একটি ভালো ধারণা টুলের চেয়ে বেশি দিন টেকে। Marcotte-এর আসল অবদান তিনটি কৌশল নয়, একটি দৃষ্টিভঙ্গি — “ওয়েব নমনীয় মাধ্যম, ছাপা কাগজ নয়।” টুল বদলায়, দৃষ্টিভঙ্গি থাকে।
প্র ০৩“মোবাইল-ফার্স্ট” কি শুধু CSS-এ min-width লেখার একটি ক্রম, নাকি এর চেয়ে বড় কিছু?
Luke Wroblewski যখন “Mobile First” বলেছিলেন, তিনি মূলত CSS নয়, নকশা আর অগ্রাধিকারের কথা বলছিলেন। তাঁর যুক্তি ছিল তিনটি: মোবাইল দ্রুত বাড়ছে, তাই সেখান থেকে শুরু করাই বুদ্ধিমানের; ছোট পর্দা আপনাকে বাছাই করতে বাধ্য করে; আর ফোনের নিজস্ব সুবিধা (touch, অবস্থান, ক্যামেরা) নতুন সুযোগ দেয়।
দ্বিতীয় যুক্তিটিই সবচেয়ে গভীর। ডেস্কটপের চওড়া পাতায় সবকিছু রাখা যায় — ব্যানার, তিনটি sidebar, দশটি লিংক — আর কোনটা জরুরি, সেই কঠিন সিদ্ধান্ত এড়ানো যায়। ৩৬০px-এ সেই সুযোগ নেই। একটি অনলাইন দোকানের পণ্যের পাতায় ফোনে প্রথমে কী থাকবে? ছবি, দাম, “কার্টে যোগ করুন” — বাকিটা নিচে। এই অগ্রাধিকার ঠিক হলে ডেস্কটপ সংস্করণও পরিষ্কার হয়, কারণ এখন জানেন আসল জিনিস কোনটা।
দ্বিতীয় স্তর পারফরম্যান্স আর সহনশীলতা। বাংলাদেশে অনেকেই সস্তা ফোন আর সীমিত ডেটা প্যাকেজ ব্যবহার করেন, আর দুর্বল সংযোগ খুব সাধারণ অভিজ্ঞতা। মোবাইল-ফার্স্ট ভাবনা মানে প্রথমে সেই মানুষের জন্য হালকা, দ্রুত পাতা — তারপর শক্তিশালী ডিভাইসে বাড়তি সাজ। একটি সতর্কতা: CSS-এর ক্রম নিজে ডাউনলোডের মাপ কমায় না — ব্রাউজার সাধারণত সব CSS-ই নামায়, মেলে না এমন query-সহ। তাই মোবাইল-ফার্স্ট CSS লিখেও ভারী ছবি আর বিশাল JavaScript পাঠালে লাভ নেই।
CSS-এর ক্রম (ভিত্তি ছোট পর্দার, min-width দিয়ে যোগ) এই ভাবনার একটি প্রয়োগ মাত্র — এবং কাজের প্রয়োগ, কারণ কম নিয়ম “উল্টাতে” হয়।
মূল উপলব্ধি: সীমাবদ্ধতা নকশার শত্রু নয়, শিক্ষক। ছোট পর্দা, ধীর নেটওয়ার্ক আর আঙুলের মোটা ডগা — এই তিনটি মেনে বানানো পাতা সবার জন্য ভালো হয়, বড় পর্দার মানুষের জন্যও।
প্র ০৪Breakpoint px-এ লিখব, নাকি em-এ? আর “ফোন 375, ট্যাবলেট 768” — এই চেনা সংখ্যাগুলো ব্যবহারে আপত্তি কোথায়?
দুটি প্রশ্নই আসলে এক প্রশ্নের দুই দিক: breakpoint কিসের ওপর নির্ভর করবে — ডিভাইসের ওপর, নাকি content আর মানুষের ওপর?
চেনা সংখ্যার ইতিহাস: 768px এসেছে প্রথম দিকের iPad-এর খাড়া চওড়া থেকে, 1024 তার আড়াআড়ি থেকে, 320 প্রথম দিকের iPhone থেকে। এক সময় এই কয়েকটি ডিভাইসই বাজার দখল করে ছিল, তাই সংখ্যাগুলো যুক্তিসংগত ছিল। আজ Android-এর শত শত মডেল, ভাঁজ করা ফোন, নানা মাপের ল্যাপটপ আর ইচ্ছেমতো টেনে রাখা জানালা — 768 এখন একটি অভ্যাস, কোনো সত্য নয়। আর সংখ্যাগুলো আপনার content সম্পর্কে কিছুই জানে না: আপনার বাংলা শিরোনাম হয়তো 690px-এ ভাঙে, 768-এ নয়।
px বনাম em: media query-তে em ব্রাউজারের প্রাথমিক font-size ধরে হিসাব হয়। কেউ ব্রাউজারের সেটিংসে ডিফল্ট লেখা 16px থেকে 24px করলে 48em breakpoint 768px থেকে সরে 1152px-এ চলে যায় — অর্থাৎ বড় লেখার মানুষ চওড়া পর্দাতেও এক কলামের, বড় লেখার উপযোগী লেআউট পান। px breakpoint থাকলে তিনি তিন কলামের ঠাসা লেআউটে বিশাল অক্ষর পেতেন — লাইনে দুই-তিনটি শব্দ, বারবার ভাঙা। একসময় কিছু ব্রাউজারে px আর em query zoom-এর সাথে ভিন্ন আচরণ করত বলে em-এর পক্ষে আরও যুক্তি ছিল; আধুনিক ব্রাউজারে zoom-এ দুটোই ঠিকঠাক কাজ করে, কিন্তু ফন্ট-সেটিংসের পার্থক্যটি এখনো আছে।
বাস্তব পরামর্শ: breakpoint বের করুন content দেখে (অংশ ৭), লিখুন em-এ, সংখ্যা রাখুন কম — আর যতটা সম্ভব intrinsic কৌশলে ছেড়ে দিন।
মূল উপলব্ধি: যে সংখ্যা বাইরের কোনো পণ্য থেকে ধার করা, তা সেই পণ্যের সাথেই পুরোনো হয়। যে সংখ্যা আপনার content আর পাঠকের পছন্দ থেকে আসে, তা টেকে।
প্র ০৫@media (hover: none) মিললে কি ধরে নেওয়া যায় এটা ফোন? touch আর মাউসের পার্থক্য CSS কতটা জানতে পারে?
না — আর এই ভুল অনুমান থেকে বহু বাগ জন্মায়। CSS ডিভাইসের নাম জানে না; জানে কয়েকটি ক্ষমতা। Media Queries Level 4-এ চারটি interaction feature আছে:
hoverআরpointer— শুধু মূল ইনপুট নিয়ে: hover সহজে করা যায় কি না, আর পয়েন্টার সূক্ষ্ম (মাউস,fine) নাকি মোটা (আঙুল,coarse).any-hoverআরany-pointer— যুক্ত যেকোনো ইনপুট নিয়ে।
এবার বাস্তব ডিভাইস ভাবুন। touch-পর্দার ল্যাপটপ: মূল ইনপুট সাধারণত trackpad, তাই hover: hover — অথচ মানুষটি হয়তো আঙুলেই চাপছেন। ট্যাবলেটে মাউস বা কীবোর্ড-কভার লাগানো: মূল ইনপুট touch, কিন্তু মাউসও আছে। স্টাইলাস কিছু ডিভাইসে পর্দার ওপরে ভেসে থেকে hover দেয়। স্মার্ট টিভির রিমোটে পয়েন্টারই নেই, আছে শুধু দিক-বোতাম। আর ফোনে ব্লুটুথ মাউস লাগানোও সম্ভব। কোনো একক শর্ত এই সবকিছুকে “ফোন” আর “কম্পিউটার”-এ ভাগ করতে পারে না।
তাই নিরাপদ নীতি হলো ক্ষমতা ধরে নকশা: সব ইনপুটে কাজ করে এমন ভিত্তি (চাপলে খোলে এমন মেনু, যথেষ্ট বড় target, কীবোর্ডে :focus-visible), তারপর (hover: hover) and (pointer: fine) মিললে বাড়তি hover-সাজ। WCAG 2.1-এর 1.4.13 নিয়মও বলে, hover বা focus-এ যা দেখা যায়, তা বন্ধ করা, তার ওপর পয়েন্টার নেওয়া আর পড়ার মতো সময় পর্যন্ত টিকিয়ে রাখা যেতে হবে।
মূল উপলব্ধি: ডিভাইস চেনার চেষ্টা নয়, ক্ষমতা অনুযায়ী উন্নতি — progressive enhancement. ব্যবহারকারী কী দিয়ে চালাচ্ছেন, তা আপনি কখনো নিশ্চিত জানবেন না; এমনভাবে বানান যাতে জানার দরকারই না পড়ে।
অনুশীলন
বেশিরভাগ কাজ দেখা আর যাচাইয়ের — DevTools খোলা রাখুন।
-
৩২০px শিকার: আপনার পছন্দের যেকোনো একটি সংবাদ বা দোকানের সাইট কম্পিউটারে খুলুন। DevTools-এর device toolbar-এ “Responsive” বেছে চওড়া 320px করুন। পাতা কি পাশে নড়ে? নড়লে কোন element দায়ী, খুঁজে বের করুন।
Elements প্যানেলে
htmlবাbodyনির্বাচন করে Styles-এ একটি অস্থায়ী নিয়ম যোগ করুন:* { outline: 1px solid red; }. যে লাল দাগ ডান কিনারা পেরিয়ে গেছে, সেটিই অপরাধী। সাধারণত পাওয়া যায়: নির্দিষ্টwidth-এর বিজ্ঞাপন বা ব্যানার,max-widthছাড়া ছবি বা iframe, না ভাঙা লম্বা লিংক, বা টেবিল যার wrapper-এoverflow-x: autoনেই। খেয়াল করুন, সমাধান সবসময় সেই element-এ — পুরো পাতায়overflow-x: hiddenনয়। -
viewport ছাড়া একদিন: নিজের বানানো যেকোনো একটি পাতা (যেমন পর্ব ১৫-এর সাইট) থেকে viewport meta লাইনটি মুছে ফেলুন, তারপর আসল ফোনে খুলুন। কী দেখলেন, আর কেন — layout viewport দিয়ে ব্যাখ্যা করুন।
পুরো পাতা খুদে আকারে দেখাবে, যেন ডেস্কটপের পাতা দূর থেকে দেখছেন; লেখা পড়তে চিমটি দিয়ে বড় করতে হবে। কারণ viewport meta না থাকায় ফোন layout viewport প্রায় 980px ধরেছে, সেই মাপে লেআউট করে পুরোটা ছোট করে পর্দায় বসিয়েছে। আপনার CSS-এ media query থাকলে সেগুলোও 980px দেখে বড় পর্দার নিয়ম খাটিয়েছে। (DevTools-এর device toolbar-ও সাধারণত এই আচরণ নকল করে, তাই সেখানেও দেখা যায়।) পরীক্ষা শেষে লাইনটি অবশ্যই ফিরিয়ে দিন।
-
উল্টে লিখুন: নিচের desktop-first CSS-টিকে মোবাইল-ফার্স্টে রূপান্তর করুন — একই ফল, কিন্তু শুধু
min-widthquery দিয়ে:.list { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2rem; } .side { display: block; width: 18rem; } @media (max-width: 47.99em) { .list { grid-template-columns: 1fr; gap: 1rem; } .side { width: auto; } }ভিত্তিতে ছোট পর্দার নিয়ম রাখুন, query-তে শুধু যা বড় পর্দায় যোগ বা বদলায়:
.list { display: grid; gap: 1rem; } /* এক কলাম: grid-এর ডিফল্ট */ @media (min-width: 48em) { .list { grid-template-columns: repeat(3, 1fr); gap: 2rem; } .side { width: 18rem; } }খেয়াল করুন:
grid-template-columns: 1frবাwidth: autoলেখার দরকারই পড়ল না, কারণ সেগুলো এমনিতেই ডিফল্ট।.side-এরdisplay: block-ও বাদ, যদি element-টি আগেই block হয়। আটটি ঘোষণা কমে পাঁচটিতে নামল, আর47.99em-এর মতো ভগ্নাংশের কৌশলও আর লাগল না। -
Touch target মাপুন: যেকোনো একটি সাইটের মোবাইল রূপে (device toolbar-এ) নিচের মেনু বা footer-এর লিংকগুলোর ওপর DevTools-এর inspect পয়েন্টার রাখুন — প্রতিটির চওড়া × উচ্চতা দেখায়। কোনগুলো 24×24-এর কম? কীভাবে ঠিক করবেন?
প্রায়ই footer-এর ছোট লিংক, সোশ্যাল আইকন বা “×” বন্ধ-বোতাম 24px-এর কম পাওয়া যায় — যেমন শুধু 16px-এর আইকন, চারপাশে কোনো padding নেই। ঠিক করার উপায়: আইকনের আকার না বাড়িয়েই চাপার জায়গা বাড়ান —
a-তেdisplay: inline-flex; align-items: center; justify-content: center; min-inline-size: 44px; min-block-size: 44px;, আর লিংকগুলোর মাঝেgap. বাক্যের ভেতরের সাধারণ লিংক WCAG 2.5.8-এর ব্যতিক্রম, কিন্তু মেনু আর বোতাম নয়।
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমএকটি নতুন রেসপন্সিভ পাতা বানানোর ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- 📝 head-এ viewport meta সহ semantic HTML লেখা
- 📱 query-র বাইরে ছোট পর্দার ভিত্তি CSS — fluid মাপ, নমনীয় ছবি
- 🧩 কম্পোনেন্টে intrinsic কৌশল — flex-wrap, auto-fit
- ↔️ ধীরে চওড়া করে যেখানে content ভাঙে, সেখানে min-width breakpoint
- 🔍 320px, zoom, আসল ফোন আর ধীর নেটওয়ার্কে পরীক্ষা
একটি পাতার head-এ viewport meta tag নেই। একটি মোবাইল ব্রাউজার সাধারণত কী করবে?
- পাতাকে ঠিক ফোনের চওড়ার সমান ধরে সাজাবে
- পাতাকে প্রায় 980px চওড়া ধরে সাজিয়ে ছোট করে দেখাবে
- পাতা খুলবেই না, error দেখাবে
- সব CSS উপেক্ষা করে সাদামাটা লেখা দেখাবে
মোবাইল-ফার্স্ট পদ্ধতিতে বড় পর্দার জন্য নিয়ম যোগ করতে সাধারণত কোন ধরনের media query লেখা হয়?
@media (max-width: 48em)@media print@media (min-width: 48em)@media (orientation: portrait)
1280px চওড়া একটি ছবি সরু পাত্রে যেন বাইরে না বেরোয় এবং অনুপাত ঠিক থাকে — কোন CSS সবচেয়ে উপযুক্ত?
img { max-width: 100%; height: auto; }img { width: 100%; height: 300px; }img { overflow: hidden; }img { width: 360px; }
WCAG 2.2-এর 2.5.8 Target Size (Minimum) অনুযায়ী (ব্যতিক্রম ছাড়া) চাপার জায়গার সর্বনিম্ন মাপ কত?
- 44×44 CSS px
- 48×48 CSS px
- 16×16 CSS px
- 24×24 CSS px
রেসপন্সিভ পাতায় breakpoint বাছাইয়ের সবচেয়ে ভালো পদ্ধতি কোনটি?
- জনপ্রিয় ফোন আর ট্যাবলেটের পর্দার মাপ ধরে
- পাতা ধীরে ধীরে চওড়া করে যেখানে content ভাঙে, সেখানে
- প্রতি 100px অন্তর একটি করে
- কোনো জনপ্রিয় CSS framework-এর সংখ্যা হুবহু নিয়ে
WCAG 1.4.10 Reflow নিয়ম অনুযায়ী সাধারণ লেখার পাতা কোন চওড়ায় দুই দিকে স্ক্রল ছাড়া ব্যবহারযোগ্য হতে হবে?
- 768 CSS px
- 480 CSS px
- 320 CSS px
- 200 CSS px
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- রেসপন্সিভ ডিজাইন = একটি HTML, আর এমন CSS যা নিয়ম দেয়, মাপ মুখস্থ করে না; m. সাইটের দুই কপির ঝামেলা নেই।
- head-এ সবসময়
<meta name="viewport" content="width=device-width, initial-scale=1">— না থাকলে ফোন প্রায় 980px ধরে, media query-ও ভুল মাপ দেখে; প্রিভিউর iframe নিজের চওড়াকেই viewport ধরে। - Marcotte-এর তিন উপাদান: fluid layout (
%,max-width,fr), নমনীয় ছবি (max-width: 100%; height: auto+ width/height attribute), media query. - মোবাইল-ফার্স্ট: ভিত্তি ছোট পর্দার,
min-widthquery ছোট থেকে বড় ক্রমে; breakpoint content দেখে, em-এ; আগে intrinsic কৌশল। - target অন্তত 24×24, ভালো 44–48px; hover-এ জরুরি কিছু নয়; পরীক্ষা: device toolbar, আসল ফোন, ধীর নেটওয়ার্ক, 320px / ৪০০% zoom.
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ৩১ · Media query আর container queryপরবর্তী পর্বশর্ত লেখার পুরো ব্যাকরণ আর কম্পোনেন্ট-ভিত্তিক রেসপন্সিভ।
- পর্ব ২৯ · প্রচলিত লেআউট প্যাটার্ন — sidebar, holy grail, dashboard আর galleryঝালিয়ে নিনmedia query ছাড়া মানিয়ে নেওয়া প্যাটার্ন।
- পর্ব ১৩ · head, meta, SEO আর সোশ্যাল শেয়ারিং (Open Graph)ঝালিয়ে নিনviewport meta-র প্রতিটি অংশ আর zoom বন্ধ করার বিপদ।
- HTML ও CSS · কোর্স হোম৫৯টি পর্বপুরো কোর্সের রোডম্যাপ — কোন পর্ব কখন।
- কম্পিউটার ফান্ডামেন্টালস · ইন্টারনেট কীভাবে চলেপাশের ট্র্যাকধীর নেটওয়ার্কে পাতা কেন দেরিতে আসে — ভেতরের গল্প।