সরাসরি পর্বে যান
পর্ব ২০ · ৫৯-এর মধ্যে · মডিউল ৩

একক আর রং — px, rem, %, vw এবং hex, rgb, hsl, oklch

CSS Units & Colors — px, em, rem, %, Viewport Units, calc(), hex, rgb(), hsl(), oklch(), color-mix() & Contrast

Taught in Bangla, this lesson covers CSS units and colors: absolute versus relative units, CSS pixels versus device pixels, em versus rem, what percentages refer to, viewport units and the mobile address bar problem, unitless line-height and calc(), and respecting user font size. It then explains named colors, hex, rgb(), hsl(), currentColor, opacity versus alpha, oklch(), color-mix(), display-p3 and readable contrast.

এই পর্বে যা শিখবেন

  • absolute আর relative একক, CSS পিক্সেল বনাম ডিভাইসের পিক্সেল, আর ব্রাউজার কীভাবে সব একককে px-এ হিসাব করে
  • em আর rem-এর পার্থক্য, % কোন property-তে কিসের শতাংশ, আর মোবাইলের viewport সমস্যার আধুনিক সমাধান
  • unitless line-height, calc(), আর কোন কাজে কোন একক — ব্যবহারকারীর লেখার মাপের পছন্দকে সম্মান করে
  • নাম, hex, rgb(), hsl(), currentColor, transparent, opacity বনাম alpha
  • oklch(), color-mix(), display-p3, আর পড়ার মতো কনট্রাস্ট কীভাবে মাপবেন — বাংলাদেশের পতাকা দিয়ে হাতে-কলমে

১ · মাপের একক কেন — absolute আর relative

দর্জির দোকানে গিয়ে যদি বলেন “হাতা লম্বা করে দিন”, দর্জি জিজ্ঞেস করবেন — কত? এক ইঞ্চি? দুই ইঞ্চি? সংখ্যা ছাড়া মাপ হয় না, আর একক ছাড়া সংখ্যার মানে হয় না। “হাতা ২ লম্বা করুন” — ২ কী? ইঞ্চি, সেন্টিমিটার, না আঙুল?

CSS-এও একই কথা। width: 300 লিখলে ব্রাউজার পুরো declaration-টি বাদ দেয়, কারণ সে জানে না ৩০০ কিসের। লিখতে হয় width: 300px বা width: 50%. শুধু 0-এর বেলায় একক লাগে না — শূন্য ইঞ্চি আর শূন্য সেন্টিমিটার একই জিনিস।

CSS-এর এককগুলো দুই পরিবারে ভাগ করা যায়:

📏 Absolute — স্থির মাপ

Absolute length নিজের মধ্যেই সম্পূর্ণ, অন্য কিছুর ওপর নির্ভর করে না। px, pt, cm, mm, in. CSS-এ এদের মধ্যে স্থির সম্পর্ক: 1in = 96px, 1pt = 1/72in.

বর্ডার, ছোট খুঁটিনাটি, প্রিন্ট

🔗 Relative — আপেক্ষিক মাপ

Relative length অন্য কোনো মাপের ভগ্নাংশ বা গুণিতক — লেখার মাপ (em, rem, ch), মূল বাক্স (%), বা দেখার জানালা (vw, vh).

লেখা, লেআউট, রেসপন্সিভ নকশা

বাড়ি বানানোর নকশার কথা ভাবুন। “জানালা ৪ ফুট চওড়া” — এটা absolute; বাড়ি যত বড়ই হোক, জানালা ৪ ফুট। আর “বারান্দা ঘরের অর্ধেক চওড়া” — এটা relative; ঘর বড় হলে বারান্দাও বড় হয়। ভালো স্থপতি দুটোই ব্যবহার করেন: দরজার কবজা স্থির মাপে, ঘরের ভাগ অনুপাতে। CSS-এও ঠিক তাই — প্রশ্নটা “কোন একক ভালো” নয়, “এই মাপটা কিসের সাথে বদলানো উচিত”।

বড় প্রশ্নটা হলো: আপনার পাতা খোলা হবে ৫ ইঞ্চির ফোনে, ১৪ ইঞ্চির ল্যাপটপে, অফিসের বড় মনিটরে, এমনকি প্রজেক্টরে। কেউ চোখের সমস্যার জন্য ব্রাউজারে লেখা বড় করে রাখেন। তাই বেশিরভাগ মাপ স্থির না রেখে ঠিক জিনিসের সাথে বাঁধা উচিত — লেখার মাপ ব্যবহারকারীর পছন্দের সাথে, কলামের চওড়া পর্দার সাথে। এই পর্বের প্রথম অর্ধেক সেই বাঁধনের গল্প।

২ · px — CSS-এর পিক্সেল আসলে স্ক্রিনের বিন্দু নয়

স্ক্রিন অসংখ্য ছোট আলোর বিন্দু দিয়ে তৈরি — এদের বলে ডিভাইস পিক্সেল। পুরোনো দিনে CSS-এর 1px মানে ছিল ঠিক একটি ডিভাইস পিক্সেল। তারপর এলো খুব ঘন পিক্সেলের ফোন। একই আকারের পর্দায় দুই-তিন গুণ বেশি বিন্দু। যদি 1px তখনও একটি বিন্দুই থাকত, তাহলে 16px লেখা নতুন ফোনে পিঁপড়ের মতো ছোট হয়ে যেত।

তাই আজ CSS pixel একটি “কল্পিত” মাপ। ব্রাউজার নিজে ঠিক করে একটি CSS পিক্সেলে কয়টি ডিভাইস পিক্সেল লাগবে। এই অনুপাতের নাম device pixel ratio — JavaScript-এ window.devicePixelRatio. সাধারণ ল্যাপটপে এটি প্রায়ই 1 বা 1.25, অনেক ফোনে 2 বা 3. অনুপাত 3 হলে একটি 1px রেখা আসলে ৩×৩ = ৯টি বিন্দু দিয়ে আঁকা হয় — তাই লেখা ধারালো দেখায়, আকারও ঠিক থাকে।

মূল ধারণা

আপনি CSS-এ যে মাপই লিখুন — em, %, vw — ব্রাউজার শেষ পর্যন্ত সবকিছুকে CSS পিক্সেলে হিসাব করে, তারপর device pixel ratio দিয়ে গুণ করে স্ক্রিনে আঁকে। ব্রাউজারের Zoom বাড়ালেও আসলে এই অনুপাতই বাড়ে। তাই px “স্থির” হলেও Zoom-এর সাথে বড় হয়।

নিচের ছোট স্ক্রিপ্টটি একটি বাক্সের চওড়া নানা এককে বসিয়ে ব্রাউজারকে জিজ্ঞেস করে — “শেষে কত px হলো?” getComputedStyle() ব্রাউজারের হিসাবের ফল ফেরত দেয়:

// বাক্সের font-size 20px, পাতার মূল font-size সাধারণত 16px
const card = document.querySelector('.card');
const tries = ['100px', '2em', '2rem', '10vw', '1in', '12pt'];

for (const v of tries) {
  card.style.width = v;
  console.log(v.padEnd(6), '->', getComputedStyle(card).width);
}
card.style.width = '';

console.log('root font-size:', getComputedStyle(document.documentElement).fontSize);
console.log('devicePixelRatio:', window.devicePixelRatio);

দেখবেন 2em -> 40px (বাক্সের নিজের font-size 20px-এর দ্বিগুণ), 2rem -> 32px (মূল 16px-এর দ্বিগুণ), 1in -> 96px, 12pt -> 16px. 10vw-এর সংখ্যা আপনার পর্দার চওড়ার ওপর নির্ভর করে, তাই একেকজনের একেক রকম। শেষ লাইনে আপনার ডিভাইসের device pixel ratio. চেষ্টা করুন: ব্রাউজারে Ctrl + + দিয়ে Zoom বাড়িয়ে আবার চালান — devicePixelRatio বেড়ে যাবে। তারপর তালিকায় '30ch' যোগ করে দেখুন।

আরও গভীরে: CSS spec-এ 1px-কে একটি “reference pixel” হিসেবে সংজ্ঞায়িত করা আছে — ৯৬ dpi-এর একটি পর্দার একটি পিক্সেল হাতের দূরত্ব থেকে (প্রায় ২৮ ইঞ্চি) চোখে যত বড় কোণ তৈরি করে, প্রায় ০.০২১৩ ডিগ্রি। তাই দূর থেকে দেখা প্রজেক্টরে 1px শারীরিকভাবে বড়, হাতে ধরা ফোনে ছোট — কিন্তু চোখে প্রায় সমান লাগে। আর একটি মান যে ধাপে ধাপে চূড়ান্ত হয়, spec তার নাম দিয়েছে: আপনি যা লেখেন তা specified value, উত্তরাধিকারের জন্য তৈরি রূপ computed value, লেআউটের পর আসল px — used value. পর্ব ১৮-এর inheritance এই computed value-টিই সন্তানদের হাতে তুলে দেয় — অংশ ৬-এ এর একটি বড় পরিণাম দেখবেন।

৩ · em আর rem — লেখার মাপের সাথে বাঁধা

লেখার মাপ নিয়ে একটি গুরুত্বপূর্ণ সত্য: ব্রাউজারের একটি ডিফল্ট font-size আছে, সাধারণত 16px. ব্যবহারকারী চাইলে ব্রাউজারের সেটিংসে এটি বদলাতে পারেন — চোখে কম দেখেন এমন অনেকেই 20px বা 24px করে রাখেন। লেখার মাপকে এই পছন্দের সাথে বাঁধার দুটি একক:

  • em — বর্তমান font-size-এর গুণিতক। font-size-এর ভেতরে লিখলে মানে মূল উপাদানের (parent) font-size; অন্য property-তে (যেমন padding: 1em) মানে element-এর নিজের font-size.
  • rem — “root em”: সবসময় root element <html>-এর font-size-এর গুণিতক। পাতার যেকোনো গভীরে লিখুন, মাপ একই।

শুনতে প্রায় এক রকম। কিন্তু একটি ফাঁদ আছে — em নেস্টেড হলে গুণ হতে থাকে। মেনুর ভেতরে মেনু, তালিকার ভেতরে তালিকা — প্রতিটি স্তর আগের স্তরের ফলকে আবার গুণ করে। ঠিক যেন চক্রবৃদ্ধি সুদ। নিচের স্টেপারে হিসাবটি দেখুন:

1html    { font-size: 16px; }2.em ul  { font-size: 1.2em; }3.rem ul { font-size: 1.2rem; }
font-size-এর হিসাব
কোথায়
em দিয়ে
rem দিয়ে
  1. শুরু — root. <html>-এর font-size 16px (ব্রাউজারের ডিফল্ট)। দুটি তালিকা আছে: একটির নিয়ম em-এ, অন্যটির rem-এ। দুটিতেই লেখা “1.2” — অর্থাৎ ২০% বড়।
  2. প্রথম স্তর. দুটোই 19.2px. em-এর হিসাব: মূলের (এখানে 16px) ১.২ গুণ। rem-এর হিসাব: root-এর ১.২ গুণ। প্রথম স্তরে মূল আর root একই, তাই ফল সমান।
  3. দ্বিতীয় স্তর — পার্থক্য শুরু. ভেতরের তালিকাটিও .em ul selector-এ মেলে। তার মূল এখন 19.2px, তাই em দেয় 19.2 × 1.2 = 23.04px. rem এখনো root দেখে — আবার 19.2px.
  4. তৃতীয় স্তর. em: 27.65px — শুরুর চেয়ে প্রায় ৭৩% বড়, অথচ আপনি লিখেছিলেন মাত্র “২০% বড়”! উল্টো দিকেও বিপদ: 0.8em হলে তৃতীয় স্তরে লেখা প্রায় 8px-এ নেমে পড়ার অযোগ্য হতো।
  5. ব্যবহারকারী লেখা বড় করলেন. কেউ ব্রাউজারে ডিফল্ট লেখা 20px করলেন। দুটি এককই এই পছন্দ মানে — em-এ 34.56px, rem-এ 24px. শিক্ষা: লেখার মাপ সাধারণত rem-এ; em রাখুন সেখানে, যেখানে আপনি সত্যিই চান মাপটা আশেপাশের লেখার সাথে বাড়ুক-কমুক — যেমন বাটনের padding.

এবার নিজের চোখে দেখুন। বাঁয়ে em, ডানে rem — একই সংখ্যা, একই কাঠামো:

.em ul  { font-size: 1.2em; }
.rem ul { font-size: 1.2rem; }

/* বাক্সের padding em-এ — লেখার সাথে বাক্সও বাড়ে */
.em, .rem {
  display: inline-block;
  vertical-align: top;
  width: 45%;
  padding: 0.5em;
  border: 1px solid #94a3b8;
}

বাঁয়ের তালিকায় প্রতিটি স্তর আগেরটির চেয়ে বড় — লেখা সিঁড়ির মতো উঠছে। ডানে প্রথম স্তরের পর সব সমান। চেষ্টা করুন: দুই জায়গাতেই 1.2-কে 0.8 করুন — বাঁয়ের তৃতীয় স্তর কতটা ছোট হলো দেখুন। তারপর একদম ওপরে html { font-size: 24px; } যোগ করুন — দুটোই বড় হবে, কারণ দুটোই শেষ পর্যন্ত root থেকে হিসাব শুরু করে।

একটি পুরোনো কৌশল এখনো অনেক টিউটোরিয়াল আর AI-এর উত্তরে দেখবেন: html { font-size: 62.5%; }, যাতে 1rem = 10px হয় আর হিসাব সহজ লাগে। এটি শতাংশে লেখা বলে ব্যবহারকারীর পছন্দ মানে — কিন্তু তখন পাতার সব লেখাকে আবার rem দিয়ে বড় করতে হয়, আর বাইরের কোনো component যদি ধরে নেয় 1rem = 16px, সেটি হঠাৎ ছোট হয়ে যায়। সবচেয়ে বিপজ্জনক হলো html { font-size: 16px; } — এটি ব্যবহারকারীর পছন্দ পুরোপুরি মুছে দেয়। নিরাপদ নিয়ম: root-এর font-size-এ হাত না দেওয়া, অথবা দিলে শুধু শতাংশে।

৪ · % — কিন্তু কিসের শতাংশ?

“৫০% ছাড়” শুনলে প্রথম প্রশ্ন — কিসের ৫০%? দামের, না লাভের? CSS-এর %-এও এই প্রশ্নটাই আসল, আর উত্তরটা property অনুযায়ী আলাদা। বেশিরভাগ ক্ষেত্রে শতাংশ হিসাব হয় containing block-এর মাপ থেকে — সাধারণত সেই বাক্স, যার ভেতরে element-টি আছে। কিন্তু ব্যতিক্রমগুলোই পরীক্ষায় আর বাস্তবে সবচেয়ে বেশি ঝামেলা করে:

Property% কিসেরমনে রাখার কথা
widthcontaining block-এর চওড়াসবচেয়ে স্বাভাবিক ব্যবহার
heightcontaining block-এর উচ্চতামূল বাক্সের উচ্চতা নির্দিষ্ট না থাকলে % কাজ করে না, auto-র মতো আচরণ করে
padding, margincontaining block-এর চওড়া — ওপর-নিচেরও!padding-top: 10% মানে চওড়ার ১০%, উচ্চতার নয়
font-sizeমূল উপাদানের font-size150% = 1.5em
line-heightelement-এর নিজের font-sizeঅংশ ৬-এ এর একটি ফাঁদ দেখবেন
top / leftcontaining block-এর উচ্চতা / চওড়াpositioned element-এ (পর্ব ২৪)
translateelement-এর নিজের বাক্সtranslate: 0 -50% = নিজের উচ্চতার অর্ধেক ওপরে

padding-এর নিয়মটি অদ্ভুত লাগে, কিন্তু এর পেছনে যুক্তি আছে। চওড়া সাধারণত আগে জানা যায়, উচ্চতা জানা যায় ভেতরের জিনিস সাজানোর পরে। ওপর-নিচের padding যদি উচ্চতা থেকে হিসাব হতো, তাহলে একটি চক্র তৈরি হতো — উচ্চতা জানতে padding লাগে, padding জানতে উচ্চতা। তাই spec চারদিকের padding-কেই চওড়ার সাথে বেঁধেছে।

নিচের এডিটরে ছয়টি বার, ছয়টি এককে। ড্যাশ দাগের বাক্সটির নিচে-ডান কোণ ধরে টেনে ছোট-বড় করুন — কোনটি বাক্সের সাথে বদলায়, কোনটি বদলায় না, খেয়াল করুন:

<style>
  .wrap { resize: horizontal; overflow: auto; width: 360px; max-width: 100%;
          border: 2px dashed #888; padding: 8px; font-size: 18px; }
  .bar  { background: #2563eb; color: white; margin: 6px 0;
          padding: 2px 6px; white-space: nowrap; box-sizing: border-box; }
  .a { width: 200px; }
  .b { width: 50%; }
  .c { width: 10em; }
  .d { width: 10rem; }
  .e { width: 30vw; }
  .f { width: 20ch; }
</style>
<div class="wrap">
  <div class="bar a">200px</div>
  <div class="bar b">50%</div>
  <div class="bar c">10em</div>
  <div class="bar d">10rem</div>
  <div class="bar e">30vw</div>
  <div class="bar f">20ch</div>
</div>

বাক্স টানলে শুধু 50% বারটি বদলায় — সে বাক্সের অর্ধেক। 10em (180px) বড়, কারণ বাক্সের font-size 18px; 10rem (160px) root-এর 16px থেকে আসে। 30vw বাক্সের সাথে বদলায় না — বদলায় পুরো ব্রাউজারের জানালা (এখানে প্রিভিউর চওড়া) ছোট-বড় করলে। চেষ্টা করুন: .wrap-এর font-size 18px থেকে 24px করুন — কোন দুটি বার বদলাল? (উত্তর: em আর ch, কারণ দুটোই element-এর লেখার মাপ থেকে আসে।) তারপর .b-তে padding-top: 10% যোগ করে বাক্স টানুন — বারটি লম্বাও হচ্ছে চওড়ার সাথে!

৫ · Viewport একক — vw, vh আর মোবাইলের address bar

Viewport হলো ব্রাউজারে পাতার যে অংশ দেখা যায় — জানালার কাচটুকু। viewport units সেই জানালার মাপের শতাংশ: 1vw = জানালার চওড়ার ১%, 1vh = উচ্চতার ১%. সাথে আছে vmin (চওড়া আর উচ্চতার মধ্যে ছোটটির ১%) আর vmax (বড়টির ১%). “পুরো পর্দা জুড়ে একটি স্বাগত-অংশ” বানাতে মানুষ বহু বছর লিখেছে height: 100vh.

ডেস্কটপে এটি ঠিকঠাক চলে। সমস্যা ফোনে। মোবাইল ব্রাউজারের ওপরে বা নিচে address bar থাকে, যা স্ক্রল করলে লুকিয়ে যায় আর ফিরে আসে। ফলে “জানালার উচ্চতা” একটি নয় — দুটি। বেশিরভাগ মোবাইল ব্রাউজার vh-কে ধরে বড় মাপটি, অর্থাৎ bar লুকানো অবস্থার। তাই পাতা খোলার মুহূর্তে, যখন bar দেখা যাচ্ছে, 100vh বাক্সের নিচের অংশ পর্দার বাইরে চলে যায়। আর ঠিক সেখানেই সাধারণত থাকে “এখনই কিনুন” বাটনটি!

এর সমাধানে CSS তিন জোড়া নতুন একক এনেছে — small, large আর dynamic viewport. উদাহরণের একটি ফোন ধরে দেখুন (সংখ্যাগুলো বোঝানোর জন্য — bar দেখা গেলে পাতার জায়গা ৬৪০px, লুকালে ৭০০px):

1.hero-a { height: 100vh;  }2.hero-b { height: 100svh; }3.hero-c { height: 100lvh; }4.hero-d { height: 100dvh; }
উদাহরণের ফোন
address bar
দেখা যাওয়া অংশ
100vh
100svh
100lvh
100dvh
  1. পাতা খুলল. address bar দেখা যাচ্ছে, পাতার জায়গা ৬৪০px. কিন্তু 100vh = ৭০০px (bar লুকানো অবস্থার মাপ)। ফলে স্বাগত-অংশের নিচের ৬০px পর্দার বাইরে। ব্যবহারকারী প্রথম দেখাতেই অর্ধেক কাটা বাটন দেখেন।
  2. নিচে স্ক্রল করলেন — bar লুকাল. এখন জায়গা ৭০০px; vh আর lvh (large) ঠিক মাপে। svh (small) সবসময় bar দেখা অবস্থার মাপ, তাই ৬৪০px-ই থাকে। dvh (dynamic) bar-এর সাথে বদলায় — এখন ৭০০px.
  3. আবার ওপরে — bar ফিরে এলো. dvh আবার ৬৪০px হলো। এতে বাক্সের উচ্চতা বদলায়, আর তার নিচের সবকিছু একটু লাফ দেয়। স্ক্রলের সময় বারবার লেআউট বদলানো চোখেও বিরক্তিকর, ফোনের প্রসেসরের জন্যও বাড়তি কাজ।
  4. সিদ্ধান্ত. svh কখনো bar-এর নিচে চাপা পড়ে না — স্বাগত-অংশের জন্য সাধারণত এটিই নিরাপদ। পুরো পর্দা সবসময় ভরাট রাখা জরুরি হলে (যেমন একটি পূর্ণ-পর্দার ম্যাপ) dvh. সমর্থন: এই এককগুলো ২০২২ সালের শেষ নাগাদ সব প্রধান ব্রাউজারে এসেছে, এখন Baseline Widely available. খুব পুরোনো ব্রাউজারের জন্য fallback: আগে height: 100vh;, পরের লাইনে height: 100svh; — যে ব্রাউজার নতুনটি বোঝে না, সে দ্বিতীয় লাইন বাদ দিয়ে প্রথমটি রাখে।

width: 100vw-এর একটি ডেস্কটপ-ফাঁদও আছে। Windows-এর মতো যেখানে scrollbar নিজে জায়গা নেয়, সেখানে 100vw scrollbar-এর চওড়াও ধরে — ফলে বাক্সটি পাতার চেয়ে কয়েক পিক্সেল চওড়া হয়ে নিচে একটি অকারণ পাশের স্ক্রল তৈরি করে। পূর্ণ চওড়ার জন্য সাধারণত width: 100%-ই ঠিক। আর শুধু vw দিয়ে লেখার মাপ (font-size: 4vw) দেবেন না — ব্রাউজারের Zoom বাড়ালে লেখা বড় হয় না, যা WCAG-এর “Resize text” নিয়ম ভাঙে।

লেখা দিয়ে মাপা — ch আর ex

ch হলো বর্তমান ফন্টে “0” অঙ্কটির চওড়া, আর ex হলো ছোট হাতের “x”-এর উচ্চতা। ch-এর সবচেয়ে কাজের ব্যবহার — অনুচ্ছেদের লাইন খুব লম্বা না হতে দেওয়া: max-width: 65ch মোটামুটি ৬০–৭০ অক্ষরের লাইন দেয়, যা পড়তে আরামদায়ক। বাংলা লেখায় অক্ষরের চওড়া ইংরেজি “0”-এর সমান নয়, তাই ch এখানে আনুমানিক মাপ — পর্ব ২১-এ বাংলা টাইপোগ্রাফিতে আরও দেখবেন।

এক ঝলক সামনে — container query units

viewport একক পুরো জানালা দেখে। কিন্তু একটি কার্ড কখনো চওড়া মূল অংশে বসে, কখনো সরু sidebar-এ। তখন জানালা নয়, কার্ডের পাত্রের মাপ জানা দরকার। এজন্য আছে container query units — cqw, cqh, cqi, cqb — যা কাছের container-এর মাপের শতাংশ। এগুলোও এখন Baseline Widely available; container বানানোর পুরো কৌশল পর্ব ৩১-এ।

৬ · একক ছাড়া line-height আর calc()

line-height ঠিক করে এক লাইন থেকে পরের লাইনের দূরত্ব। এটি চারভাবে লেখা যায়: 24px, 1.5em, 150%, অথবা শুধু 1.5 — কোনো একক ছাড়া। চেহারায় প্রথম তিনটি প্রায়ই একই রকম লাগে, কিন্তু সন্তানেরা কী পায় সেখানেই বড় পার্থক্য।

অংশ ২-এর “আরও গভীরে”-তে বলেছিলাম — inheritance-এ সন্তানেরা পায় computed value. 1.5em বা 150% লিখলে computed value একটি স্থির px (16 × 1.5 = 24px), আর সেই 24px-ই সব সন্তানের কাছে যায় — তাদের লেখা যত বড়ই হোক। কিন্তু একক ছাড়া 1.5 লিখলে সন্তানেরা পায় শুধু গুণকটি, আর প্রত্যেকে নিজের font-size দিয়ে নতুন করে গুণ করে।

.a { line-height: 1.5em; } /* সন্তানেরা পায় 24px */
.b { line-height: 1.5; }   /* সন্তানেরা পায় গুণক 1.5 */

.big { font-size: 36px; margin: 4px 0; }

.a, .b {
  width: calc(100% - 2rem);
  padding: 0 1rem;
  border: 1px solid #94a3b8;
  margin-bottom: 8px;
}

ওপরের বাক্সে 36px শিরোনামের লাইনগুলোর উচ্চতা মাত্র 24px — বাংলার কার, ফলা আর মাত্রা একে অপরের গায়ে উঠে গেছে। নিচের বাক্সে শিরোনাম পেয়েছে 36 × 1.5 = 54px, তাই পরিষ্কার। চেষ্টা করুন: .a-তে 1.5em-এর বদলে 150% লিখুন — একই ভুল থাকবে। তারপর .b-তে 1.5-কে 1.8 করুন; বাংলা লেখায় ১.৬–১.৮ সাধারণত বেশি আরামদায়ক (পর্ব ১৪)। আর খেয়াল করুন width: calc(100% - 2rem) — নিচে এর ব্যাখ্যা।

calc() — আলাদা একক মিলিয়ে হিসাব

কখনো মাপটা দুই রকম এককের মিশ্রণ: “পুরো চওড়া থেকে দুই পাশে ১rem করে বাদ” বা “sidebar-এর ২৫০px বাদ দিয়ে বাকিটা”। calc() ঠিক এই কাজ করে — calc(100% - 250px). ব্রাউজার লেআউটের সময় % আর px দুটোকেই px-এ বদলে হিসাব শেষ করে, তাই পর্দা বদলালেও ফল ঠিক থাকে। তিনটি নিয়ম মনে রাখুন:

  • + আর --এর দুই পাশে ফাঁকা জায়গা বাধ্যতামূলক। calc(100%-2rem) অবৈধ, কারণ -2rem-কে ব্রাউজার একটি ঋণাত্মক সংখ্যা ভাবে।
  • * আর /-এ অন্তত একদিকে শুধু সংখ্যা থাকতে হয়: calc(2rem * 3) ঠিক, calc(2rem * 3rem) নয়।
  • calc()-এর ভেতরে calc() বা CSS variable (পর্ব ৩৩) রাখা যায়।

calc()-এর তিন ভাইও আছে: min() (কয়েকটির মধ্যে ছোটটি), max() (বড়টি) আর clamp(সর্বনিম্ন, পছন্দের, সর্বোচ্চ). যেমন width: min(100%, 40rem) মানে “৪০rem-এর বেশি চওড়া নয়, কিন্তু ছোট পর্দায় পুরো চওড়া”। সবগুলো অনেক বছর ধরে সব আধুনিক ব্রাউজারে আছে; clamp() দিয়ে পর্দার সাথে মসৃণভাবে বাড়া লেখা পর্ব ৩৫-এ বানাব।

৭ · কোন কাজে কোন একক — আর ব্যবহারকারীর পছন্দকে সম্মান

সব একক জানার পর আসল দক্ষতা হলো বেছে নেওয়া। নিচের টেবিলটি কোনো কঠিন আইন নয়, অভিজ্ঞ ডেভেলপারদের সাধারণ অভ্যাস — প্রতিটির পেছনে প্রশ্ন একটাই: “এই মাপটা কিসের সাথে বদলানো উচিত?”

কাজসাধারণ পছন্দকেন
লেখার মাপ (font-size)remব্যবহারকারীর ডিফল্ট লেখার মাপ মানে, নেস্টিং-এ জমে না
বাটন বা ট্যাগের paddingemবাটনের লেখা বড় হলে বাক্সও সমান হারে বড় হয়
বর্ডার, ছোট রেখা, ছায়াpx১px-এর দাগ লেখার সাথে মোটা হওয়ার দরকার নেই
line-heightএকক ছাড়া (1.5–1.8)প্রতিটি সন্তান নিজের লেখার মাপে হিসাব করে
কলাম আর বাক্সের চওড়া%, Grid-এর fr (পর্ব ২৭), max-widthপাত্রের সাথে বদলায়
পড়ার কলামের সর্বোচ্চ চওড়াmax-width: 65ch বা 40remলাইন খুব লম্বা হলে চোখ পরের লাইন হারায়
পূর্ণ-পর্দার অংশের উচ্চতাmin-height: 100svhমোবাইলের bar-এ ঢাকা পড়ে না; min- হলে বেশি লেখায় বাক্স বাড়তে পারে
Media query-র সীমা (পর্ব ৩১)em বা remলেখা বড় করা ব্যবহারকারীর জন্যও লেআউট ঠিক সময়ে বদলায়
প্রিন্টের পাতাcm, mm, ptকাগজে এগুলোর শারীরিক অর্থ আছে

দুটি আলাদা জিনিস — Zoom আর “লেখার মাপ” সেটিং

ব্যবহারকারীর হাতে লেখা বড় করার দুটি উপায়। Zoom (Ctrl + +) পুরো পাতাকে বড় করে — px, rem, ছবি, সব। আর ব্রাউজারের সেটিংসে ডিফল্ট font size বদলালে বদলায় শুধু root-এর লেখার মাপ। আপনি যদি সব লেখা px-এ দেন, দ্বিতীয় উপায়টি আপনার পাতায় কাজই করে না — অথচ বয়স্ক মানুষ আর কম দেখেন এমন অনেকে ঠিক এটাই ব্যবহার করেন, কারণ এতে প্রতিটি সাইট আলাদা করে zoom করতে হয় না।

মূল ধারণা

WCAG 2.2-এর নিয়ম ১.৪.৪ (Resize text) বলে, লেখা ২০০% পর্যন্ত বড় করলেও কোনো লেখা বা কাজ হারানো চলবে না। rem-এ লেখা, একক ছাড়া line-height আর স্থির উচ্চতার বদলে min-height — এই তিন অভ্যাসেই বেশিরভাগ পাতা এই পরীক্ষায় পাস করে। পুরো অ্যাক্সেসিবিলিটি-চেকলিস্ট পর্ব ৪৫-এ।

নিজে পরীক্ষা করে দেখার সহজ উপায়: Chrome-এর Settings → Appearance → Font size থেকে (Edge-এ Appearance-এর Fonts অংশে) “Very large” বেছে নিন, তারপর কয়েকটি পরিচিত সাইট খুলুন। যেগুলোর লেখা বড় হলো না, সেগুলো px-এ লেখা। পরীক্ষা শেষে সেটিং আবার আগের মতো করে দেবেন।

৮ · রং লেখার ভাষা — নাম, hex, rgb(), hsl()

স্ক্রিনের প্রতিটি পিক্সেল আসলে তিনটি ছোট বাতি — লাল (Red), সবুজ (Green), নীল (Blue). প্রতিটির উজ্জ্বলতা ০ থেকে ২৫৫. তিনটিই পুরো জ্বললে সাদা, সব নিভলে কালো, লাল আর সবুজ মিলে হলুদ। স্ক্রিনের সাধারণ রঙের এই জগতের নাম sRGB. CSS-এ একই রং কয়েকটি “ভাষায়” লেখা যায়:

  • নাম: named color — red, tomato, seagreen… প্রায় ১৫০টি তৈরি নাম। দ্রুত পরীক্ষার জন্য ভালো, কিন্তু ব্র্যান্ডের নির্দিষ্ট রং নামে পাওয়া যায় না।
  • Hex: #RRGGBB — তিন জোড়া ষোলো-ভিত্তিক (hexadecimal) অঙ্ক। ছোট রূপ #RGB (প্রতিটি অঙ্ক দুবার: #0a8 = #00aa88), আর স্বচ্ছতাসহ #RRGGBBAA.
  • rgb(): rgb(244 42 65) — একই তিন সংখ্যা দশমিকে। আধুনিক লেখায় কমা নেই, স্বচ্ছতা দেওয়া হয় /-এর পরে: rgb(244 42 65 / 50%). পুরোনো rgba(244, 42, 65, 0.5) এখনো চলে, তবে আলাদা rgba() আর দরকার নেই।
  • hsl(): hsl(353 90% 56%) — রঙের চাকায় কোণ (hue), রঙের তীব্রতা (saturation) আর আলো (lightness). নিচে বিস্তারিত।

Hex দেখে ভয় পাওয়ার কিছু নেই — এটি শুধু অন্য ভিত্তিতে লেখা সংখ্যা। বাংলাদেশের পতাকার লাল #F42A41-কে ভেঙে দেখি (ষোলো-ভিত্তিক সংখ্যা নিয়ে বিস্তারিত জানতে ICT কোর্সের সংখ্যা পদ্ধতির পর্ব দেখুন):

# F4 2A 41 = rgb(244 42 65)
  1. # চিহ্ন. ব্রাউজারকে জানায়, এরপরের অক্ষরগুলো ষোলো-ভিত্তিক সংখ্যা। এই পদ্ধতিতে অঙ্ক ষোলোটি: 0–9, তারপর A (১০), B (১১), C (১২), D (১৩), E (১৪), F (১৫)। বড় বা ছোট হাতের অক্ষর — দুটোই চলে।
  2. প্রথম জোড়া — লাল বাতি. F4: প্রথম অঙ্ক F (১৫) ষোলোর ঘরে, দ্বিতীয় অঙ্ক ৪ এককের ঘরে। ১৫ × ১৬ + ৪ = ২৪৪ — ২৫৫-এর মধ্যে প্রায় পুরো।
  3. দ্বিতীয় জোড়া — সবুজ বাতি. 2A: ২ × ১৬ + ১০ = ৪২ — খুব কম।
  4. তৃতীয় জোড়া — নীল বাতি. 41: ৪ × ১৬ + ১ = ৬৫ — এটিও কম। দুই অঙ্কে সর্বোচ্চ FF = ২৫৫, তাই প্রতিটি বাতির ২৫৬টি ধাপ।
  5. ফল. #F42A41 আর rgb(244 42 65) হুবহু একই রং — শুধু লেখার ভাষা আলাদা। তিন বাতির ২৫৬ × ২৫৬ × ২৫৬ = প্রায় ১ কোটি ৬৮ লাখ রং লেখা যায়। চতুর্থ একটি জোড়া যোগ করলে (#F42A4180) সেটি হয় স্বচ্ছতা — 80 = ১২৮, প্রায় অর্ধেক।

hsl() — মানুষের মতো করে রং ভাবা

RGB হলো মেশিনের ভাষা — তিন বাতির মাত্রা। কিন্তু মানুষ রং এভাবে ভাবে না। আমরা বলি “এই সবুজটা আরেকটু হালকা করো” বা “এটা একটু ফ্যাকাশে লাগছে”। hex-এ “আরেকটু হালকা” করতে তিনটি সংখ্যাই বদলাতে হয়, আর কোনটা কতটা — আন্দাজ করা কঠিন। HSL এই তিনটি মানুষের প্রশ্নকে আলাদা করে:

  • Hue (০–৩৬০): রঙের চাকায় কোন দিকে — ০ লাল, ১২০ সবুজ, ২৪০ নীল, আবার ৩৬০-এ লাল।
  • Saturation (০%–১০০%): রং কতটা তীব্র — ০% মানে ধূসর।
  • Lightness (০%–১০০%): কতটা আলো — ০% কালো, ১০০% সাদা, ৫০% খাঁটি রং।
.wheel {
  width: 140px; height: 140px; border-radius: 50%;
  background: conic-gradient(
    hsl(0 100% 50%), hsl(60 100% 50%), hsl(120 100% 50%),
    hsl(180 100% 50%), hsl(240 100% 50%), hsl(300 100% 50%),
    hsl(360 100% 50%));
}
span { display: inline-block; width: 56px; height: 40px; margin-right: 4px; }

.s1 { background: hsl(160 100% 20%); }
.s2 { background: hsl(160 100% 35%); }
.s3 { background: hsl(160 100% 55%); }
.s4 { background: hsl(160 100% 80%); }

ওপরে পুরো রঙের চাকা — ঘড়ির কাঁটার দিকে hue ০ থেকে ৩৬০ (চাকা আঁকার conic-gradient শিখবেন পর্ব ২২-এ)। নিচে একই সবুজ পরিবারের চারটি রং, গাঢ় থেকে হালকা — প্রথমটি প্রায় পতাকার সবুজ #006A4E-এর কাছাকাছি (যা আসলে hsl(164 100% 21%)). চেষ্টা করুন: চারটি 160-কে 220 করুন — পুরো পরিবার নীল হয়ে যাবে, এক জায়গায় বদলে। তারপর 100% saturation-কে 30% করুন — রংগুলো ফ্যাকাশে, “ধূসর-মেশানো” হবে।

currentColor, transparent আর opacity বনাম alpha

দুটি বিশেষ শব্দ খুব কাজের। currentColor মানে “এই element-এর লেখার রং যা, সেটাই” — বর্ডার বা আইকনের রং লেখার সাথে মিলিয়ে রাখতে চমৎকার; লেখার রং বদলালে সব একসাথে বদলায়। transparent মানে পুরো স্বচ্ছ — আসলে rgb(0 0 0 / 0).

আর স্বচ্ছতা দেওয়ার দুটি উপায় প্রায়ই গুলিয়ে যায়। রঙের ভেতরে alpha (rgb(0 106 78 / 50%)) শুধু সেই রংটিকে স্বচ্ছ করে। আর opacity: 0.5 পুরো element-কে — লেখা, বর্ডার, ভেতরের ছবি, সন্তান, সব কিছু — একসাথে আধা-স্বচ্ছ করে:

.stage {
  padding: 10px;
  background: repeating-linear-gradient(45deg, #fde68a 0 12px, #fff 12px 24px);
}
.card { padding: 10px; margin: 8px 0; font-weight: bold; }

.op { background: #006A4E; color: white; opacity: 0.5; }
.al { background: rgb(0 106 78 / 50%); color: white; }
.cc { color: #b91c1c; border: 3px solid currentColor;
      background: transparent; }

ডোরাকাটা পেছনের ওপর তিনটি কার্ড। প্রথমটিতে সবুজ পেছন আর সাদা লেখা দুটোই ফিকে — লেখা পড়তে কষ্ট। দ্বিতীয়টিতে শুধু সবুজ পেছনটা স্বচ্ছ, লেখা পুরো সাদা। তৃতীয়টির বর্ডার নিজে থেকেই লেখার লাল রং নিয়েছে। চেষ্টা করুন: .cc-এর color বদলে #2563eb করুন — বর্ডারও নীল হবে, আলাদা করে লিখতে হলো না। সতর্কতা: “disabled” বাটন বোঝাতে অনেকে opacity কমিয়ে দেন, এতে লেখার কনট্রাস্টও কমে যায় — অংশ ৯ দেখুন। আরও গভীরে: opacity 1-এর কম হলে element একটি নতুন stacking context তৈরি করে, যার প্রভাব পর্ব ২৪-এ দেখবেন।

CSS-এর রঙের নামগুলোর বেশিরভাগ এসেছে ১৯৮০-র দশকের Unix-এর X Window System থেকে — তাই gray আর darkgray-এর মধ্যে darkgray আসলে বেশি হালকা, এমন অদ্ভুত ব্যাপারও আছে। ১৯৯০-এর দশকে অনেক কম্পিউটার মাত্র ২৫৬টি রং দেখাতে পারত, তাই ডিজাইনাররা ২১৬টি “web-safe” রঙের মধ্যে থাকতেন। আর ২০১৪ সালে যোগ হয় rebeccapurple (#663399) — CSS-এর অন্যতম পথিকৃৎ Eric Meyer-এর মেয়ে Rebecca-র স্মরণে — ছোট্ট Rebecca ছয় বছর বয়সে মারা যায়। রঙের নামের তালিকায় এটি একটি মানুষের স্মৃতি বহন করে।

বাংলাদেশের পতাকা — একক আর রং একসাথে

পতাকার মাপের নিয়মে এই পর্বের অনেক কিছু একসাথে আছে: দৈর্ঘ্য-প্রস্থের অনুপাত ১০:৬, লাল বৃত্তের ব্যাসার্ধ দৈর্ঘ্যের পাঁচ ভাগের এক ভাগ, আর বৃত্তের কেন্দ্র বাঁ দিক থেকে দৈর্ঘ্যের ৯/২০ অংশে (৪৫%), উচ্চতার ঠিক মাঝখানে। সরকারি নির্দেশে রং বলা আছে রঞ্জকের নামে; স্ক্রিনে সাধারণত ব্যবহৃত মান সবুজ #006A4E আর লাল #F42A41 — এগুলো আনুমানিক রূপান্তর।

<style>
  .flag {
    position: relative;
    width: 300px;
    aspect-ratio: 10 / 6;
    background: #006A4E;
  }
  .sun {
    position: absolute;
    width: 40%;              /* ব্যাস = দৈর্ঘ্যের ২/৫ */
    aspect-ratio: 1;
    border-radius: 50%;
    background: rgb(244 42 65);
    left: calc(45% - 20%);   /* কেন্দ্র ৪৫%-এ, তাই বাঁ প্রান্ত ২৫%-এ */
    top: 50%;                /* পতাকার উচ্চতার অর্ধেক */
    translate: 0 -50%;       /* নিজের উচ্চতার অর্ধেক ওপরে */
  }
</style>
<div class="flag" role="img" aria-label="বাংলাদেশের জাতীয় পতাকা">
  <div class="sun"></div>
</div>

সবুজ আয়তক্ষেত্রে বাঁ দিকে একটু সরানো লাল বৃত্ত। খেয়াল করুন, একই 50% দুই জায়গায় দুই জিনিস: top: 50% পতাকার উচ্চতার অর্ধেক, আর translate-এর -50% বৃত্তের নিজের উচ্চতার অর্ধেক — অংশ ৪-এর টেবিল মনে আছে? (position নিয়ে পুরো আলোচনা পর্ব ২৪-এ।) চেষ্টা করুন: width: 300px-কে 20rem বা 80% করুন — সব অনুপাত ঠিক থাকে, কারণ বৃত্তের মাপ শতাংশে। তারপর লালটিকে hsl(353 90% 56%) বা oklch(62.6% 0.231 22.3) লিখে দেখুন — চোখে কোনো পার্থক্য পাবেন না, একই রং তিন ভাষায়।

৯ · আধুনিক রং — oklch(), color-mix() আর পড়ার মতো কনট্রাস্ট

HSL মানুষের মতো ভাবতে সাহায্য করে, কিন্তু এর একটি লুকানো দুর্বলতা আছে: এর “lightness” আসলে মানুষের চোখের অনুভূতি মাপে না। hsl(60 100% 50%) (হলুদ) আর hsl(240 100% 50%) (নীল) — দুটোরই lightness ৫০%, অথচ চোখে হলুদ প্রায় সাদার মতো উজ্জ্বল, আর নীল বেশ গাঢ়। ফলে HSL-এ “সব রঙের ৫০% সংস্করণ” বানালে একটি সমান-উজ্জ্বল প্যালেট পাওয়া যায় না — কোনো বাটনের লেখা পড়া যায়, কোনোটার যায় না।

এর সমাধান oklch() — একটি আধুনিক color space, যার নকশাই হয়েছে perceptual uniformity মাথায় রেখে: সংখ্যায় সমান পরিবর্তন মানে চোখেও প্রায় সমান পরিবর্তন। তিনটি সংখ্যা: L (lightness, ০%–১০০%, চোখে অনুভূত আলো), C (chroma, রঙের তীব্রতা — ০ থেকে সাধারণত ০.৩৭-এর মধ্যে) আর H (hue, ০–৩৬০)। এর আয়তাকার রূপ oklab(). নিচে দুই সারি তুলনা করুন:

.row span { display: inline-block; width: 48px; height: 40px;
            margin-right: 4px; text-align: center; line-height: 40px; }
.hsl span:nth-child(1) { background: hsl(0 100% 50%); }
.hsl span:nth-child(2) { background: hsl(60 100% 50%); }
.hsl span:nth-child(3) { background: hsl(120 100% 50%); }
.hsl span:nth-child(4) { background: hsl(180 100% 50%); }
.hsl span:nth-child(5) { background: hsl(240 100% 50%); }
.hsl span:nth-child(6) { background: hsl(300 100% 50%); }
.ok span:nth-child(1) { background: oklch(70% 0.14 20); }
.ok span:nth-child(2) { background: oklch(70% 0.14 90); }
.ok span:nth-child(3) { background: oklch(70% 0.14 145); }
.ok span:nth-child(4) { background: oklch(70% 0.14 200); }
.ok span:nth-child(5) { background: oklch(70% 0.14 260); }
.ok span:nth-child(6) { background: oklch(70% 0.14 320); }
.mix span:nth-child(1) { background: #006A4E; }
.mix span:nth-child(2) { background: color-mix(in oklch, #006A4E 60%, white); }
.mix span:nth-child(3) { background: color-mix(in oklch, #006A4E 25%, white); }

প্রথম সারিতে কালো “আ” হলুদ আর সায়ানের ওপর খুব স্পষ্ট, কিন্তু নীলের ওপর প্রায় হারিয়ে গেছে — “৫০% lightness” আসলে সমান নয়। দ্বিতীয় সারিতে সব রঙের উজ্জ্বলতা চোখে প্রায় এক, আর প্রতিটির ওপর “আ” সমানভাবে পড়া যায়। তৃতীয় সারিতে color-mix() পতাকার সবুজকে সাদার সাথে মিশিয়ে হালকা দুটি রূপ বানিয়েছে — হাতে কোনো hex খুঁজতে হয়নি। চেষ্টা করুন: দ্বিতীয় সারির ছয়টি 70%-কে 45% করুন — সব একসাথে গাঢ় হবে, তবুও সমান থাকবে। তারপর white-এর বদলে black লিখে গাঢ় রূপ বানান। (এডিটরটি ২০ লাইনের একটু বেশি, কারণ প্রতিটি ঘর আলাদা লেখা; পর্ব ৩৩-এর CSS variable দিয়ে এটি অনেক ছোট করা যায়।)

সমর্থন: oklch(), oklab(), lab(), lch() আর color-mix() সবগুলো ২০২৩ সালে সব প্রধান ব্রাউজারে এসেছে, এখন (২০২৬) Baseline Widely available. খুব পুরোনো ব্রাউজারের কথা ভাবলে আগে একটি hex লিখে পরের লাইনে oklch দিন — না বুঝলে ব্রাউজার দ্বিতীয় লাইন বাদ দেয়। ডিজাইনাররা oklch পছন্দ করেন আরও একটি কারণে: একটি ব্র্যান্ড রঙের ৫০ থেকে ৯০০ পর্যন্ত ধাপ বানাতে শুধু L বদলালেই চলে, hue স্থির থাকে।

sRGB-এর বাইরে — display-p3

অনেক আধুনিক ফোন আর ল্যাপটপের পর্দা sRGB-এর চেয়ে বেশি তীব্র রং দেখাতে পারে — একে বলে wide gamut, আর সবচেয়ে প্রচলিতটির নাম Display P3. CSS-এ লেখা হয় color(display-p3 1 0 0) — sRGB-এর সবচেয়ে তীব্র লালের চেয়েও বেশি তীব্র লাল। oklch-এ বেশি chroma লিখলেও এই রং পাওয়া যায়; সাধারণ পর্দায় ব্রাউজার নিজেই কাছের দেখানো-যায় এমন রঙে নামিয়ে আনে। কোনো পর্দা এমন রং দেখাতে পারে কি না জানতে আছে media query @media (color-gamut: p3). শুরুর দিকে এটি জানা থাকলেই যথেষ্ট।

সুন্দর, কিন্তু পড়া যায় কি?

রং বাছাইয়ের সবচেয়ে গুরুত্বপূর্ণ প্রশ্ন সৌন্দর্য নয় — লেখাটা পড়া যায় কি না। contrast ratio মাপে লেখা আর পেছনের রঙের আপেক্ষিক উজ্জ্বলতার পার্থক্য: ১:১ (একই রং) থেকে ২১:১ (সাদায় কালো)। WCAG 2.2-এর AA স্তরে:

  • সাধারণ লেখা: অন্তত ৪.৫:১.
  • বড় লেখা (প্রায় 24px, অথবা মোটা হরফে প্রায় 18.66px বা তার বেশি): অন্তত ৩:১.
  • বাটনের বর্ডার, ইনপুটের দাগ, আইকনের মতো UI অংশ: আশেপাশের সাথে অন্তত ৩:১.
রঙের জোড়াকনট্রাস্টসাধারণ লেখাবড় লেখা
সবুজ #006A4E-এ সাদা লেখাপ্রায় ৬.৬:১পাসপাস
লাল #F42A41-এ সাদা লেখাপ্রায় ৪.০:১ফেলপাস
সবুজের ওপর লাল লেখাপ্রায় ১.৭:১ফেলফেল
গাঢ় লাল #D0203A-এ সাদা লেখাপ্রায় ৫.৩:১পাসপাস
সাদায় হালকা ধূসর #9CA3AFপ্রায় ২.৫:১ফেলফেল

অর্থাৎ পতাকার লাল দিয়ে বড় শিরোনামের ব্যানার চলে, কিন্তু ছোট লেখার বাটনে লালটাকে একটু গাঢ় করতে হবে — oklch-এ শুধু L কমিয়ে (প্রায় ৬২% থেকে ৫৫%) একই পরিবারের রং পাওয়া যায়। আর সবুজের ওপর লাল লেখা — পতাকায় সুন্দর, লেখায় অচল; লাল-সবুজ রং আলাদা করতে অসুবিধা হয় এমন মানুষের জন্য তো আরও বেশি। মাপার সহজ উপায়: DevTools-এ কোনো লেখার রঙের ছোট বর্গে ক্লিক করুন — color picker-এ “Contrast ratio” দেখাবে, পাস না ফেল সহ। পুরো আলোচনা পর্ব ৪৫-এ।

১০ · AI-এর যুগে — একক আর রঙের কাজ AI-কে দিলে কী দেখবেন

“একটা সুন্দর landing page-এর CSS লিখে দাও” — AI কয়েক সেকেন্ডে দেবে, আর ল্যাপটপে দেখতেও ভালো লাগবে। কিন্তু AI শিখেছে বহু বছরের পুরোনো কোড থেকে। তাই একক আর রঙে এমন কিছু অভ্যাস প্রায়ই আসে, যা ল্যাপটপে ধরা পড়ে না — ধরা পড়ে ফোনে, বড় লেখার সেটিংয়ে, আর কনট্রাস্ট পরীক্ষায়।

AI সাধারণত যেসব ভুল করে

AI-এর ভুলকেন সমস্যাঠিক উপায়
সব font-size px-এব্যবহারকারীর লেখার মাপের সেটিং কাজ করে নাrem
html { font-size: 16px } বা 10pxব্যবহারকারীর পছন্দ মুছে যায়root-এ হাত না দেওয়া, দিলে শতাংশে
স্বাগত-অংশে height: 100vhফোনে নিচের বাটন ঢাকা পড়ে, বেশি লেখা বাইরে উপচে পড়েmin-height: 100svh
line-height: 1.5em বা 24px body-তেবড় শিরোনামের লাইন চেপে যায়একক ছাড়া 1.6
হালকা ধূসর লেখা, যেমন #9CA3AF সাদায়কনট্রাস্ট ২.৫:১ — পড়া কঠিনDevTools-এ মেপে ৪.৫:১-এর বেশি
disabled বোঝাতে শুধু opacity: 0.5লেখাও ফিকে, কনট্রাস্ট ভাঙেস্পষ্ট আলাদা রং আর disabled attribute
font-size: 5vwZoom-এ লেখা বড় হয় নাclamp()-এ rem মিশিয়ে (পর্ব ৩৫)
অকারণ -webkit- prefix বা ভুল calc (100%-20px)পুরোনো বা অবৈধ কোডprefix ছাড়া লেখা, --এর দুই পাশে ফাঁকা

AI-কে কাজ দেওয়ার আগে শর্তগুলো লিখে দিন। শেষ লাইনটি খেয়াল করুন — AI-কে নিজের রঙের হিসাব দেখাতে বললে তার ভুলও বেরিয়ে আসে, আর আপনি সেটি DevTools-এ মিলিয়ে নিতে পারেন।

তুমি একজন অ্যাক্সেসিবিলিটি-সচেতন ফ্রন্ট-এন্ড ডেভেলপার। আমার অনলাইন দোকানের হোমপেজের জন্য CSS লেখো। ব্র্যান্ডের রং বাংলাদেশের পতাকার সবুজ #006A4E আর লাল #F42A41. শর্ত: ১. সব font-size rem-এ; html-এর font-size বদলাবে না। ২. line-height একক ছাড়া, বাংলা লেখার জন্য 1.6 থেকে 1.8. ৩. স্বাগত-অংশে min-height: 100svh, আর পুরোনো ব্রাউজারের জন্য আগের লাইনে 100vh. ৪. রংগুলো oklch()-এ লেখো, প্রতিটির আগে একটি hex fallback দাও; হালকা ও গাঢ় রূপ বানাতে color-mix() ব্যবহার করো। ৫. কোনো -webkit- prefix নয়, আর লেখার জন্য opacity দিয়ে রং ফিকে করবে না। শেষে একটি টেবিলে প্রতিটি লেখা-আর-পেছনের রঙের জোড়ার contrast ratio দাও, আর বলো কোনটি WCAG AA-তে ৪.৫:১ পাস করে না।

AI-এর দেওয়া CSS হাতে পেলে — যাচাইয়ের চেকলিস্ট

পরীক্ষা ও ইন্টারভিউতে — বিশ্ববিদ্যালয়, চাকরি বা ফ্রন্ট-এন্ড ইন্টারভিউর পরীক্ষায় এ ধরনের প্রশ্ন প্রায়ই আসে:

  • em আর rem-এর পার্থক্য? — em মূল উপাদানের (বা নিজের) font-size থেকে হিসাব হয় আর নেস্টিং-এ জমে; rem সবসময় root-এর font-size থেকে।
  • padding-top: 10% কিসের ১০%? — containing block-এর চওড়ার, উচ্চতার নয়।
  • line-height-এ একক ছাড়া মান কেন ভালো? — সন্তানেরা স্থির px নয়, গুণক পায়; প্রত্যেকে নিজের font-size দিয়ে হিসাব করে।
  • opacity আর rgba/alpha-র পার্থক্য? — opacity পুরো element আর তার সন্তানদের স্বচ্ছ করে; alpha শুধু সেই রংটিকে।
  • WCAG AA-তে কনট্রাস্টের ন্যূনতম মান? — সাধারণ লেখা ৪.৫:১, বড় লেখা আর UI অংশ ৩:১.

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন। এগুলোই আপনাকে কোড-লেখক থেকে সিস্টেম-চিন্তক বানাবে।

প্র ০১CSS-এর 1px কেন স্ক্রিনের একটি পিক্সেল নয়? এই সিদ্ধান্ত না নিলে আজকের ওয়েব কেমন হতো?

শুরুর দিকের ওয়েবে প্রায় সব মনিটরের পিক্সেল ঘনত্ব কাছাকাছি ছিল, তাই 1px = একটি পর্দার বিন্দু — এই সরল সমীকরণে কারও সমস্যা হয়নি। ডিজাইনাররা পিক্সেল ধরে ধরে নকশা করতেন, আর সেটাই সবখানে প্রায় একই দেখাত।

২০১০ সালে Apple “Retina” পর্দার iPhone আনে, যেখানে একই মাপের পর্দায় আগের দ্বিগুণ ঘন পিক্সেল। যদি CSS-এর px তখনও পর্দার বিন্দু হতো, তাহলে কোটি কোটি পুরোনো পাতা ঐ ফোনে অর্ধেক আকারে, পড়ার অযোগ্য হয়ে দেখা দিত। সমাধান ছিল px-কে পর্দার বিন্দু থেকে আলাদা করা: ফোন বলল “আমার একটি CSS পিক্সেল = ২×২ বিন্দু”। পুরোনো পাতাগুলো সঠিক আকারে রইল, আর লেখা হলো আগের চেয়ে অনেক ধারালো। পরে Android-এর নানা ফোনে এই অনুপাত ১.৫, ২.৬২৫, ৩ — নানা রকম হলো।

CSS spec আসলে এর অনেক আগেই এই দরজা খুলে রেখেছিল। spec-এ px-কে বলা হয়েছে একটি “reference pixel” — দূরত্বের সাথে মানানো একটি কোণের মাপ। তাই প্রজেক্টরের পর্দায় একটি px হয়তো কয়েক মিলিমিটার চওড়া, কিন্তু দূর থেকে দেখা দর্শকের চোখে সেটি ফোনের px-এর মতোই লাগে।

এর ফল কয়েকটি জায়গায় আজও দেখা যায়। ঘন পর্দায় ছবি ঝাপসা না দেখাতে srcset দিয়ে দ্বিগুণ রেজোলিউশনের ছবি দিতে হয় (পর্ব ৩২)। 0.5px-এর মতো ভগ্নাংশ রেখা কোনো পর্দায় সত্যিকারের এক বিন্দু হয়, কোনোটায় ঝাপসা। আর ব্রাউজারের Zoom মূলত এই অনুপাতই বদলায় — ১০০% থেকে ২০০% zoom মানে একটি CSS পিক্সেলে দ্বিগুণ বিন্দু।

মূল উপলব্ধি: ভালো abstraction হার্ডওয়্যারের পরিবর্তন থেকে সফটওয়্যারকে রক্ষা করে। CSS px-কে একটি “চোখের মাপ” বানিয়ে ওয়েব নতুন পর্দার যুগেও পুরোনো পাতাগুলো ভাঙতে দেয়নি — এই কারণেই বহু পুরোনো ওয়েব পাতা আজকের ফোনেও খোলা যায়।

প্র ০২“সব কিছু px-এ লিখলেই তো সহজ, ব্রাউজারে Zoom তো আছেই” — এই যুক্তি কোথায় ভুল?

যুক্তিটা অর্ধেক সত্য, আর সেজন্যই বিপজ্জনক। আধুনিক ব্রাউজারের Zoom সত্যিই px-এ লেখা পাতাও বড় করে। কিন্তু ব্যবহারকারীর হাতে আরেকটি সেটিং আছে — ডিফল্ট লেখার মাপ। দুটি এক জিনিস নয়।

  • Zoom প্রতিটি সাইটে আলাদা করে করতে হয়, আর পুরো লেআউট বড় হয় — ছোট ল্যাপটপে ২০০% zoom-এ পাতাটি প্রায় ফোনের মতো সরু হয়ে যায়।
  • ডিফল্ট লেখার মাপ একবার বদলালেই সব সাইটে কাজ করে — শুধু লেখা বড় হয়, লেআউট যতটা সম্ভব একই থাকে। কম দৃষ্টিশক্তির অনেক মানুষ, বিশেষ করে বয়স্করা, এটাই পছন্দ করেন। কিন্তু px-এ লেখা পাতা এই সেটিং পুরোপুরি উপেক্ষা করে।

এই কারণেই একসময় জনপ্রিয় হয় html { font-size: 62.5% } কৌশল — ১৬px-এর ৬২.৫% = ১০px, তাই 1.6rem = ১৬px, হিসাব যেন px-এর মতোই সহজ। শতাংশে লেখা বলে এটি ব্যবহারকারীর পছন্দ মানে, কিন্তু নতুন সমস্যাও আনে: যে লেখায় আপনি rem দিতে ভুলে যান সেটি ১০px-এর হয়ে পড়ার অযোগ্য হয়, আর বাইরের কোনো library ধরে নেয় 1rem = 16px. আজকের সাধারণ পরামর্শ — root-এ হাত না দিয়ে সরাসরি rem-এ ভাবা (১rem = ১৬px ধরে: 1.125rem = 18px, 1.5rem = 24px).

আরেকটি সূক্ষ্ম জায়গা media query (পর্ব ৩১)। @media (min-width: 48em) লিখলে সীমাটি ব্যবহারকারীর ডিফল্ট লেখার মাপ থেকে হিসাব হয় — লেখা বড় করা ব্যবহারকারীর জন্য লেআউট একটু আগেই এক-কলামে চলে যায়, ফলে বড় লেখা সরু কলামে চাপা পড়ে না।

মূল উপলব্ধি: অ্যাক্সেসিবিলিটি মানে ব্যবহারকারীর নিজের সিদ্ধান্তকে সম্মান করা। “আমার মেশিনে ঠিক দেখায়” যথেষ্ট নয় — প্রশ্ন হলো, যে মানুষ লেখা বড় করে রেখেছেন, তাঁর মেশিনে কী দেখায়।

প্র ০৩মোবাইল ব্রাউজার 100vh-কে কেন “ভুল” মাপে রাখল? নতুন svh, lvh, dvh কি সব সমস্যার সমাধান?

ভুল মনে হলেও সিদ্ধান্তটি ইচ্ছাকৃত ছিল। মোবাইলে address bar স্ক্রলের সাথে আস্তে আস্তে লুকায় আর ফেরে। যদি vh প্রতি মুহূর্তে বদলাত, তাহলে স্ক্রলের প্রতিটি ফ্রেমে 100vh দেওয়া প্রতিটি বাক্সের উচ্চতা বদলাত, আর ব্রাউজারকে বারবার পুরো লেআউট নতুন করে হিসাব করতে হতো। ফল: লেখা লাফাত, পড়ার জায়গা হারিয়ে যেত, আর কম দামের ফোনে স্ক্রল হতো ঝাঁকুনিময়। তাই iOS-এর Safari প্রথমে vh-কে স্থির রাখার সিদ্ধান্ত নেয় — bar লুকানো অবস্থার বড় মাপে — আর অন্য মোবাইল ব্রাউজারও মোটামুটি একই পথে যায়।

স্থির রাখার দাম ছিল সেই চেনা বাগ: পাতা খোলার সময় নিচের অংশ পর্দার বাইরে। বছরের পর বছর ডেভেলপাররা JavaScript দিয়ে আসল উচ্চতা মেপে CSS variable-এ বসাতেন — ঝামেলার, আর ধীর। শেষে CSS Values and Units Level 4 সমস্যাটিকে নাম দিয়ে ভাগ করে দেয়: svh (সবচেয়ে ছোট অবস্থা), lvh (সবচেয়ে বড়), dvh (এই মুহূর্তের)। এগুলোর চওড়ার জোড়াও আছে — svw, dvw ইত্যাদি — আর লেখার দিক অনুযায়ী vi, vb.

সব সমস্যার সমাধান কি? না। dvh ঠিক সেই লাফানো ফিরিয়ে আনে, যা এড়াতে আগের সিদ্ধান্ত হয়েছিল — তাই শুধু যেখানে সত্যিই দরকার সেখানে। on-screen কি-বোর্ড খুললে viewport বদলায় কি না, সেটি আবার আলাদা প্রশ্ন, আর ব্রাউজারভেদে আচরণ ভিন্ন (এর জন্য viewport meta-র interactive-widget নামে একটি আলাদা সেটিং আছে, যার সমর্থন এখনো সব ব্রাউজারে নয়)। তাই মোবাইলে উচ্চতা নিয়ে কাজ করলে আসল ফোনে পরীক্ষাই শেষ কথা।

মূল উপলব্ধি: ওয়েবের অনেক “অদ্ভুত” আচরণ আসলে একটি trade-off-এর ফল — এখানে নির্ভুল মাপ বনাম মসৃণ স্ক্রল। নতুন feature পুরোনো trade-off মুছে দেয় না, শুধু আপনাকে বেছে নেওয়ার স্বাধীনতা দেয়।

প্র ০৪HSL তো আগে থেকেই “মানুষের মতো” — তাহলে oklch() কেন দরকার হলো? এর পেছনের বিজ্ঞানটা কী?

HSL আর তার ভাই HSV জন্মেছিল ১৯৭০-এর দশকের শেষে কম্পিউটার গ্রাফিক্সের গবেষণায় — উদ্দেশ্য ছিল RGB-কে মানুষের পক্ষে নাড়াচাড়া সহজ করা। এরা মূলত RGB ঘনকটিকে একটু ঘুরিয়ে-বাঁকিয়ে দেখার একটি গাণিতিক কৌশল। চোখের অনুভূতি মাপার কোনো বৈজ্ঞানিক তথ্য এতে ব্যবহার হয়নি। তাই হলুদ আর নীল একই “৫০% lightness”-এ চোখে একেবারে আলাদা উজ্জ্বল।

চোখের অনুভূতি মাপার চেষ্টা রঙবিজ্ঞানে অনেক পুরোনো। ১৯৭৬ সালে আন্তর্জাতিক আলো কমিশন (CIE) প্রকাশ করে CIELAB, যা মানুষের ওপর পরীক্ষার তথ্য থেকে তৈরি — CSS-এর lab() আর lch() এরই রূপ। কিন্তু CIELAB-এর একটি পরিচিত ত্রুটি: নীল রঙের chroma কমাতে গেলে সেটি বেগুনির দিকে সরে যায়, ফলে নীলের হালকা রূপ বানাতে গেলে বেগুনি-ঘেঁষা রং আসে।

২০২০ সালে Björn Ottosson নামে একজন প্রকৌশলী আধুনিক রং-অনুভূতির তথ্য দিয়ে নতুন করে একটি সরল মডেল বানান — Oklab, আর তার মেরু-রূপ OKLCH. এটি হিসাবে সহজ, নীলের সেই সরে যাওয়া অনেক কম, আর “L” সত্যিই চোখের আলো-অনুভূতির কাছাকাছি। CSS Color Level 4 খুব দ্রুত এটিকে গ্রহণ করে, আর ২০২৩ সালে সব প্রধান ব্রাউজারে আসে। Tailwind CSS-এর মতো জনপ্রিয় framework-এর সাম্প্রতিক সংস্করণও তার ডিফল্ট রঙের প্যালেট oklch-এ লিখেছে।

ব্যবহারিক লাভ তিনটি: (১) একই L মানে সব hue-তে প্রায় সমান উজ্জ্বলতা, তাই একটি বাটন-পরিবারের সব রঙে একই রঙের লেখা সমানভাবে পড়া যায়; (২) dark mode বা হালকা-গাঢ় ধাপ বানাতে শুধু L বদলালেই চলে (পর্ব ৩৬); (৩) color-mix(in oklch, …) বা gradient-এ মাঝের রংগুলো ঘোলাটে ধূসর হয় না। একটি সতর্কতা: L সমান হলেও WCAG-এর কনট্রাস্ট হিসাব আলাদা সূত্রে চলে — তাই শেষ যাচাই সবসময় contrast ratio দিয়েই।

মূল উপলব্ধি: ভালো টুল মানে ঠিক প্রশ্নের জন্য ঠিক মাপকাঠি। RGB মেশিনের প্রশ্নের উত্তর দেয়, HSL হাতের সুবিধার, আর OKLCH মানুষের চোখের।

প্র ০৫৪.৫:১ সংখ্যাটা কোথা থেকে এলো? কনট্রাস্ট পাস করলেই কি পাতা সবার জন্য পড়ার উপযোগী?

WCAG 2.0 (২০০৮) কনট্রাস্টের একটি সূত্র দেয়: দুই রঙের আপেক্ষিক উজ্জ্বলতা (relative luminance) বের করে, উজ্জ্বলটির সাথে ০.০৫ যোগ করে, গাঢ়টির সাথে ০.০৫ যোগ করে ভাগ। ফল ১ থেকে ২১. ৪.৫:১ সীমাটি বেছে নেওয়া হয় এভাবে — স্বাভাবিক দৃষ্টিতে ৩:১-এর মতো কনট্রাস্ট যথেষ্ট ধরা হয়, আর মাঝারি কম দৃষ্টিশক্তির মানুষ (যা প্রায় ২০/৪০ দৃষ্টির সমতুল্য ধরা হয়) যে কনট্রাস্ট হারান, তা পুষিয়ে নিতে সীমাটি বাড়িয়ে ৪.৫:১ করা হয়। বড় লেখা এমনিতেই পড়া সহজ, তাই তার সীমা ৩:১. AAA স্তরে সীমা ৭:১.

কিন্তু পাস করলেই সব ঠিক — এমন নয়। কয়েকটি সীমাবদ্ধতা:

  • সূত্রটি ফন্টের মোটা-পাতলা বোঝে না। খুব পাতলা হরফের ছোট লেখা ৪.৫:১-এ পাস করেও কষ্টকর হতে পারে — বাংলার সূক্ষ্ম কার-ফলার ক্ষেত্রে আরও বেশি।
  • গাঢ় পেছনে সূত্রটি কিছুটা উদার। এ কারণে APCA-র মতো নতুন পদ্ধতি নিয়ে গবেষণা চলছে (WCAG 3-এর আলোচনায় এসেছে), যা লেখার মাপ আর মোটা-পাতলাও হিসাবে নেয়। এটি এখনো মান (standard) হয়নি — আজকের আইনি ও পেশাদার মাপকাঠি WCAG 2.2-এর অনুপাতই।
  • রঙে-অন্ধতা আলাদা প্রশ্ন। পুরুষদের প্রায় ১২ জনে ১ জনের কোনো না কোনো রং-পার্থক্য করার অসুবিধা থাকে, বেশিরভাগই লাল-সবুজে। তাই শুধু রং দিয়ে তথ্য দেওয়া চলে না — “লাল মানে ভুল” না বলে সাথে একটি আইকন বা লেখা দিন (WCAG নিয়ম ১.৪.১)।
  • পরিবেশ। রোদে ফোনের পর্দায়, বা কম দামের মনিটরে, কম কনট্রাস্ট আরও খারাপ দেখায় — বাংলাদেশের দুপুরের রোদে রিকশায় বসে ফোন দেখার কথা ভাবুন।

মূল উপলব্ধি: কনট্রাস্টের সংখ্যা একটি ন্যূনতম সীমা, লক্ষ্য নয়। সংখ্যা মেপে পাস করান, তারপর আসল মানুষের চোখে, আসল পর্দায়, আসল আলোয় দেখে নিন।

অনুশীলন

বেশিরভাগ কাজে DevTools খুলে দেখা আর হিসাব করাই আসল কাজ।

  1. Computed প্যানেলে মাপ খুঁজুন: এই পাতার যেকোনো অনুচ্ছেদে ডান-ক্লিক করে “Inspect” চাপুন। DevTools-এর Computed ট্যাবে font-size, line-height আর width খুঁজুন। CSS-এ যা লেখা (Styles ট্যাব) আর Computed-এ যা দেখাচ্ছে — পার্থক্য কোথায়?

    Styles ট্যাবে দেখবেন লেখকের লেখা মান — হয়তো 1.05rem, 1.8 বা 100%. Computed ট্যাবে প্রায় সব মান px-এ — যেমন font-size: 16.8px. width-এর জায়গায় লেআউটের পরের আসল চওড়া (used value). ব্যতিক্রম line-height: একক ছাড়া লেখা থাকলে অনেক ব্রাউজার Computed-এ সেটি px-এ দেখায়, কিন্তু সন্তানেরা আসলে গুণকটিই পায় — DevTools-এর দেখানো সংখ্যা আর উত্তরাধিকারের নিয়ম সবসময় একই জিনিস নয়।

  2. হিসাব করুন: html-এর font-size ব্রাউজারের ডিফল্ট (16px). একটি .card-এর font-size: 1.25rem, তার ভেতরে একটি .tag-এর font-size: 0.8em আর padding: 0.5em 1em. ট্যাগের লেখা আর padding কত px? ব্যবহারকারী ডিফল্ট লেখা 20px করলে?

    কার্ড: 1.25 × 16 = 20px. ট্যাগের লেখা: 0.8 × 20 = 16px. ট্যাগের padding-এ em মানে ট্যাগের নিজের font-size (16px): ওপর-নিচে 8px, ডানে-বাঁয়ে 16px.

    ডিফল্ট 20px হলে: কার্ড 25px, ট্যাগের লেখা 20px, padding 10px আর 20px — সব কিছু সমান অনুপাতে বড় হলো। এটাই rem আর em একসাথে ব্যবহারের সৌন্দর্য: rem শুরুর বিন্দু ঠিক করে, em স্থানীয় অনুপাত রাখে।

  3. চক্রবৃদ্ধি em ঠিক করুন: একটি সাইটের মেনুতে nav li { font-size: 0.9em; } লেখা, আর তিন স্তরের উপ-মেনুতে লেখা প্রায় পড়াই যায় না। চেহারা একই রেখে সমস্যাটি সমাধান করুন।

    em-কে rem করুন — তাহলে প্রতিটি স্তর root থেকে হিসাব করে, জমে না। প্রিভিউতে দুটি সমাধান পাশাপাশি দেখুন:

    <style>
      .bad li  { font-size: 0.9em; }   /* স্তরে স্তরে 0.9 × 0.9 × 0.9 */
      .good li { font-size: 0.9rem; }  /* সব স্তরে 14.4px */
    </style>
    <nav class="bad"><ul><li>কোর্স
      <ul><li>প্রোগ্রামিং
        <ul><li>HTML ও CSS
          <ul><li>একক আর রং</li></ul></li></ul></li></ul></li></ul></nav>
    <nav class="good"><ul><li>কোর্স
      <ul><li>প্রোগ্রামিং
        <ul><li>HTML ও CSS
          <ul><li>একক আর রং</li></ul></li></ul></li></ul></li></ul></nav>

    ওপরের মেনুতে চতুর্থ স্তর প্রায় 10.5px (16 × 0.9⁴), নিচেরটিতে সব স্তর 14.4px. বিকল্প সমাধান: শুধু প্রথম স্তরে em রেখে ভেতরের তালিকায় font-size: inherit বা 1em দেওয়া। চেষ্টা করুন: .good li-এ 0.9rem-কে 1rem করুন।

  4. পতাকার রঙে বাটন: দোকানের “অর্ডার করুন” বাটনে লাল #F42A41-এর ওপর সাদা 16px লেখা। DevTools-এর color picker বা যেকোনো contrast checker দিয়ে যাচাই করুন। পাস না করলে কী বদলাবেন, যাতে ব্র্যান্ডের রং চেনা যায়?

    কনট্রাস্ট প্রায় ৪.০:১ — 16px সাধারণ লেখার জন্য দরকার ৪.৫:১, তাই ফেল। তিনটি পথ:

    • লালটি একটু গাঢ় করুন — oklch-এ hue আর chroma প্রায় একই রেখে L কমান, যেমন oklch(55% 0.21 22)-এর কাছাকাছি, বা hex-এ #D0203A (প্রায় ৫.৩:১)। চোখে এখনো “পতাকার লাল” পরিবারই।
    • লেখা বড় ও মোটা করুন (প্রায় 18.66px bold বা 24px) — তখন সীমা ৩:১, আর ৪.০ পাস করে। তবে বাটনের লেখা বড় করা সবসময় নকশায় মানায় না।
    • লাল ব্র্যান্ড রং বর্ডার বা আইকনে রাখুন, আর বাটনের পেছনে সবুজ #006A4E দিন — সাদা লেখায় প্রায় ৬.৬:১.

    যে পথই নিন, শেষে আবার মেপে দেখুন — অনুমান নয়, সংখ্যা।

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমhtml-এর font-size 16px আর viewport 1000px চওড়া ধরে মাপগুলো ছোট থেকে বড় সাজান (▲▼ চেপে সরান)

  1. 10px
  2. 1rem (১৬px)
  3. 2rem (৩২px)
  4. 5vw (৫০px)
  5. 1in (৯৬px)

একটি div-এর font-size 20px. তার ভেতরের p-তে font-size: 1.5em লেখা, আর html-এর font-size 16px. p-এর লেখার মাপ কত হবে?

  • 24px
  • 20px
  • 30px
  • 1.5px

CSS-এ padding-top: 10% লিখলে ১০% কিসের থেকে হিসাব হয়?

  • containing block-এর উচ্চতা
  • containing block-এর চওড়া
  • element-এর নিজের font-size
  • ব্রাউজারের জানালার উচ্চতা

মোবাইলে একটি স্বাগত-অংশ এমন উচ্চতার দরকার, যা address bar দেখা গেলেও কখনো পর্দার বাইরে যাবে না এবং স্ক্রলের সময় লাফাবে না। কোন মান সবচেয়ে উপযুক্ত?

  • 100vh
  • 100lvh
  • 100dvh
  • 100svh

body-তে line-height দেওয়ার জন্য কোনটি সবচেয়ে ভালো, যাতে ভেতরের বড় শিরোনামের লাইনও চেপে না যায়?

  • line-height: 1.6
  • line-height: 1.6em
  • line-height: 160%
  • line-height: 26px

একটি কার্ডের পেছনের রং আধা-স্বচ্ছ করতে হবে, কিন্তু ভেতরের লেখা পুরো স্পষ্ট থাকবে। কোনটি লিখবেন?

  • opacity: 0.5
  • visibility: 0.5
  • background: rgb(0 106 78 / 50%)
  • background: transparent

WCAG 2.2-এর AA স্তরে সাধারণ মাপের লেখা আর তার পেছনের রঙের মধ্যে ন্যূনতম কনট্রাস্ট কত হতে হয়?

  • ৩:১
  • ৪.৫:১
  • ৭:১
  • ২১:১

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. CSS-এর px একটি চোখের মাপ, পর্দার বিন্দু নয়; ব্রাউজার শেষে সব একককে px-এ হিসাব করে, তারপর device pixel ratio দিয়ে আঁকে।
  2. লেখার মাপ rem-এ, স্থানীয় অনুপাত em-এ (নেস্টিং-এ em জমে); % কিসের — property দেখে বলতে হয়; padding-এর % সবসময় চওড়ার।
  3. মোবাইলে পূর্ণ-পর্দার অংশে min-height: 100svh; line-height একক ছাড়া; মিশ্র মাপে calc(), --এর দুই পাশে ফাঁকা রেখে।
  4. একই রং নানা ভাষায়: নাম, hex, rgb(), hsl(), oklch(); alpha শুধু রংকে, opacity পুরো element-কে স্বচ্ছ করে; currentColor লেখার রং অনুসরণ করে।
  5. প্যালেট বানাতে oklch আর color-mix, কিন্তু শেষ কথা কনট্রাস্ট: সাধারণ লেখা ৪.৫:১, বড় লেখা ৩:১ — মেপে দেখুন, অনুমান নয়।

পরের পর্বে: মাপ আর রং তো হলো — এবার লেখার নিজের সৌন্দর্য। ওয়েব ফন্ট, বাংলা হরফের জন্য ঠিক ফন্ট বাছাই, font-weight, letter-spacing আর পড়তে আরামদায়ক অনুচ্ছেদের নকশা।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান