๐ฆ Understanding CSS Variables and Functions
CSS Variables allow you to store values (like colors, sizes, fonts) in reusable variables directly in your CSS.
๐น Key Concepts
Custom properties start with
โVariables are defined using standard CSS syntax
Scoped to elements (can be global or local)
Accessed using the
var()functionUseful for maintainable and scalable design systems
๐น Defining Global Variables and Using CSS Variable
Global variables are usually defined inside the :root selector to be available across the entire document.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>CSS Variables Example</title>
<style>
.infographic-cssvars {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
box-sizing: border-box;
margin: 0 auto;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background: var(--paper);
color: var(--ink);
border-radius: 14px;
overflow: hidden;
}
.infographic-cssvars[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
}
.cv-inner { padding: 0.5rem; }
.cv-layout { display: flex; flex-direction: column; gap: 1.5rem; }
.cv-code-wrap {
background: #0b0b0b;
border: 1px solid #2a2a2a;
border-radius: 10px;
overflow: hidden;
}
.cv-filetabs {
display: flex;
background: #161616;
border-bottom: 1px solid #2a2a2a;
}
.cv-filetab {
border: none;
background: transparent;
color: #8a8a8a;
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
font-size: 0.78rem;
font-weight: 700;
padding: 0.6rem 1rem;
cursor: pointer;
border-bottom: 2px solid transparent;
transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}
.cv-filetab:hover { color: #e5e5e5; }
.cv-filetab.cv-tab-on {
color: #ffffff;
border-bottom-color: #5b8def;
background: #0b0b0b;
}
.cv-code {
padding: 1rem 1.8rem 1rem 0.9rem;
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
font-size: 0.8rem;
line-height: 1.85;
overflow-x: auto;
}
.cv-codepane { display: none; }
.cv-codepane.cv-pane-on { display: block; }
.cv-line { display: block; white-space: pre; color: #8a8a8a; padding: 0.05rem 0.4rem; border-radius: 5px; }
.cv-line.cv-active-main { background: rgba(52,152,219,0.18); box-shadow: inset 3px 0 0 #3498db; color: #ffffff; }
.cv-line.cv-active-text { background: rgba(150,150,150,0.18); box-shadow: inset 3px 0 0 #999; color: #ffffff; }
.cv-line.cv-active-pad { background: rgba(230,126,34,0.18); box-shadow: inset 3px 0 0 #e67e22; color: #ffffff; }
.cv-tag { color: #60a5fa; font-weight: 700; }
.cv-attr { color: #f2b96b; }
.cv-str { color: #9ece6a; }
.cv-sel { color: #f472b6; font-weight: 700; }
.cv-prop { color: #c586c0; }
.cv-val { color: #ce9178; }
.cv-com { color: #6a6a6a; font-style: italic; }
.cv-swatch {
display: inline-block;
width: 0.7em;
height: 0.7em;
border-radius: 3px;
margin-left: 0.3em;
vertical-align: middle;
border: 1px solid rgba(255,255,255,0.3);
}
.cv-browser {
border: 1px solid var(--line);
border-radius: 10px;
overflow: hidden;
background: var(--paper);
}
.cv-browser-bar {
background: var(--paper-alt);
padding: 0.5rem 0.7rem;
display: flex;
align-items: center;
gap: 0.5rem;
border-bottom: 1px solid var(--line);
}
.cv-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--line); }
.cv-tab {
background: var(--paper);
border: 1px solid var(--line);
border-bottom: none;
border-radius: 6px 6px 0 0;
font-size: 0.72rem;
color: var(--ink-soft);
padding: 0.25rem 0.6rem;
}
.cv-urlrow {
background: var(--paper-alt);
padding: 0.35rem 0.7rem 0.6rem;
font-size: 0.72rem;
color: var(--ink-soft);
font-family: "SFMono-Regular", Consolas, monospace;
}
.cv-controlrow {
background: var(--paper-alt);
padding: 0.6rem 0.7rem 0.8rem;
display: flex;
align-items: center;
gap: 1.1rem;
flex-wrap: wrap;
border-top: 1px solid var(--line);
}
.cv-control {
display: flex;
align-items: center;
gap: 0.4rem;
}
.cv-control-label {
font-size: 0.7rem;
color: var(--ink-soft);
font-family: "SFMono-Regular", Consolas, monospace;
white-space: nowrap;
}
.cv-color-input {
width: 26px;
height: 26px;
border: 1px solid var(--line);
border-radius: 6px;
padding: 0;
cursor: pointer;
background: none;
}
.cv-range-input {
width: 90px;
accent-color: var(--accent);
cursor: pointer;
}
.cv-range-readout {
font-size: 0.7rem;
color: var(--ink);
font-weight: 700;
font-family: "SFMono-Regular", Consolas, monospace;
min-width: 34px;
}
.cv-screen {
padding: 1.4rem;
font-family: sans-serif;
transition: background-color 0.15s ease, padding 0.15s ease, color 0.15s ease;
}
.cv-out-h1 {
margin: 0 0 0.6rem 0;
transition: color 0.15s ease;
}
.cv-out-p {
margin: 0 0 0.8rem 0;
transition: padding 0.15s ease, color 0.15s ease;
}
.cv-out-button {
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 0.9rem;
transition: background-color 0.15s ease, padding 0.15s ease;
}
.cv-note {
font-size: 0.82rem;
color: var(--ink-soft);
padding: 0 0.2rem;
}
.cv-note strong { color: var(--ink); }
.cv-note code {
font-family: "SFMono-Regular", Consolas, monospace;
background: var(--paper-alt);
padding: 0.05rem 0.3rem;
border-radius: 4px;
}
</style>
</head>
<body>
<div class="infographic-cssvars" id="cv-root">
<div class="cv-inner">
<div class="cv-layout">
<div class="cv-code-wrap">
<div class="cv-filetabs">
<button class="cv-filetab cv-tab-on" id="cv-tab-html">index.html</button>
<button class="cv-filetab" id="cv-tab-css">styles.css</button>
</div>
<div class="cv-code">
<div class="cv-codepane cv-pane-on" id="cv-pane-html">
<span class="cv-line"><!<span class="cv-tag">DOCTYPE</span> <span class="cv-attr">html</span>></span>
<span class="cv-line"><<span class="cv-tag">html</span> <span class="cv-attr">lang</span>=<span class="cv-str">"en"</span>></span>
<span class="cv-line"> <<span class="cv-tag">head</span>></span>
<span class="cv-line"> <<span class="cv-tag">meta</span> <span class="cv-attr">charset</span>=<span class="cv-str">"UTF-8"</span> /></span>
<span class="cv-line"> <<span class="cv-tag">meta</span> <span class="cv-attr">name</span>=<span class="cv-str">"viewport"</span> <span class="cv-attr">content</span>=<span class="cv-str">"width=device-width, initial-scale=1.0"</span> /></span>
<span class="cv-line"> <<span class="cv-tag">title</span>>CSS Variables Example</<span class="cv-tag">title</span>></span>
<span class="cv-line"> <<span class="cv-tag">link</span> <span class="cv-attr">rel</span>=<span class="cv-str">"stylesheet"</span> <span class="cv-attr">href</span>=<span class="cv-str">"styles.css"</span> /></span>
<span class="cv-line"> </<span class="cv-tag">head</span>></span>
<span class="cv-line"> <<span class="cv-tag">body</span>></span>
<span class="cv-line cv-clickable" id="cv-line-h1"> <<span class="cv-tag">h1</span>>Hello CSS Variables</<span class="cv-tag">h1</span>></span>
<span class="cv-line cv-clickable" id="cv-line-p"> <<span class="cv-tag">p</span>>This text uses a custom text color and padding.</<span class="cv-tag">p</span>></span>
<span class="cv-line cv-clickable" id="cv-line-button"> <<span class="cv-tag">button</span>>Click Me</<span class="cv-tag">button</span>></span>
<span class="cv-line"> </<span class="cv-tag">body</span>></span>
<span class="cv-line"></<span class="cv-tag">html</span>></span>
</div>
<div class="cv-codepane" id="cv-pane-css">
<span class="cv-line"><span class="cv-com">/* Defining the global variables */</span></span>
<span class="cv-line"><span class="cv-sel">:root</span> {</span>
<span class="cv-line cv-active-main" id="cv-line-var-main"> <span class="cv-prop">--main-color</span>: <span class="cv-val" id="cv-code-main-color">#3498db</span>;<span class="cv-swatch" id="cv-swatch-main" style="background:#3498db;"></span></span>
<span class="cv-line cv-active-text" id="cv-line-var-text"> <span class="cv-prop">--text-color</span>: <span class="cv-val" id="cv-code-text-color">#333</span>;<span class="cv-swatch" id="cv-swatch-text" style="background:#333;"></span></span>
<span class="cv-line cv-active-pad" id="cv-line-var-pad"> <span class="cv-prop">--padding</span>: <span class="cv-val" id="cv-code-padding">1rem</span>;</span>
<span class="cv-line">}</span>
<span class="cv-line"></span>
<span class="cv-line"><span class="cv-com">/* Accessing the global variables */</span></span>
<span class="cv-line"><span class="cv-sel">body</span> {</span>
<span class="cv-line"> <span class="cv-prop">font-family</span>: <span class="cv-val">sans-serif</span>;</span>
<span class="cv-line"> <span class="cv-prop">background-color</span>: <span class="cv-val">#f9f9f9</span>;</span>
<span class="cv-line cv-active-pad"> <span class="cv-prop">padding</span>: <span class="cv-val">var(--padding)</span>;</span>
<span class="cv-line cv-active-text"> <span class="cv-prop">color</span>: <span class="cv-val">var(--text-color)</span>;</span>
<span class="cv-line">}</span>
<span class="cv-line"></span>
<span class="cv-line"><span class="cv-sel">h1</span> {</span>
<span class="cv-line cv-active-main"> <span class="cv-prop">color</span>: <span class="cv-val">var(--main-color)</span>;</span>
<span class="cv-line">}</span>
<span class="cv-line"></span>
<span class="cv-line"><span class="cv-sel">p</span> {</span>
<span class="cv-line cv-active-pad"> <span class="cv-prop">padding</span>: <span class="cv-val">var(--padding)</span>;</span>
<span class="cv-line cv-active-text"> <span class="cv-prop">color</span>: <span class="cv-val">var(--text-color)</span>;</span>
<span class="cv-line">}</span>
<span class="cv-line"></span>
<span class="cv-line"><span class="cv-sel">button</span> {</span>
<span class="cv-line cv-active-main"> <span class="cv-prop">background-color</span>: <span class="cv-val">var(--main-color)</span>;</span>
<span class="cv-line"> <span class="cv-prop">color</span>: <span class="cv-val">white</span>;</span>
<span class="cv-line cv-active-pad"> <span class="cv-prop">padding</span>: <span class="cv-val">var(--padding)</span>;</span>
<span class="cv-line"> <span class="cv-prop">border</span>: <span class="cv-val">none</span>;</span>
<span class="cv-line"> <span class="cv-prop">border-radius</span>: <span class="cv-val">6px</span>;</span>
<span class="cv-line"> <span class="cv-prop">cursor</span>: <span class="cv-val">pointer</span>;</span>
<span class="cv-line">}</span>
</div>
</div>
</div>
<div class="cv-browser">
<div class="cv-browser-bar">
<span class="cv-dot"></span><span class="cv-dot"></span><span class="cv-dot"></span>
<div class="cv-tab">๐ CSS Variables Example</div>
</div>
<div class="cv-urlrow">127.0.0.1:5500/index.html</div>
<div class="cv-screen" id="cv-screen">
<h1 class="cv-out-h1" id="cv-out-h1">Hello CSS Variables</h1>
<p class="cv-out-p" id="cv-out-p">This text uses a custom text color and padding.</p>
<button class="cv-out-button" id="cv-out-button">Click Me</button>
</div>
<div class="cv-controlrow">
<div class="cv-control">
<span class="cv-control-label">--main-color</span>
<input type="color" class="cv-color-input" id="cv-input-main" value="#3498db">
</div>
<div class="cv-control">
<span class="cv-control-label">--text-color</span>
<input type="color" class="cv-color-input" id="cv-input-text" value="#333333">
</div>
<div class="cv-control">
<span class="cv-control-label">--padding</span>
<input type="range" class="cv-range-input" id="cv-input-padding" min="0" max="3" step="0.1" value="1">
<span class="cv-range-readout" id="cv-readout-padding">1rem</span>
</div>
</div>
</div>
<div class="cv-note" id="cv-note">
Change any control above โ every element that reads <code>var(--main-color)</code>, <code>var(--text-color)</code>, or <code>var(--padding)</code> updates at once, because they all point back to the single definition in <code>:root</code>.
</div>
</div>
</div>
</div>
<script>
(function () {
const wrapper = document.getElementById('cv-root');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
})();
(function () {
const tabHtml = document.getElementById('cv-tab-html');
const tabCss = document.getElementById('cv-tab-css');
const paneHtml = document.getElementById('cv-pane-html');
const paneCss = document.getElementById('cv-pane-css');
tabHtml.addEventListener('click', () => {
tabHtml.classList.add('cv-tab-on');
tabCss.classList.remove('cv-tab-on');
paneHtml.classList.add('cv-pane-on');
paneCss.classList.remove('cv-pane-on');
});
tabCss.addEventListener('click', () => {
tabCss.classList.add('cv-tab-on');
tabHtml.classList.remove('cv-tab-on');
paneCss.classList.add('cv-pane-on');
paneHtml.classList.remove('cv-pane-on');
});
const screen = document.getElementById('cv-screen');
const outH1 = document.getElementById('cv-out-h1');
const outP = document.getElementById('cv-out-p');
const outButton = document.getElementById('cv-out-button');
const inputMain = document.getElementById('cv-input-main');
const inputText = document.getElementById('cv-input-text');
const inputPadding = document.getElementById('cv-input-padding');
const readoutPadding = document.getElementById('cv-readout-padding');
const codeMain = document.getElementById('cv-code-main-color');
const codeText = document.getElementById('cv-code-text-color');
const codePadding = document.getElementById('cv-code-padding');
const swatchMain = document.getElementById('cv-swatch-main');
const swatchText = document.getElementById('cv-swatch-text');
const note = document.getElementById('cv-note');
function applyAll() {
const mainColor = inputMain.value;
const textColor = inputText.value;
const pad = parseFloat(inputPadding.value).toFixed(1) + 'rem';
screen.style.setProperty('--main-color', mainColor);
screen.style.setProperty('--text-color', textColor);
screen.style.setProperty('--padding', pad);
outH1.style.color = mainColor;
outP.style.color = textColor;
outP.style.padding = pad;
outButton.style.backgroundColor = mainColor;
outButton.style.padding = pad;
screen.style.padding = pad;
screen.style.color = textColor;
codeMain.textContent = mainColor;
codeText.textContent = textColor;
codePadding.textContent = pad;
swatchMain.style.background = mainColor;
swatchText.style.background = textColor;
readoutPadding.textContent = pad;
}
inputMain.addEventListener('input', () => {
applyAll();
note.innerHTML = 'Changing <code>--main-color</code> updates the <code>h1</code> text and the button background at once โ both reference <code>var(--main-color)</code> instead of repeating the hex value.';
tabCss.click();
});
inputText.addEventListener('input', () => {
applyAll();
note.innerHTML = 'Changing <code>--text-color</code> updates <code>body</code> and <code>p</code> together โ the paragraph never sets its own color, it just inherits and references the variable.';
tabCss.click();
});
inputPadding.addEventListener('input', () => {
applyAll();
note.innerHTML = 'Changing <code>--padding</code> updates spacing on <code>body</code>, <code>p</code>, and <code>button</code> simultaneously โ one number, three places at once.';
tabCss.click();
});
applyAll();
})();
</script>
</body>
</html>๐น Fallback Values
You can provide a fallback if the variable is not defined:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>CSS Variables: Fallback Values</title>
<style>
.infographic-cssfallback {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
box-sizing: border-box;
margin: 0 auto;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background: var(--paper);
color: var(--ink);
border-radius: 14px;
overflow: hidden;
}
.infographic-cssfallback[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
}
.cf-inner { padding: 0.5rem; }
.cf-layout { display: flex; flex-direction: column; gap: 1.5rem; }
.cf-code-wrap {
background: #0b0b0b;
border: 1px solid #2a2a2a;
border-radius: 10px;
overflow: hidden;
}
.cf-filetabs {
display: flex;
background: #161616;
border-bottom: 1px solid #2a2a2a;
}
.cf-filetab {
border: none;
background: transparent;
color: #8a8a8a;
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
font-size: 0.78rem;
font-weight: 700;
padding: 0.6rem 1rem;
cursor: pointer;
border-bottom: 2px solid transparent;
transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}
.cf-filetab:hover { color: #e5e5e5; }
.cf-filetab.cf-tab-on {
color: #ffffff;
border-bottom-color: #5b8def;
background: #0b0b0b;
}
.cf-code {
padding: 1rem 1.8rem 1rem 0.9rem;
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
font-size: 0.8rem;
line-height: 1.85;
overflow-x: auto;
}
.cf-codepane { display: none; }
.cf-codepane.cf-pane-on { display: block; }
.cf-line { display: block; white-space: pre; color: #8a8a8a; padding: 0.05rem 0.4rem; border-radius: 5px; }
.cf-line.cf-active { background: #1c2333; box-shadow: inset 3px 0 0 #5b8def; color: #ffffff; }
.cf-tag { color: #60a5fa; font-weight: 700; }
.cf-attr { color: #f2b96b; }
.cf-str { color: #9ece6a; }
.cf-sel { color: #f472b6; font-weight: 700; }
.cf-prop { color: #c586c0; }
.cf-val { color: #ce9178; }
.cf-com { color: #6a6a6a; font-style: italic; }
.cf-com-def { color: #7a8a5c; font-style: italic; }
.cf-swatch {
display: inline-block;
width: 0.7em;
height: 0.7em;
border-radius: 3px;
margin-left: 0.3em;
vertical-align: middle;
border: 1px solid rgba(255,255,255,0.3);
}
.cf-browser {
border: 1px solid var(--line);
border-radius: 10px;
overflow: hidden;
background: var(--paper);
}
.cf-browser-bar {
background: var(--paper-alt);
padding: 0.5rem 0.7rem;
display: flex;
align-items: center;
gap: 0.5rem;
border-bottom: 1px solid var(--line);
}
.cf-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--line); }
.cf-tab {
background: var(--paper);
border: 1px solid var(--line);
border-bottom: none;
border-radius: 6px 6px 0 0;
font-size: 0.72rem;
color: var(--ink-soft);
padding: 0.25rem 0.6rem;
}
.cf-urlrow {
background: var(--paper-alt);
padding: 0.35rem 0.7rem 0.6rem;
font-size: 0.72rem;
color: var(--ink-soft);
font-family: "SFMono-Regular", Consolas, monospace;
}
.cf-controlrow {
background: var(--paper-alt);
padding: 0.6rem 0.7rem 0.8rem;
display: flex;
align-items: center;
gap: 1rem;
flex-wrap: wrap;
border-top: 1px solid var(--line);
}
.cf-control-label {
font-size: 0.72rem;
color: var(--ink-soft);
font-family: "SFMono-Regular", Consolas, monospace;
white-space: nowrap;
}
.cf-toggle {
position: relative;
width: 40px;
height: 22px;
border-radius: 999px;
border: none;
background: var(--line);
cursor: pointer;
padding: 0;
transition: background 0.2s ease;
flex-shrink: 0;
}
.cf-toggle::after {
content: "";
position: absolute;
top: 2px;
left: 2px;
width: 18px;
height: 18px;
border-radius: 50%;
background: #ffffff;
transition: transform 0.2s ease;
box-shadow: 0 1px 2px rgba(0,0,0,0.25);
}
.cf-toggle.cf-on { background: var(--accent); }
.cf-toggle.cf-on::after { transform: translateX(18px); }
.cf-color-input {
width: 26px;
height: 26px;
border: 1px solid var(--line);
border-radius: 6px;
padding: 0;
cursor: pointer;
background: none;
transition: opacity 0.15s ease;
}
.cf-color-input:disabled { opacity: 0.35; cursor: not-allowed; }
.cf-screen {
padding: 2rem 1.4rem;
font-family: sans-serif;
background-color: #f9f9f9;
}
.cf-out-h1 {
color: #000000;
font-size: 2rem;
margin: 0 0 0.6rem 0;
transition: color 0.15s ease;
}
.cf-out-p {
color: #333;
margin: 0;
font-size: 0.9rem;
}
.cf-note {
font-size: 0.82rem;
color: var(--ink-soft);
padding: 0 0.2rem;
}
.cf-note strong { color: var(--ink); }
.cf-note code {
font-family: "SFMono-Regular", Consolas, monospace;
background: var(--paper-alt);
padding: 0.05rem 0.3rem;
border-radius: 4px;
}
</style>
</head>
<body>
<div class="infographic-cssfallback" id="cf-root">
<div class="cf-inner">
<div class="cf-layout">
<div class="cf-code-wrap">
<div class="cf-filetabs">
<button class="cf-filetab cf-tab-on" id="cf-tab-html">index.html</button>
<button class="cf-filetab" id="cf-tab-css">styles.css</button>
</div>
<div class="cf-code">
<div class="cf-codepane cf-pane-on" id="cf-pane-html">
<span class="cf-line"><!<span class="cf-tag">DOCTYPE</span> <span class="cf-attr">html</span>></span>
<span class="cf-line"><<span class="cf-tag">html</span> <span class="cf-attr">lang</span>=<span class="cf-str">"en"</span>></span>
<span class="cf-line"> <<span class="cf-tag">head</span>></span>
<span class="cf-line"> <<span class="cf-tag">meta</span> <span class="cf-attr">charset</span>=<span class="cf-str">"UTF-8"</span> /></span>
<span class="cf-line"> <<span class="cf-tag">meta</span> <span class="cf-attr">name</span>=<span class="cf-str">"viewport"</span> <span class="cf-attr">content</span>=<span class="cf-str">"width=device-width, initial-scale=1.0"</span> /></span>
<span class="cf-line"> <<span class="cf-tag">title</span>>Accent Color Example</<span class="cf-tag">title</span>></span>
<span class="cf-line"> <<span class="cf-tag">link</span> <span class="cf-attr">rel</span>=<span class="cf-str">"stylesheet"</span> <span class="cf-attr">href</span>=<span class="cf-str">"styles.css"</span> /></span>
<span class="cf-line"> </<span class="cf-tag">head</span>></span>
<span class="cf-line"> <<span class="cf-tag">body</span>></span>
<span class="cf-line"> <<span class="cf-tag">h1</span>>Hello, CSS Variables!</<span class="cf-tag">h1</span>></span>
<span class="cf-line"> <<span class="cf-tag">p</span>>This heading uses an accent color with a fallback.</<span class="cf-tag">p</span>></span>
<span class="cf-line"> </<span class="cf-tag">body</span>></span>
<span class="cf-line"></<span class="cf-tag">html</span>></span>
</div>
<div class="cf-codepane" id="cf-pane-css">
<span class="cf-line"><span class="cf-com">/* Optional: Define the variable */</span></span>
<span class="cf-line"><span class="cf-sel">:root</span> {</span>
<span class="cf-line" id="cf-var-comment"><span class="cf-com"> /* Uncomment this line to define the custom accent color */</span></span>
<span class="cf-line cf-active" id="cf-var-line"><span class="cf-com-def" id="cf-var-text"> /* --accent-color: crimson; */</span><span class="cf-swatch" id="cf-swatch" style="background:#000; display:none;"></span></span>
<span class="cf-line">}</span>
<span class="cf-line"></span>
<span class="cf-line cf-active" id="cf-h1-line"><span class="cf-sel">h1</span> {</span>
<span class="cf-line cf-active" id="cf-h1-color-line"> <span class="cf-prop">color</span>: <span class="cf-val" id="cf-var-call">var(--accent-color, #000)</span>; <span class="cf-com">/* fallback to black if not defined */</span></span>
<span class="cf-line"> <span class="cf-prop">font-family</span>: <span class="cf-val">sans-serif</span>;</span>
<span class="cf-line"> <span class="cf-prop">font-size</span>: <span class="cf-val">2.5rem</span>;</span>
<span class="cf-line"> <span class="cf-prop">margin-bottom</span>: <span class="cf-val">1rem</span>;</span>
<span class="cf-line">}</span>
<span class="cf-line"></span>
<span class="cf-line"><span class="cf-sel">body</span> {</span>
<span class="cf-line"> <span class="cf-prop">padding</span>: <span class="cf-val">2rem</span>;</span>
<span class="cf-line"> <span class="cf-prop">background-color</span>: <span class="cf-val">#f9f9f9</span>;</span>
<span class="cf-line">}</span>
</div>
</div>
</div>
<div class="cf-browser">
<div class="cf-browser-bar">
<span class="cf-dot"></span><span class="cf-dot"></span><span class="cf-dot"></span>
<div class="cf-tab">๐ Accent Color Example</div>
</div>
<div class="cf-urlrow">127.0.0.1:5500/index.html</div>
<div class="cf-screen">
<h1 class="cf-out-h1" id="cf-out-h1">Hello, CSS Variables!</h1>
<p class="cf-out-p">This heading uses an accent color with a fallback.</p>
</div>
<div class="cf-controlrow">
<span class="cf-control-label">define --accent-color:</span>
<button class="cf-toggle" id="cf-toggle" aria-pressed="false" aria-label="Toggle --accent-color definition"></button>
<input type="color" class="cf-color-input" id="cf-color-input" value="#dc143c" disabled>
</div>
</div>
<div class="cf-note" id="cf-note">
<code>var(--accent-color, #000)</code> means: use <code>--accent-color</code> if it's defined, otherwise fall back to <code>#000</code>. Right now the variable is commented out in <code>:root</code>, so <strong>black</strong> wins.
</div>
</div>
</div>
</div>
<script>
(function () {
const wrapper = document.getElementById('cf-root');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
})();
(function () {
const tabHtml = document.getElementById('cf-tab-html');
const tabCss = document.getElementById('cf-tab-css');
const paneHtml = document.getElementById('cf-pane-html');
const paneCss = document.getElementById('cf-pane-css');
tabHtml.addEventListener('click', () => {
tabHtml.classList.add('cf-tab-on');
tabCss.classList.remove('cf-tab-on');
paneHtml.classList.add('cf-pane-on');
paneCss.classList.remove('cf-pane-on');
});
tabCss.addEventListener('click', () => {
tabCss.classList.add('cf-tab-on');
tabHtml.classList.remove('cf-tab-on');
paneCss.classList.add('cf-pane-on');
paneHtml.classList.remove('cf-pane-on');
});
const toggle = document.getElementById('cf-toggle');
const colorInput = document.getElementById('cf-color-input');
const outH1 = document.getElementById('cf-out-h1');
const varText = document.getElementById('cf-var-text');
const swatch = document.getElementById('cf-swatch');
const note = document.getElementById('cf-note');
let defined = false;
function render() {
const color = colorInput.value;
if (defined) {
varText.textContent = ' --accent-color: ' + color + ';';
varText.className = '';
swatch.style.display = 'inline-block';
swatch.style.background = color;
outH1.style.color = color;
note.innerHTML = '<code>--accent-color</code> is now defined in <code>:root</code>, so <code>var(--accent-color, #000)</code> uses it โ the fallback <code>#000</code> is ignored whenever the variable exists.';
} else {
varText.textContent = ' /* --accent-color: ' + color + '; */';
varText.className = 'cf-com-def';
swatch.style.display = 'none';
outH1.style.color = '#000000';
note.innerHTML = '<code>var(--accent-color, #000)</code> means: use <code>--accent-color</code> if it\'s defined, otherwise fall back to <code>#000</code>. Right now the variable is commented out in <code>:root</code>, so <strong>black</strong> wins.';
}
tabCss.click();
}
toggle.addEventListener('click', () => {
defined = !defined;
toggle.classList.toggle('cf-on', defined);
toggle.setAttribute('aria-pressed', String(defined));
colorInput.disabled = !defined;
render();
});
colorInput.addEventListener('input', () => {
if (defined) render();
});
})();
</script>
</body>
</html>๐น Overriding Variables with Inheritance
You can redefine a variable in a more specific context to override its value:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>CSS Variables: Scoped Overrides</title>
<style>
.infographic-cssscope {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
box-sizing: border-box;
margin: 0 auto;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background: var(--paper);
color: var(--ink);
border-radius: 14px;
overflow: hidden;
}
.infographic-cssscope[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
}
.cs-inner { padding: 0.5rem; }
.cs-layout { display: flex; flex-direction: column; gap: 1.5rem; }
.cs-code-wrap {
background: #0b0b0b;
border: 1px solid #2a2a2a;
border-radius: 10px;
overflow: hidden;
}
.cs-filetabs {
display: flex;
background: #161616;
border-bottom: 1px solid #2a2a2a;
}
.cs-filetab {
border: none;
background: transparent;
color: #8a8a8a;
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
font-size: 0.78rem;
font-weight: 700;
padding: 0.6rem 1rem;
cursor: pointer;
border-bottom: 2px solid transparent;
transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}
.cs-filetab:hover { color: #e5e5e5; }
.cs-filetab.cs-tab-on {
color: #ffffff;
border-bottom-color: #5b8def;
background: #0b0b0b;
}
.cs-code {
padding: 1rem 1.8rem 1rem 0.9rem;
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
font-size: 0.8rem;
line-height: 1.85;
overflow-x: auto;
}
.cs-codepane { display: none; }
.cs-codepane.cs-pane-on { display: block; }
.cs-line { display: block; white-space: pre; color: #8a8a8a; padding: 0.05rem 0.4rem; border-radius: 5px; }
.cs-line.cs-active { background: #1c2333; box-shadow: inset 3px 0 0 #5b8def; color: #ffffff; }
.cs-line.cs-dimmed { opacity: 0.4; }
.cs-tag { color: #60a5fa; font-weight: 700; }
.cs-attr { color: #f2b96b; }
.cs-str { color: #9ece6a; }
.cs-sel { color: #f472b6; font-weight: 700; }
.cs-prop { color: #c586c0; }
.cs-val { color: #ce9178; }
.cs-com { color: #6a6a6a; font-style: italic; }
.cs-swatch {
display: inline-block;
width: 0.7em;
height: 0.7em;
border-radius: 3px;
margin-left: 0.3em;
vertical-align: middle;
border: 1px solid rgba(255,255,255,0.3);
}
.cs-browser {
border: 1px solid var(--line);
border-radius: 10px;
overflow: hidden;
background: var(--paper);
}
.cs-browser-bar {
background: var(--paper-alt);
padding: 0.5rem 0.7rem;
display: flex;
align-items: center;
gap: 0.5rem;
border-bottom: 1px solid var(--line);
}
.cs-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--line); }
.cs-tab {
background: var(--paper);
border: 1px solid var(--line);
border-bottom: none;
border-radius: 6px 6px 0 0;
font-size: 0.72rem;
color: var(--ink-soft);
padding: 0.25rem 0.6rem;
}
.cs-urlrow {
background: var(--paper-alt);
padding: 0.35rem 0.7rem 0.6rem;
font-size: 0.72rem;
color: var(--ink-soft);
font-family: "SFMono-Regular", Consolas, monospace;
}
.cs-controlrow {
background: var(--paper-alt);
padding: 0.6rem 0.7rem 0.8rem;
display: flex;
align-items: center;
gap: 0.6rem;
border-top: 1px solid var(--line);
}
.cs-control-label {
font-size: 0.72rem;
color: var(--ink-soft);
font-family: "SFMono-Regular", Consolas, monospace;
}
.cs-toggle {
position: relative;
width: 40px;
height: 22px;
border-radius: 999px;
border: none;
background: var(--line);
cursor: pointer;
padding: 0;
transition: background 0.2s ease;
flex-shrink: 0;
}
.cs-toggle::after {
content: "";
position: absolute;
top: 2px;
left: 2px;
width: 18px;
height: 18px;
border-radius: 50%;
background: #ffffff;
transition: transform 0.2s ease;
box-shadow: 0 1px 2px rgba(0,0,0,0.25);
}
.cs-toggle.cs-on { background: var(--accent); }
.cs-toggle.cs-on::after { transform: translateX(18px); }
.cs-screen {
padding: 1.4rem;
background: #f5f5f5;
}
.cs-out-section {
padding: 2rem 1.2rem;
border-radius: 8px;
text-align: center;
font-family: sans-serif;
font-weight: 600;
background-color: white;
color: #1a1a1a;
border: 1px solid #ddd;
transition: background-color 0.2s ease, color 0.2s ease;
}
.cs-out-section.cs-out-dark {
background-color: black;
color: white;
border-color: #333;
}
.cs-note {
font-size: 0.82rem;
color: var(--ink-soft);
padding: 0 0.2rem;
}
.cs-note strong { color: var(--ink); }
.cs-note code {
font-family: "SFMono-Regular", Consolas, monospace;
background: var(--paper-alt);
padding: 0.05rem 0.3rem;
border-radius: 4px;
}
</style>
</head>
<body>
<div class="infographic-cssscope" id="cs-root">
<div class="cs-inner">
<div class="cs-layout">
<div class="cs-code-wrap">
<div class="cs-filetabs">
<button class="cs-filetab cs-tab-on" id="cs-tab-html">index.html</button>
<button class="cs-filetab" id="cs-tab-css">style.css</button>
</div>
<div class="cs-code">
<div class="cs-codepane cs-pane-on" id="cs-pane-html">
<span class="cs-line" id="cs-html-line"><<span class="cs-tag">section</span> <span class="cs-attr">class</span>=<span class="cs-str" id="cs-html-class">"dark-mode"</span>></span>
<span class="cs-line"> This section has a dark background</span>
<span class="cs-line"></<span class="cs-tag">section</span>></span>
</div>
<div class="cs-codepane" id="cs-pane-css">
<span class="cs-line"><span class="cs-sel">:root</span> {</span>
<span class="cs-line" id="cs-line-root-var"> <span class="cs-prop">--theme-bg</span>: <span class="cs-val">white</span>; <span class="cs-com">/* default light background */</span><span class="cs-swatch" style="background:#fff; border-color:#999;"></span></span>
<span class="cs-line">}</span>
<span class="cs-line"></span>
<span class="cs-line cs-active" id="cs-line-darkmode-sel"><span class="cs-sel">.dark-mode</span> {</span>
<span class="cs-line cs-active" id="cs-line-darkmode-var"> <span class="cs-prop">--theme-bg</span>: <span class="cs-val">black</span>; <span class="cs-com">/* override to dark background */</span><span class="cs-swatch" style="background:#000;"></span></span>
<span class="cs-line cs-active" id="cs-line-darkmode-close">}</span>
<span class="cs-line"></span>
<span class="cs-line"><span class="cs-sel">section</span> {</span>
<span class="cs-line"> <span class="cs-prop">background-color</span>: <span class="cs-val">var(--theme-bg)</span>; <span class="cs-com">/* resolves per-scope */</span></span>
<span class="cs-line">}</span>
</div>
</div>
</div>
<div class="cs-browser">
<div class="cs-browser-bar">
<span class="cs-dot"></span><span class="cs-dot"></span><span class="cs-dot"></span>
<div class="cs-tab">๐ Scoped Variables</div>
</div>
<div class="cs-urlrow">127.0.0.1:5500/index.html</div>
<div class="cs-screen">
<div class="cs-out-section cs-out-dark" id="cs-out-section">This section has a dark background</div>
</div>
<div class="cs-controlrow">
<span class="cs-control-label">class="dark-mode":</span>
<button class="cs-toggle cs-on" id="cs-toggle" aria-pressed="true" aria-label="Toggle dark-mode class"></button>
</div>
</div>
<div class="cs-note" id="cs-note">
<code>--theme-bg</code> is defined twice: <strong>white</strong> globally on <code>:root</code>, <strong>black</strong> locally on <code>.dark-mode</code>. Since the section has that class, the closer, more specific definition wins โ same variable name, different value depending on scope.
</div>
</div>
</div>
</div>
<script>
(function () {
const wrapper = document.getElementById('cs-root');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
})();
(function () {
const tabHtml = document.getElementById('cs-tab-html');
const tabCss = document.getElementById('cs-tab-css');
const paneHtml = document.getElementById('cs-pane-html');
const paneCss = document.getElementById('cs-pane-css');
tabHtml.addEventListener('click', () => {
tabHtml.classList.add('cs-tab-on');
tabCss.classList.remove('cs-tab-on');
paneHtml.classList.add('cs-pane-on');
paneCss.classList.remove('cs-pane-on');
});
tabCss.addEventListener('click', () => {
tabCss.classList.add('cs-tab-on');
tabHtml.classList.remove('cs-tab-on');
paneCss.classList.add('cs-pane-on');
paneHtml.classList.remove('cs-pane-on');
});
const toggle = document.getElementById('cs-toggle');
const section = document.getElementById('cs-out-section');
const htmlClass = document.getElementById('cs-html-class');
const darkLines = [
document.getElementById('cs-line-darkmode-sel'),
document.getElementById('cs-line-darkmode-var'),
document.getElementById('cs-line-darkmode-close')
];
const note = document.getElementById('cs-note');
let hasClass = true;
function render() {
section.classList.toggle('cs-out-dark', hasClass);
htmlClass.textContent = hasClass ? '"dark-mode"' : '""';
darkLines.forEach(l => {
l.classList.toggle('cs-active', hasClass);
l.classList.toggle('cs-dimmed', !hasClass);
});
note.innerHTML = hasClass
? '<code>--theme-bg</code> is defined twice: <strong>white</strong> globally on <code>:root</code>, <strong>black</strong> locally on <code>.dark-mode</code>. Since the section has that class, the closer, more specific definition wins.'
: 'Remove <code>class="dark-mode"</code> and the local override no longer applies โ <code>var(--theme-bg)</code> falls back through the cascade to the <code>:root</code> definition, <strong>white</strong>.';
tabCss.click();
}
toggle.addEventListener('click', () => {
hasClass = !hasClass;
toggle.classList.toggle('cs-on', hasClass);
toggle.setAttribute('aria-pressed', String(hasClass));
render();
});
})();
</script>
</body>
</html>๐ Explanation: ( Lets understand it as light and dark theme toggle)
:rootdefines the default value for the variable-theme-bg(used for the light theme).When
.dark-modeis added to a parent element like<section>, the-theme-bgis overridden toblack.The
sectionuses the variable withvar(--theme-bg)โ so it automatically picks the right value depending on the theme.
โ Summary of Benefits
Centralised control of styling values
Easier theme switching (e.g., light/dark modes)
More readable and maintainable CSS
Avoids repeating values in multiple places
๐ง CSS Functions
CSS functions are built-in methods that take arguments and return values to dynamically compute styles. They're used inside property values like width, transform, calc(), etc.
๐ง Common CSS Functions
1. ๐ข calc()
Used to perform mathematical operations.
width: calc(100% - 50px);โก๏ธ Calculates a value by combining units (%, px, em, etc.)
2. ๐จ var()
Accesses the value of a CSS custom property (variable).
--main-color: #3498db;
color: var(--main-color);3. ๐ rgb(), rgba(), hsl(), hsla()
Define color values using red/green/blue or hue/saturation/lightness.
background-color: rgba(255, 0, 0, 0.5);4. ๐ url()
Used to embed external resources (e.g., images, fonts).
background-image: url("hero.jpg");5. ๐ attr()
Used in content generation with pseudo-elements (limited support).
content: attr(data-label);6. ๐งฎ min(), max(), and clamp()
Useful for responsive design with fluid values.
width: min(90%, 500px);
font-size: clamp(1rem, 2vw, 2rem);min()โ Picks the smallest valuemax()โ Picks the largest valueclamp(min, preferred, max)โ Picks a value within a range
โจ Summary Table
Function | Purpose | Example |
|---|---|---|
| Math operations in CSS |
|
| Custom properties (variables) |
|
| Color in red/green/blue |
|
| External assets |
|
| Responsive scaling with limits |
|
| Inject attribute content |
|