← Back to UI screens

Live: try it with the mouse and the keyboard (Tab, arrows, Escape).

ScreenshotTabs component — mobile, monochrome style
Theme

Tabs component — mobile, monochrome style

Tabs UI component for websites and web apps, shown in Fernway, a fictional productivity product. Shows a tab list with a count badge and a disabled tab, the selected panel, and every tab state (default, hover, focus-visible, selected, disabled). Monochrome style: pure greyscale, Geist, black primary actions and flat surfaces. Comes with copyable HTML, CSS and a few lines of plain JavaScript (keyboard support and ARIA per the WAI-ARIA Authoring Practices), a live demo, and a DESIGN.md with light and dark colour tokens.

Open live HTML ↗ Download DESIGN.md
Pattern
Tabs
Device
Mobile
Style
Monochrome
Product (fictional)
Fernway
Category
Productivity

Spec

Colours (light)
background #ffffff · surface #fafafa · text #111111 · muted #666666 · primary #111111 · accent #444444
Colours (dark)
background #0a0a0a · surface #161616 · text #f2f2f2 · muted #a0a0a0 · primary #f2f2f2 · accent #c8c8c8
Fonts
Geist (headings and body), JetBrains Mono (code) · Google Fonts, under their own licences
Light and dark
Both included; follows the system setting
ARIA pattern
Tabs (WAI-ARIA Authoring Practices)
Keyboard
Left and Right arrows, Home and End; Tab moves into the panel
States
default, hover, focus-visible, selected, disabled
tabsmobileproductivitybadgelist

Code

Paste the HTML where the component goes, the CSS into your stylesheet and the script before </body>. The tokens block holds the light and dark colours; swap in your own.

HTML
<div class="mgd-tabs">
  <div class="mgd-tabs__list" role="tablist" aria-label="Q4 launch project">
    <button class="mgd-tabs__tab" type="button" role="tab" id="tab-overview" aria-controls="panel-overview" aria-selected="true" tabindex="0">Overview</button>
    <button class="mgd-tabs__tab" type="button" role="tab" id="tab-tasks" aria-controls="panel-tasks" aria-selected="false" tabindex="-1">Tasks <span class="mgd-tabs__count">12</span></button>
    <button class="mgd-tabs__tab" type="button" role="tab" id="tab-files" aria-controls="panel-files" aria-selected="false" tabindex="-1">Files</button>
    <button class="mgd-tabs__tab" type="button" role="tab" id="tab-activity" aria-controls="panel-activity" aria-selected="false" tabindex="-1">Activity</button>
    <button class="mgd-tabs__tab" type="button" role="tab" id="tab-billing" aria-controls="panel-billing" aria-selected="false" tabindex="-1" aria-disabled="true">Billing</button>
  </div>
  <div class="mgd-tabs__panel" role="tabpanel" id="panel-overview" aria-labelledby="tab-overview" tabindex="0"><h3>Q4 launch</h3><p>Ship the new onboarding to every Fernway workspace by 12 December.</p><ul class="mgd-tabs__rows"><li>Owner<span>Mara Okafor</span></li><li>Due<span>12 Dec</span></li><li>Progress<span>7 of 12 tasks</span></li></ul></div>
  <div class="mgd-tabs__panel" role="tabpanel" id="panel-tasks" aria-labelledby="tab-tasks" tabindex="0" hidden><h3>12 open tasks</h3><p>Sorted by due date.</p><ul class="mgd-tabs__rows"><li>Write welcome email copy<span>Teodora · Fri</span></li><li>Record the 60-second tour<span>Sam · Mon</span></li><li>QA the invite flow on mobile<span>Lin · Tue</span></li></ul></div>
  <div class="mgd-tabs__panel" role="tabpanel" id="panel-files" aria-labelledby="tab-files" tabindex="0" hidden><h3>Files</h3><p>4 files, 18 MB.</p><ul class="mgd-tabs__rows"><li>onboarding-flow.fig<span>12 MB</span></li><li>launch-brief.pdf<span>2 MB</span></li></ul></div>
  <div class="mgd-tabs__panel" role="tabpanel" id="panel-activity" aria-labelledby="tab-activity" tabindex="0" hidden><h3>Activity</h3><p>Latest first.</p><ul class="mgd-tabs__rows"><li>Jonah moved 3 tasks to Done<span>2h ago</span></li><li>Priya commented on the tour script<span>5h ago</span></li></ul></div>
  <div class="mgd-tabs__panel" role="tabpanel" id="panel-billing" aria-labelledby="tab-billing" tabindex="0" hidden><h3>Billing</h3><p>Only workspace admins can see billing.</p></div>
</div>
CSS
/* Tokens (light + dark) */
:root{--bg:#ffffff;--surface:#fafafa;--border:#e4e4e4;--text:#111111;--muted:#666666;--primary:#111111;--on-primary:#ffffff;--accent:#444444;--font-h:"Geist",Georgia,serif;--font-b:"Geist",system-ui,sans-serif;--hw:600;
--c-bw:1px;--c-line:var(--border);--c-r:6px;--c-pill:6px;--c-sh:none;--c-pop:0 10px 28px rgb(0 0 0 / .16);--c-tt:none;--c-ls:0;--c-fw:500;--c-fs:14px;--c-ring:2px solid var(--text);--c-ind:2px;color-scheme:light}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){--bg:#0a0a0a;--surface:#161616;--border:#2c2c2c;--text:#f2f2f2;--muted:#a0a0a0;--primary:#f2f2f2;--on-primary:#0a0a0a;--accent:#c8c8c8;color-scheme:dark}
}
:root[data-theme="dark"]{--bg:#0a0a0a;--surface:#161616;--border:#2c2c2c;--text:#f2f2f2;--muted:#a0a0a0;--primary:#f2f2f2;--on-primary:#0a0a0a;--accent:#c8c8c8;color-scheme:dark}

/* Component */
.mgd-sr{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.mgd-tabs{max-width:760px}
.mgd-tabs__list{display:flex;gap:4px;overflow-x:auto;scrollbar-width:none;border-bottom:var(--c-bw) solid var(--border)}
.mgd-tabs__tab{flex:none;display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:0 16px;border:0;background:none;color:var(--muted);font:var(--c-fw) var(--c-fs)/1 var(--font-b);text-transform:var(--c-tt);letter-spacing:var(--c-ls);cursor:pointer;border-radius:var(--c-r) var(--c-r) 0 0;margin-bottom:calc(-1 * var(--c-bw));transition:color .12s,background-color .12s,box-shadow .12s}
.mgd-tabs__tab:hover,.mgd-tabs__tab.is-hover{color:var(--text);background:color-mix(in oklab,var(--primary) 7%,transparent)}
.mgd-tabs__tab:focus-visible,.mgd-tabs__tab.is-focus{outline:var(--c-ring);outline-offset:-2px}
.mgd-tabs__tab[aria-selected="true"],.mgd-tabs__tab.is-on{color:var(--text);box-shadow:inset 0 calc(-1 * var(--c-ind)) 0 var(--text)}
.mgd-tabs__tab[aria-disabled="true"],.mgd-tabs__tab.is-off{opacity:.45;cursor:not-allowed;background:none}
.mgd-tabs__count{min-width:22px;height:20px;padding:0 6px;border-radius:999px;display:inline-grid;place-items:center;font:600 11px/1 var(--font-b);letter-spacing:0;background:color-mix(in oklab,var(--accent) 18%,var(--surface));color:var(--text)}
.mgd-tabs__panel{padding:22px 2px 4px}
.mgd-tabs__panel:focus-visible{outline:var(--c-ring);outline-offset:4px;border-radius:4px}
.mgd-tabs__panel h3{margin:0 0 6px;font:var(--hw) 20px/1.2 var(--font-h)}
.mgd-tabs__panel p{margin:0 0 14px;color:var(--muted)}
.mgd-tabs__rows{list-style:none;margin:0;padding:0;display:grid;gap:8px}
.mgd-tabs__rows li{display:flex;justify-content:space-between;gap:12px;padding:12px 14px;border:var(--c-bw) solid var(--c-line);border-radius:var(--c-r);background:var(--surface);box-shadow:var(--c-sh)}
.mgd-tabs__rows span{color:var(--muted);font-size:13px;font-variant-numeric:tabular-nums}
@media (prefers-reduced-motion:reduce){.mgd-tabs,.mgd-tabs *{transition:none!important;animation-duration:2.4s!important}}
JavaScript
document.querySelectorAll(".mgd-tabs [role=tablist]").forEach(function (list) {
  var tabs = [].slice.call(list.querySelectorAll("[role=tab]"));
  var usable = function () { return tabs.filter(function (t) { return t.getAttribute("aria-disabled") !== "true"; }); };
  function select(tab) {
    if (tab.getAttribute("aria-disabled") === "true") return;
    tabs.forEach(function (t) {
      var on = t === tab;
      t.setAttribute("aria-selected", on); t.tabIndex = on ? 0 : -1;
      document.getElementById(t.getAttribute("aria-controls")).hidden = !on;
    });
    tab.focus();
  }
  list.addEventListener("click", function (e) { var t = e.target.closest("[role=tab]"); if (t) select(t); });
  list.addEventListener("keydown", function (e) {
    var u = usable(), i = u.indexOf(document.activeElement), next = null;
    if (e.key === "ArrowRight") next = u[(i + 1) % u.length];
    else if (e.key === "ArrowLeft") next = u[(i - 1 + u.length) % u.length];
    else if (e.key === "Home") next = u[0];
    else if (e.key === "End") next = u[u.length - 1];
    if (next) { e.preventDefault(); select(next); }
  });
});

DESIGN.md

Component section (states, ARIA, keyboard)
## Component: Tabs

Switch between related panels without leaving the page. Arrow keys move between tabs; the panel follows.

- **Pattern:** WAI-ARIA Authoring Practices, Tabs (https://www.w3.org/WAI/ARIA/apg/patterns/tabs/)
- **Roles and attributes:** role="tablist" with an aria-label; each tab is a button with role="tab", aria-selected and aria-controls; each panel has role="tabpanel", aria-labelledby and tabindex="0". Only the selected tab is in the tab order (roving tabindex).
- **States drawn:** default, hover, focus-visible, selected, disabled
- **Focus:** a visible `:focus-visible` outline (2px solid text), never removed
- **Style knobs (monochrome):** border 1px, corners 6px, shadow none, labels sentence case
- **Motion:** transitions are short (≤160ms) and switched off under `prefers-reduced-motion: reduce`
- **Code:** HTML + CSS + a few lines of plain JavaScript (no libraries); colours come only from the tokens above, so light and dark both work

### Keyboard
- **Left / Right arrow:** move to the previous / next tab and show its panel (wraps)
- **Home / End:** first / last tab
- **Tab:** leave the tab list and move into the panel

### Licence
Original Made Good Designs code: free to use and adapt in any project, including commercial ones, with no credit needed. Fonts are Google Fonts under their own licences.
AI

Build this with your AI

Fonts: Geist (Google Fonts)

Writing about this component?

More tabs components

Tabs component — web, monochrome (Fernway)
web · monochrome
Tabs component — mobile, minimal (Fernway)
mobile · minimal
Tabs component — mobile, editorial (Fernway)
mobile · editorial
Tabs component — mobile, brutalist (Fernway)
mobile · brutalist
Tabs component — mobile, luxury (Fernway)
mobile · luxury
Tabs component — mobile, playful (Fernway)
mobile · playful
Tabs component — mobile, corporate (Fernway)
mobile · corporate
Tabs component — mobile, retro (Fernway)
mobile · retro
Building with an AI coding agent? Every screen here is also in the free Made Good Designs MCP server: ask Claude, Cursor or ChatGPT to search_ui_screens (e.g. “billing settings, editorial style”), get_ui_flow for a whole journey, and get_ui_screen_code to pull the HTML and DESIGN.md straight into your project.

Save to board