CSS Variables & Custom Properties

CSS ভ্যারিয়েবল ও কাস্টম প্রপার্টি

Read: ~22 min Intermediate 5 practice problems Live preview runner

1. Define a Value Once, Use It Everywhere

Imagine your brand color is used in forty different CSS rules across a site, and the client asks you to change it. Without variables, you'd hunt down and edit forty lines. With a CSS custom property — commonly called a CSS variable — you define the color once and every rule that references it updates automatically. This is the foundation of real, maintainable design systems.

ধরুন আপনার ব্র্যান্ড কালারটি একটি সাইটের চল্লিশটি ভিন্ন CSS নিয়মে ব্যবহৃত হচ্ছে, আর ক্লায়েন্ট সেটি বদলাতে বলছেন। ভ্যারিয়েবল ছাড়া আপনাকে চল্লিশটি লাইন খুঁজে বের করে বদলাতে হবে। একটি CSS custom property — যাকে সাধারণত CSS ভ্যারিয়েবল বলা হয় — দিয়ে আপনি রংটি একবার সংজ্ঞায়িত করেন, আর যে নিয়মগুলো এটি ব্যবহার করে সেগুলো নিজে থেকেই আপডেট হয়ে যায়। এটিই আসল, রক্ষণাবেক্ষণযোগ্য ডিজাইন সিস্টেমের ভিত্তি।

Core insight: a CSS variable lets you define a color once and reuse it site-wide — to change it, you edit only one place.

মূল বিষয়: CSS ভ্যারিয়েবল দিয়ে একটি রঙ একবার সংজ্ঞায়িত করে পুরো সাইটে ব্যবহার করা যায় — পরিবর্তন করতে হলে একজায়গায় বদলালেই চলে।

2. --variable-name Syntax

A custom property name always starts with two dashes: --main-color: #39b549;. It's not a special keyword — it's any name you choose, prefixed with --. Custom properties are declared inside a CSS rule just like any other property, most often inside :root, a pseudo-class that matches the top-level <html> element and makes the variable available everywhere on the page.

একটি custom property-এর নাম সবসময় দুটি ড্যাশ দিয়ে শুরু হয়: --main-color: #39b549;। এটি কোনো বিশেষ কিওয়ার্ড নয় — -- প্রিফিক্স দিয়ে আপনি নিজের পছন্দমতো যেকোনো নাম দিতে পারেন। Custom property অন্য যেকোনো প্রপার্টির মতোই একটি CSS নিয়মের ভেতরে ঘোষণা করা হয়, সবচেয়ে বেশি ব্যবহৃত হয় :root-এর ভেতরে — যা শীর্ষ-স্তরের <html> এলিমেন্টকে ম্যাচ করে এবং ভ্যারিয়েবলটিকে পুরো পেজের যেকোনো জায়গায় ব্যবহারযোগ্য করে তোলে।

3. var() — Reading a Variable, with Fallbacks

To use a custom property, wrap its name in var(): color: var(--main-color);. var() also accepts an optional second argument as a fallback: color: var(--main-color, blue); uses blue if --main-color was never defined or is invalid. Fallbacks make components safer to reuse in contexts where the variable might not exist yet.

একটি custom property ব্যবহার করতে এর নামকে var()-এ মুড়িয়ে নিন: color: var(--main-color);। var() ঐচ্ছিক দ্বিতীয় আর্গুমেন্টও গ্রহণ করে fallback হিসেবে: color: var(--main-color, blue); — --main-color কখনো সংজ্ঞায়িত না হলে বা অবৈধ হলে blue ব্যবহার করবে। Fallback একটি কম্পোনেন্টকে এমন context-এও নিরাপদে পুনর্ব্যবহারযোগ্য করে তোলে যেখানে ভ্যারিয়েবলটি হয়তো এখনো নেই।
variables.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>CSS Variables</title></head>
<body>
  <div class="card">
    <h2>Design System Card</h2>
    <p>All colors and spacing here come from variables defined once on :root.</p>
    <button class="btn">Action</button>
  </div>
</body>
</html>
style.css
:root {
  --brand-color: #39b549;
  --text-color: #1a1a1a;
  --gap: 16px;
}

body { font-family: sans-serif; padding: var(--gap); }

.card {
  border: 2px solid var(--brand-color);
  border-radius: 8px;
  padding: var(--gap);
  color: var(--text-color);
}

.btn {
  background: var(--brand-color);
  color: white;
  border: none;
  padding: 8px 16px;
  border-radius: 6px;
  /* fallback in case --highlight-color is never defined */
  box-shadow: 0 0 0 2px var(--highlight-color, #e6f4e8);
}

4. Scoping Variables to :root or a Class

Variables declared on :root are global — available anywhere. But you can also declare a variable inside any regular class, and it will only be available to that element and its descendants, overriding the global value within that scope. This is exactly how component-level theming works: a .card can redefine --brand-color just for itself without touching the site-wide default.

:root-এ ঘোষিত ভ্যারিয়েবল গ্লোবাল — যেকোনো জায়গা থেকে ব্যবহারযোগ্য। কিন্তু আপনি যেকোনো সাধারণ ক্লাসের ভেতরেও ভ্যারিয়েবল ঘোষণা করতে পারেন, যা কেবল সেই এলিমেন্ট ও তার descendant-দের জন্য প্রযোজ্য হবে — সেই scope-এর ভেতরে গ্লোবাল মানকে override করে। কম্পোনেন্ট-লেভেল থিমিং ঠিক এভাবেই কাজ করে — একটি .card নিজের জন্য --brand-color পুনর্সংজ্ঞায়িত করতে পারে, সাইট-ওয়াইড ডিফল্ট স্পর্শ না করেই।

5. Theming & Dark Mode Basics

Because variables can be redefined per-scope, theming becomes a matter of swapping a small set of values rather than rewriting rules. A typical dark-mode setup defines --bg and --text on :root for light mode, then redefines the same variable names inside a .dark-theme class (or a prefers-color-scheme: dark media query). Every rule that already uses var(--bg) and var(--text) updates automatically — you never touch those rules again.

যেহেতু ভ্যারিয়েবল প্রতি-scope-এ পুনর্সংজ্ঞায়িত করা যায়, থিমিং মানে দাঁড়ায় নিয়ম নতুন করে লেখার বদলে কিছু মান অদল-বদল করা। একটি সাধারণ dark-mode সেটআপে light mode-এর জন্য :root-এ --bg ও --text সংজ্ঞায়িত করা হয়, তারপর একই ভ্যারিয়েবল নাম .dark-theme ক্লাসের ভেতরে (অথবা prefers-color-scheme: dark মিডিয়া কোয়েরিতে) পুনর্সংজ্ঞায়িত করা হয়। ইতিমধ্যে var(--bg) ও var(--text) ব্যবহার করা প্রতিটি নিয়ম নিজে থেকেই আপডেট হয়ে যায়।

The demo below can't run JavaScript to flip a toggle, so it shows two .card elements side by side — one scoped to light-mode variables, one scoped to dark-mode variables — to make the effect of variable scoping visible without any script.

নিচের ডেমোতে টগল চালানোর জন্য JavaScript নেই, তাই এটি দুটি .card এলিমেন্ট পাশাপাশি দেখায় — একটি light-mode ভ্যারিয়েবলের scope-এ, অন্যটি dark-mode ভ্যারিয়েবলের scope-এ — কোনো স্ক্রিপ্ট ছাড়াই variable scoping-এর প্রভাব দৃশ্যমান করার জন্য।
theme.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Theme Demo</title></head>
<body>
  <div class="card light-theme">
    <h3>Light Card</h3>
    <p>Uses the default :root variables.</p>
  </div>
  <div class="card dark-theme">
    <h3>Dark Card</h3>
    <p>Same markup, variables re-scoped locally.</p>
  </div>
</body>
</html>
style.css
:root {
  --bg: #ffffff;
  --text: #1a1a1a;
  --accent: #39b549;
}

body { font-family: sans-serif; display: flex; gap: 16px; }

.card {
  background: var(--bg);
  color: var(--text);
  border: 2px solid var(--accent);
  border-radius: 8px;
  padding: 16px;
  flex: 1;
}

/* Re-scope the same variable names for this element and its children */
.dark-theme {
  --bg: #0f172a;
  --text: #e2e8f0;
  --accent: #4ade80;
}
Key insight Real dark-mode toggles in production just add/remove a class like .dark-theme on <body> with a few lines of JavaScript — the CSS variable re-scoping shown above is the entire trick; the JavaScript only flips which class is present.

প্রোডাকশনে আসল dark-mode টগল কেবল <body>-তে .dark-theme-এর মতো একটি ক্লাস কয়েক লাইন JavaScript দিয়ে যোগ/বাদ দেয় — উপরে দেখানো CSS ভ্যারিয়েবল re-scoping-ই পুরো কৌশল; JavaScript কেবল কোন ক্লাস আছে তা বদলায়।

6. Reference (রেফারেন্স)

ConceptMeaningবাংলায়
--name: value;Declares a custom property.একটি custom property ঘোষণা করে।
var(--name)Reads the value of a custom property.একটি custom property-এর মান পড়ে।
var(--name, fallback)Uses fallback if the variable is undefined.ভ্যারিয়েবল অসংজ্ঞায়িত হলে fallback ব্যবহার করে।
:rootGlobal scope for variables (matches <html>).ভ্যারিয়েবলের গ্লোবাল scope (<html>-কে ম্যাচ করে)।
Class-level redefinitionOverrides a variable only within that element's scope.কেবল সেই এলিমেন্টের scope-এর ভেতরে ভ্যারিয়েবল override করে।

7. Practice Problems

Try each problem yourself first, then open the answer and run it in the live preview.

প্রথমে প্রতিটি সমস্যা নিজে সমাধান করার চেষ্টা করুন, তারপর উত্তর খুলে লাইভ প্রিভিউতে চালিয়ে দেখুন।
  1. Define --spacing: 20px; on :root and use it as the padding of a .box.
    :root-এ --spacing: 20px; সংজ্ঞায়িত করে একটি .box-এর padding হিসেবে ব্যবহার করুন।
    ✨ Show Answer (উত্তর দেখুন)
    ans1.html
    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><title>Spacing Variable</title></head>
    <body>
      <div class="box">Padded box</div>
    </body>
    </html>
    style.css
    :root {
      --spacing: 20px;
    }
    .box {
      padding: var(--spacing);
      background: #e6f4e8;
      border: 2px solid #39b549;
    }
  2. Write a var() call for --link-color with a fallback of blue.
    --link-color-এর জন্য একটি var() কল লিখুন যার fallback হবে blue।
    ✨ Show Answer (উত্তর দেখুন)

    Answer: color: var(--link-color, blue); — if --link-color is undefined or invalid, the browser falls back to blue.

    color: var(--link-color, blue); — --link-color অসংজ্ঞায়িত বা অবৈধ হলে ব্রাউজার fallback হিসেবে blue ব্যবহার করবে।

  3. Create two .card elements where a second card overrides --accent locally to a different color while reusing the same rules.
    দুটি .card এলিমেন্ট তৈরি করুন যেখানে দ্বিতীয় কার্ডটি একই নিয়ম পুনর্ব্যবহার করেও --accent-কে ভিন্ন রঙে override করে।
    ✨ Show Answer (উত্তর দেখুন)
    ans3.html
    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><title>Local Override</title></head>
    <body>
      <div class="card">Default accent</div>
      <div class="card purple">Overridden accent</div>
    </body>
    </html>
    style.css
    :root { --accent: #39b549; }
    .card {
      border: 3px solid var(--accent);
      padding: 12px;
      margin-bottom: 8px;
    }
    .card.purple {
      --accent: #7c3aed;
    }
  4. In one sentence, explain why :root is a common place to declare variables.
    এক বাক্যে ব্যাখ্যা করুন, ভ্যারিয়েবল ঘোষণার জন্য :root কেন একটি সাধারণ জায়গা।
    ✨ Show Answer (উত্তর দেখুন)

    Answer: :root matches the top-level <html> element, so any variable declared there is inherited and available to every other element on the page.

    :root শীর্ষ-স্তরের <html> এলিমেন্টকে ম্যাচ করে, তাই সেখানে ঘোষিত যেকোনো ভ্যারিয়েবল inherit হয়ে পেজের প্রতিটি অন্য এলিমেন্টে ব্যবহারযোগ্য হয়ে যায়।

  5. Build a simple light/dark theme pair of variables (--bg, --text) and apply them to a .panel, showing both a default and a .dark version.
    একটি সাধারণ light/dark থিম ভ্যারিয়েবল জোড়া (--bg, --text) বানিয়ে একটি .panel-এ প্রয়োগ করুন, ডিফল্ট ও .dark — দুটি ভার্সনই দেখান।
    ✨ Show Answer (উত্তর দেখুন)
    ans5.html
    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><title>Panel Theme</title></head>
    <body>
      <div class="panel">Light panel</div>
      <div class="panel dark">Dark panel</div>
    </body>
    </html>
    style.css
    :root {
      --bg: #ffffff;
      --text: #1a1a1a;
    }
    .panel {
      background: var(--bg);
      color: var(--text);
      padding: 14px;
      margin-bottom: 8px;
      font-family: sans-serif;
    }
    .panel.dark {
      --bg: #0f172a;
      --text: #e2e8f0;
    }

Summary — Module 20

CSS custom properties (--name: value;), read with var(--name) and an optional fallback, let you define a value once and reuse it everywhere. Scoping a redefinition to :root makes it global; scoping it to a class makes it local — and that local override is the entire mechanism behind theming and dark mode.

CSS custom property (--name: value;), যা var(--name) ও ঐচ্ছিক fallback দিয়ে পড়া হয়, একটি মান একবার সংজ্ঞায়িত করে সর্বত্র পুনর্ব্যবহার করতে দেয়। :root-এ পুনর্সংজ্ঞা দিলে তা গ্লোবাল হয়; ক্লাসে দিলে তা লোকাল হয় — আর এই লোকাল override-ই থিমিং ও dark mode-এর পুরো প্রক্রিয়া।

Next Module → Transitions & Animations — এমন মুভমেন্ট যা ইচ্ছাকৃত মনে হয়, গিমিক নয়।