Free tutorials & notes in Hindi & English · Clean code examples 🧰 Free PDF & Image Tools →
✨ Days 13–18 – Motion, UI & Professional CSS  ·  Day 16

Day 16: UI Components: Buttons, Cards, Navbar, Modal

⏱ 110 min📶 Intermediate🎯 100% self-study
Day 16 / 20

✅ Today you will learn

  • Think in components with variants and sizes
  • Buttons, badges, avatars, alerts
  • Cards, breadcrumbs and pagination
  • CSS-only tabs and a styled accordion
  • A dialog modal with backdrop and a toast notification

🏢 In the real world

In a real company you rarely style one page – you build a component library that every page reuses: one button style, one card, one alert. When the designer changes the button radius, it changes everywhere. This day gives you a mini design system you can copy into every client project, including your school ERP or billing app screens.

Buttons: one base, many variants

HTML + CSS
<style>
:root { --brand: #264de4; --brand-600: #1e40af; --ok: #15803d; --warn: #b45309; --err: #b91c1c; --ink: #0f172a; --muted: #64748b; --line: #e2e8f0; --r: 10px; }
* { box-sizing: border-box; }
.btn { display: inline-flex; align-items: center; gap: .4em; font: 600 .95rem system-ui; padding: .6em 1.1em; border-radius: var(--r); border: 1.5px solid transparent; cursor: pointer; text-decoration: none; transition: background-color .2s, transform .1s; margin: 4px; }
.btn:active { transform: translateY(1px); }
.btn:focus-visible { outline: 3px solid #f59e0b; outline-offset: 2px; }
.btn--primary { background: var(--brand); color: #fff; }
.btn--primary:hover { background: var(--brand-600); }
.btn--outline { border-color: var(--brand); color: var(--brand); background: #fff; }
.btn--ghost { color: var(--brand); background: transparent; }
.btn--danger { background: var(--err); color: #fff; }
.btn--sm { font-size: .8rem; }
.btn--lg { font-size: 1.1rem; padding: .75em 1.4em; }
.btn[disabled] { opacity: .5; pointer-events: none; }
</style>

<button class="btn btn--primary">Primary</button>
<button class="btn btn--outline">Outline</button>
<button class="btn btn--ghost">Ghost</button>
<button class="btn btn--danger">🗑 Delete</button><br>
<button class="btn btn--primary btn--sm">Small</button>
<button class="btn btn--primary btn--lg">Large</button>
<button class="btn btn--primary" disabled>Disabled</button>
▶  Base .btn + modifiers (--primary, --sm …) – the BEM idea you formalise tomorrow

Badges, avatars and alerts

HTML + CSS
<style>
:root { --brand: #264de4; --brand-600: #1e40af; --ok: #15803d; --warn: #b45309; --err: #b91c1c; --ink: #0f172a; --muted: #64748b; --line: #e2e8f0; --r: 10px; }
* { box-sizing: border-box; }
.badge { display: inline-block; padding: 2px 10px; border-radius: 99px; font: 700 .72rem system-ui; letter-spacing: .02em; margin: 2px; }
.badge--ok { background: #dcfce7; color: #166534; } .badge--warn { background: #fef3c7; color: #92400e; } .badge--err { background: #fee2e2; color: #991b1b; }
.avatars { display: flex; margin: 12px 0; }
.avatar { width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center; color: #fff; font: 700 14px system-ui; border: 3px solid #fff; margin-left: -10px; }
.avatar:first-child { margin-left: 0; }
.alert { display: flex; gap: 10px; padding: 12px 14px; border-radius: var(--r); border: 1px solid; margin: 8px 0; }
.alert--info { background: #eff6ff; border-color: #bfdbfe; color: #1e3a8a; }
.alert--err  { background: #fef2f2; border-color: #fecaca; color: #7f1d1d; }
</style>

<span class="badge badge--ok">Paid</span><span class="badge badge--warn">Pending</span><span class="badge badge--err">Overdue</span>
<div class="avatars"><span class="avatar" style="background:#264de4">AG</span><span class="avatar" style="background:#0891b2">RM</span><span class="avatar" style="background:#c2410c">SK</span><span class="avatar" style="background:#64748b">+5</span></div>
<div class="alert alert--info" role="status">ℹ️ <div><b>Fee reminder</b><br>Term 2 fee is due on 10 November.</div></div>
<div class="alert alert--err" role="alert">⚠️ <div><b>Payment failed</b><br>Your UPI request expired. Try again.</div></div>
▶  Status badges, an overlapping avatar group and alerts
HTML + CSS
<style>
:root { --brand: #264de4; --brand-600: #1e40af; --ok: #15803d; --warn: #b45309; --err: #b91c1c; --ink: #0f172a; --muted: #64748b; --line: #e2e8f0; --r: 10px; }
* { box-sizing: border-box; }
.crumbs ol { list-style: none; display: flex; flex-wrap: wrap; gap: 6px; padding: 0; margin: 0 0 14px; font-size: .9rem; }
.crumbs li + li::before { content: "›"; margin-right: 6px; color: var(--muted); }
.crumbs a { color: var(--brand); text-decoration: none; }
.crumbs [aria-current] { color: var(--muted); }
.pages { display: flex; gap: 6px; list-style: none; padding: 0; }
.pages a { display: grid; place-items: center; min-width: 38px; height: 38px; border: 1px solid var(--line); border-radius: 8px; text-decoration: none; color: var(--ink); }
.pages a:hover { border-color: var(--brand); }
.pages a[aria-current="page"] { background: var(--brand); color: #fff; border-color: var(--brand); }
</style>

<nav class="crumbs" aria-label="Breadcrumb"><ol><li><a href="#">Home</a></li><li><a href="#">Students</a></li><li><span aria-current="page">Class 10-A</span></li></ol></nav>
<nav aria-label="Pagination"><ul class="pages"><li><a href="#" aria-label="Previous">‹</a></li><li><a href="#">1</a></li><li><a href="#" aria-current="page">2</a></li><li><a href="#">3</a></li><li><a href="#" aria-label="Next">›</a></li></ul></nav>
▶  Separators with ::before, current page via aria-current

CSS-only tabs (radio hack) and accordion

HTML + CSS
<style>
:root { --brand: #264de4; --brand-600: #1e40af; --ok: #15803d; --warn: #b45309; --err: #b91c1c; --ink: #0f172a; --muted: #64748b; --line: #e2e8f0; --r: 10px; }
* { box-sizing: border-box; }
.tabs { display: flex; flex-wrap: wrap; border-bottom: 2px solid var(--line); }
.tabs input { position: absolute; opacity: 0; }
.tabs label { padding: 10px 16px; cursor: pointer; color: var(--muted); font-weight: 600; border-bottom: 3px solid transparent; margin-bottom: -2px; }
.tabs .panel { order: 99; width: 100%; padding: 14px 4px; display: none; }
.tabs input:checked + label { color: var(--brand); border-color: var(--brand); }
.tabs input:checked + label + .panel { display: block; }
.tabs input:focus-visible + label { outline: 3px solid #f59e0b; }
details.acc { border: 1px solid var(--line); border-radius: var(--r); margin: 8px 0; overflow: hidden; }
details.acc summary { padding: 12px 14px; cursor: pointer; font-weight: 600; list-style: none; display: flex; justify-content: space-between; }
details.acc summary::after { content: "+"; transition: transform .2s; }
details.acc[open] summary::after { transform: rotate(45deg); }
details.acc p { margin: 0; padding: 0 14px 12px; color: var(--muted); }
</style>

<div class="tabs">
  <input type="radio" name="t" id="t1" checked><label for="t1">Description</label><div class="panel">Cashew fudge made with A-grade kaju and pure ghee.</div>
  <input type="radio" name="t" id="t2"><label for="t2">Ingredients</label><div class="panel">Cashew 60%, sugar 38%, ghee 2%, silver vark.</div>
  <input type="radio" name="t" id="t3"><label for="t3">Reviews (128)</label><div class="panel">★★★★★ “Best kaju katli in Jaipur.”</div>
</div>
<details class="acc"><summary>Shelf life</summary><p>Up to 15 days at room temperature.</p></details>
<details class="acc"><summary>Delivery areas</summary><p>All of Jaipur within 2 hours.</p></details>
▶  Tabs from radio buttons; accordion from details with a rotating +
🧠 When to switch to JavaScript tabs

The radio trick is perfect for simple product pages. For full ARIA tab semantics (arrow-key navigation, role="tablist") you will write a small script in the JS course – the CSS stays the same.

HTML + CSS
<style>
:root { --brand: #264de4; --brand-600: #1e40af; --ok: #15803d; --warn: #b45309; --err: #b91c1c; --ink: #0f172a; --muted: #64748b; --line: #e2e8f0; --r: 10px; }
* { box-sizing: border-box; }
dialog.modal { border: 0; border-radius: 16px; padding: 0; width: min(92vw, 380px); box-shadow: 0 30px 60px rgb(0 0 0 / 30%); }
dialog.modal::backdrop { background: rgb(15 23 42 / 55%); backdrop-filter: blur(2px); }
dialog.modal[open] { animation: pop .2s ease-out; }
@keyframes pop { from { transform: scale(.95); opacity: 0; } }
.modal header { padding: 16px 18px; border-bottom: 1px solid var(--line); font-weight: 700; }
.modal .body { padding: 16px 18px; color: var(--muted); }
.modal footer { padding: 12px 18px; display: flex; justify-content: flex-end; gap: 8px; background: #f8fafc; }
.toast { position: fixed; left: 50%; bottom: 20px; transform: translate(-50%, 150%); background: var(--ink); color: #fff; padding: 12px 18px; border-radius: 12px; transition: transform .3s ease; }
.toast.show { transform: translate(-50%, 0); }
.btn { font: 600 .9rem system-ui; padding: .55em 1em; border-radius: 8px; border: 1px solid var(--line); background: #fff; cursor: pointer; }
.btn.primary { background: var(--err); color: #fff; border-color: var(--err); }
</style>

<button class="btn" onclick="dlg.showModal()">Delete order #1044</button>
<dialog class="modal" id="dlg" aria-labelledby="dh">
  <header id="dh">Delete this order?</header>
  <div class="body">Order #1044 (₹720) will be removed. This cannot be undone.</div>
  <footer><form method="dialog"><button class="btn">Cancel</button> <button class="btn primary" onclick="setTimeout(function(){toast.classList.add('show'); setTimeout(function(){toast.classList.remove('show')}, 2200)}, 50)">Delete</button></form></footer>
</dialog>
<div class="toast" id="toast" role="status">✔ Order #1044 deleted</div>
▶  Native dialog styled with ::backdrop; a toast slides up (try Delete)

🏅 Job skills unlocked today

✔ Design components with a base class and modifiers✔ Build badges, avatars, alerts, breadcrumbs and pagination✔ Create CSS-only tabs and accordions✔ Style dialogs and toast notifications

Practice tasks

🏋️ Practice – do it yourself

Task 1: Build a “stat card” component (icon, label, big number, trend badge) with two variants: up (green) and down (red).
Show solution
▶  Result
Task 2: Create a “stepper” (1 Cart → 2 Address → 3 Payment) with completed, current and upcoming states.
Task 3: Add a “warning” variant to the alert component using only new colour values.

Quick quiz

🧠 Quick Quiz – test yourself

1. Why a base .btn plus .btn--primary instead of one big class?
Reusable variants.
2. Style the dimmed area behind a dialog:
Pseudo-element for top-layer elements.
3. CSS-only tabs usually rely on…
Sibling selectors.
4. Mark the current page in pagination:
Accessible and styleable.
5. A toast hidden below the screen that slides up uses…
GPU-friendly.

Interview corner

💼 Interview Corner

How do you build a reusable component library in plain CSS?

Define design tokens as custom properties, create a base class per component with modifier classes for variants/sizes (BEM), keep selectors flat (single class), document usage, and avoid page-specific overrides inside components.

Native <dialog> vs a div modal?

dialog with showModal() handles the top layer, focus trapping, Esc to close, inert background and ::backdrop natively – fewer bugs and better accessibility than a custom div modal.

Summary

  • Components = base class + modifiers, driven by tokens.
  • Badges, avatars, alerts, breadcrumbs, pagination are small patterns reused everywhere.
  • Tabs via radio + :checked; accordion via details.
  • dialog + ::backdrop for modals; transform for toasts.
➡️ Next

Day 17: CSS architecture – BEM naming, file structure, reset, DevTools debugging and performance.

Frequently Asked Questions

Should I just use Bootstrap components instead?
Knowing how to build them yourself lets you customise any framework and pass interviews. Day 18 compares frameworks.
Where do I keep components in my files?
One file per component (buttons.css, cards.css) imported into main.css, or clearly commented sections in style.css – covered tomorrow.
← CSS (20 Days)
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

Next topicDay 17: CSS Architecture: BEM, Reset, DevTools, Performance Your progress: 16 / 20 (80%) · Lesson 17 / 20 Continue →

How was this lesson?

Your feedback helps us make the content better.

Write a review or suggestion (optional)

After approval, your name and city may appear publicly with your review. Please do not write your email or phone number.

▶ CodingEasily on YouTube

Learn with video lessons in easy Hindi

Featured video: RDBMS Part 3 – Class XI Commerce IT

▶ Subscribe – it’s free