Nº 358 of 520
Plain phone tabs
A four-item phone tab bar with a hairline and a top mark. No glass, no blur, no floating capsule.
Preview
Use it
Free to use · credit appreciated1 Once, in your project
npx skills add SusanAcharya/Design-Lounge 2 Then ask
Using the Design Lounge skill, build "Plain phone tabs" (piece phone-tab-plain) in my stack. Match its brief; restyle it onto my product's theme.
No skill? Paste the brief instead. It carries the numbers, tokens and behaviour.
<!-- Design Lounge Nº 358 · "Plain phone tabs" · www.designlounge.live -->
# Plain phone tabs
> **Build brief for a coding agent.** Rebuild this piece in the reader's stack. If they haven't said which stack, ask once, then default to semantic HTML + CSS + a little vanilla JS. Match the numbers below; don't "improve" them. When a kit is locked, map colours onto the kit tokens. This is the tab bar for families that are not glass.
## What it is
A phone shell for a personal app that is not using the glass language. Four tabs sit on a flat surface at the bottom: Home, Spend, Budgets, You. Spend starts current. The current tab is navy ink with a 2px crimson mark on its top edge. The others are muted. There is no blur, no translucent pill, and no floating capsule. Above the bar, the screen name is a 13px label and the current section is a 40px heading. The bar respects the home indicator with 34px of padding under the labels, and the page starts 54px below the top. The Lounge draws the status bar. Do not draw one here.
## Reference behaviour
1. Spend starts with `aria-current="page"`. The heading reads Spend.
2. Tapping a tab moves `aria-current` to it and sets the heading to that tab's name. The others lose the mark.
3. Only one tab is current.
4. The bar does not hide on scroll. This frame does not scroll.
5. No motion. Reduced motion has nothing to remove.
6. Icons are inline SVG, 22px, stroke 1.75, round caps, `currentColor`. No emoji.
7. Each tab's hit target is at least 44px tall, before the 34px home padding.
## Structure
```
padding-top 54px, padding-inline 20px
ASAR 13px
Spend 40px
fixed bottom bar, surface, 1px top rule
[ Home ] [ Spend ] [ Budgets ] [ You ]
padding-bottom 34px
```
- The label and the heading are in the page. The heading is the only `h1`.
- The bar is a `nav` with four buttons.
- The bar is `position: fixed` at the bottom, full width, `--surface`, `border-top: 1px solid --line`.
- Page padding-bottom is 96px so the heading can never sit under the bar.
- Grain is on the page. The bar is opaque surface, so the grain stops at the hairline.
## Tokens
… 133 more lines. Copy or download for the full brief. Loading the source…Brief
173 linesBuild brief for a coding agent. Rebuild this piece in the reader’s stack. If they haven’t said which stack, ask once, then default to semantic HTML + CSS + a little vanilla JS. Match the numbers below; don’t “improve” them. When a kit is locked, map colours onto the kit tokens. This is the tab bar for families that are not glass.
What it is
A phone shell for a personal app that is not using the glass language. Four tabs sit on a flat surface at the bottom: Home, Spend, Budgets, You. Spend starts current. The current tab is navy ink with a 2px crimson mark on its top edge. The others are muted. There is no blur, no translucent pill, and no floating capsule. Above the bar, the screen name is a 13px label and the current section is a 40px heading. The bar respects the home indicator with 34px of padding under the labels, and the page starts 54px below the top. The Lounge draws the status bar. Do not draw one here.
Reference behaviour
- Spend starts with
aria-current="page". The heading reads Spend. - Tapping a tab moves
aria-currentto it and sets the heading to that tab’s name. The others lose the mark. - Only one tab is current.
- The bar does not hide on scroll. This frame does not scroll.
- No motion. Reduced motion has nothing to remove.
- Icons are inline SVG, 22px, stroke 1.75, round caps,
currentColor. No emoji. - Each tab’s hit target is at least 44px tall, before the 34px home padding.
Structure
padding-top 54px, padding-inline 20px
ASAR 13px
Spend 40px
fixed bottom bar, surface, 1px top rule
[ Home ] [ Spend ] [ Budgets ] [ You ]
padding-bottom 34px
- The label and the heading are in the page. The heading is the only
h1. - The bar is a
navwith four buttons. - The bar is
position: fixedat the bottom, full width,--surface,border-top: 1px solid --line. - Page padding-bottom is 96px so the heading can never sit under the bar.
- Grain is on the page. The bar is opaque surface, so the grain stops at the hairline.
Tokens
:root {
--bg: #f4ead6;
--surface: #fbf6ea;
--ink: #1c2744;
--ink-2: #3e4a66;
--ink-3: #6d768c;
--line: #d9cbb3;
--primary: #c8102e;
--focus: #c8102e;
--display: "Noto Serif Devanagari", Georgia, serif;
--sans: "Mukta", system-ui, sans-serif;
}
Typography
| Role | Family | Size | Weight | Tracking | Colour |
|---|---|---|---|---|---|
| Label | Mukta | 13px | 600 | 0.04em | --ink-2 |
| Section | Noto Serif Devanagari | 40px | 600 | -0.02em | --ink |
| Tab | Mukta | 11px | 600 | 0 | --ink-3, current --ink |
The section heading is the largest type. The tab labels stay 11px. Do not set the tabs in the display face.
Motion
None. A tab change replaces the heading immediately. A sliding pill is the glass piece, ios-glass-tab-bar. Do not import it here.
| Thing | Trigger | What changes |
|---|---|---|
| Tab | click | aria-current moves, heading text becomes the tab name, top border becomes the primary |
States
- Tab resting: colour
--ink-3, top border 2px transparent, min-height 44px. - Tab current: colour
--ink, top border 2px--primary,aria-current="page". - No filled pill behind the current tab.
- Focus-visible: 2px outline, offset 2px.
- Disabled: not used. All four tabs are available.
- Do not add a badge count on this frame.
Accessibility
- The nav is labelled “Sections”.
- Each control is a button. The visible word is the name. The icon is
aria-hidden. aria-current="page"is the current tab. Do not also setaria-pressed.- Hit target is at least 44px tall and a quarter of the bar wide.
- Contrast:
#1c2744on#fbf6eaclears 4.5.#6d768con#fbf6eais the muted tab. If a locked theme’s muted ink fails 4.5 on the bar, use--ink-2instead of inventing a hex. - The top mark is not the only signal. The current label is darker, and the heading repeats the name.
Responsive rules
- The frame is 390×844. Padding top 54px. Bar padding bottom 34px.
- At 360 wide, the four labels still fit. Do not drop the words and leave only icons.
- At tablet width, do not stretch this bar across 1180px. A tablet uses the tablet recipe, with a sidebar or a split. This bar is a phone.
- Do not draw a status bar, a notch, or a home indicator glyph. The padding is the clearance.
Acceptance checklist
Always
- One current tab. This demo has four sections. A product uses three to five, one per real section, and does not add or drop a tab to match this demo.
- The bar is a flat surface with a 1px top rule. No blur, no glass, no floating capsule.
- The current tab uses a 2px top mark in the primary, not a pill fill.
- Each tab is at least 44px tall.
- The home clearance is 34px under the labels. The top clearance is 54px.
- Icons are stroke SVGs in
currentColor, not emoji. - One nav system. No second bar.
This demo
- The first frame heading is Spend at 40px.
- Spend has
aria-current="page"and a crimson top border. - The other labels are Home, Budgets, and You.
- Tapping Budgets sets the heading to Budgets and moves the mark.
- The bar background is
#fbf6eawith a#d9cbb3top rule. - Page padding-top is max(54px, env(safe-area-inset-top)). Bar padding-bottom is max(34px, env(safe-area-inset-bottom)).
- No status bar is drawn.
- Focus ring is 2px, offset 2px.
Implementation notes
Always: use this bar when the family is quiet, soft, sharp, editorial, or industrial. Use ios-glass-tab-bar only when the family is glass. Do not put a glass bar on a Lokta screen.
The current mark is a border, not an extra element:
.tab { border-top: 2px solid transparent; min-height: 44px; color: var(--ink-3); }
.tab[aria-current="page"] { color: var(--ink); border-top-color: var(--primary); }
.bar { padding-bottom: max(34px, env(safe-area-inset-bottom)); background: var(--surface); border-top: 1px solid var(--line); }
Common mistakes:
- Borrowing the glass tab bar because it is the first phone nav in the index.
- A floating rounded rectangle with a shadow.
- Icons only, no labels.
- Five tabs. Four is this piece.
- A badge, a FAB, and the bar all competing.
- Drawing the clock and the battery.
- Setting the tab labels in the display serif.
- A second navigation row under the heading.
- Blur on the bar “so the content shows through”. The content stops above the bar.
- Using this bar on a tablet width.
Where it sits:
- It is the shell of a personal phone app. The section heading is the screen you are on.
- Spend opens
chart-rank-spendstacked for the phone. Budgets opensbudget-meter. Those pieces are not drawn inside this demo. - Home and You are named so the bar is complete. Their screens are still open unless the pass includes them.
- Empty and failed lists on this shell use
mobile-list-emptyandmobile-load-failed, restyled onto the locked theme. - One primary button may exist in the page body. The tabs are navigation, not a second primary.
- When a theme is locked, the mark is
--primaryand the bar is--surface. - Grain stays on the page, not on the bar.
- Do not mix this with a sidebar. A phone has one nav.
- The heading at 40px is the answer for this piece, which is “where am I”. A money screen that uses this shell gives the amount the display size and drops this heading to a 13px label. Do not keep both at display size.
- The credit line stays on the token block.
Rebuild order:
- Set the phone padding, 54px top, room for the bar at the bottom.
- Place the label and the 40px heading.
- Place the fixed bar with four buttons, 34px under them.
- Mark Spend current.
- Wire taps to the heading and
aria-current. - Confirm there is no blur and no pill.
- Map colours onto the locked theme if a kit is on.
Details
- Palette
- Type
- Noto Serif Devanagari · Mukta
- Motion
- Static
- Build
- Quick build
- Tags
Studied
Tailwind CSS docsPut each instruction next to its code. Draw the grid with thin lines and let the empty sides carry a faint hatch.
All sourcesOn the shelves