← Back to UI screens

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

ScreenshotTabs component — web, retro style
Theme

Tabs component — web, retro 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). Retro style: warm cream, soft Fraunces headings with DM Sans, outlined cards and offset colour shadows. 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
Web
Style
Retro
Product (fictional)
Fernway
Category
Productivity

Spec

Colours (light)
background #fff5e9 · surface #ffffff · text #291b08 · muted #71604a · primary #bc5659 · accent #568b35
Colours (dark)
background #130900 · surface #201403 · text #f8efe3 · muted #bfae99 · primary #ff9c9c · accent #86bd67
Fonts
Fraunces (headings), DM Sans (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
tabswebproductivitybadgelist

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:#fff5e9;--surface:#ffffff;--border:#e4d3bd;--text:#291b08;--muted:#71604a;--primary:#bc5659;--on-primary:#ffffff;--accent:#568b35;--font-h:"Fraunces",Georgia,serif;--font-b:"DM Sans",system-ui,sans-serif;--hw:700;
--c-bw:2px;--c-line:var(--text);--c-r:10px;--c-pill:10px;--c-sh:3px 3px 0 var(--primary);--c-pop:5px 5px 0 var(--text);--c-tt:none;--c-ls:0;--c-fw:700;--c-fs:14px;--c-ring:3px solid var(--accent);--c-ind:3px;color-scheme:light}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){--bg:#130900;--surface:#201403;--border:#372917;--text:#f8efe3;--muted:#bfae99;--primary:#ff9c9c;--on-primary:#111111;--accent:#86bd67;color-scheme:dark}
}
:root[data-theme="dark"]{--bg:#130900;--surface:#201403;--border:#372917;--text:#f8efe3;--muted:#bfae99;--primary:#ff9c9c;--on-primary:#111111;--accent:#86bd67;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(--text)}
.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(--primary)}
.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 (3px solid accent), never removed
- **Style knobs (retro):** border 2px, corners 10px, shadow `3px 3px 0 var(--primary)`, 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: Fraunces + DM Sans (Google Fonts)

Writing about this component?

More tabs components

Tabs component — web, minimal (Fernway)
web · minimal
Tabs component — web, editorial (Fernway)
web · editorial
Tabs component — web, brutalist (Fernway)
web · brutalist
Tabs component — web, luxury (Fernway)
web · luxury
Tabs component — web, playful (Fernway)
web · playful
Tabs component — web, corporate (Fernway)
web · corporate
Tabs component — web, monochrome (Fernway)
web · monochrome
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