20 CSS Kbd Keys

20 hand-coded CSS keyboard keys for documentation, shortcut cheatsheets, settings panels, command hints and onboarding. Covers the inline kbd element in running prose, 3D caps that genuinely depress, multi-key combos with the separator outside the keys, Mac glyphs against Windows words, arrow clusters, non-uniform widths for Space and Enter, and the reading surfaces a shortcut appears in. Scoped under .kbd-NN for no-collision pasting, prefers-reduced-motion guarded, framework-agnostic.

18 pure CSS2 light JSPublished

Related20 CSS Code Blocks36 CSS Search Bars21 CSS Tooltips30 CSS Badges

Inline HTML Kbd Tag Basic Styling — preview
01 / 20Pure CSS

Inline HTML Kbd Tag Basic Styling

The reference treatment the rest of the collection builds on: the kbd element styled as a small cap that sits inside a real paragraph of documentation without disturbing the line it lives on. A hairline border plus a one-pixel bottom edge reads as key depth, and the label is set slightly smaller than the surrounding prose so the cap optically matches the x-height of the text around it.

Published

3D Keycap with Active Push Down — preview
02 / 20Pure CSS

3D Keycap with Active Push Down

A cap with a real side wall. Layered box-shadows build the wall and the shadow it casts, a lighter gradient forms the top face, and the pressed state translates the cap down while collapsing the wall by the same amount, so the key travels instead of sliding. The press fires on both active and focus-visible, because a key you can only push with a mouse is not a key.

Published

Key Combo Layout with Plus Separators — preview
03 / 20Pure CSS

Key Combo Layout with Plus Separators

Multi-key combos laid out as a flex row with a dimmed separator between the caps. The separator sits outside the kbd elements, which is the whole point: a screen reader then announces Control plus C rather than reading punctuation trapped inside a key. Includes a second row for sequential shortcuts, where G then P is a sequence and not a chord.

Published

Flat Minimalist Keycap for Body Text — preview
04 / 20Pure CSS

Flat Minimalist Keycap for Body Text

No depth, no shadow: a tinted rounded rectangle with a hairline border, sized to disappear into dense body copy. This is the treatment most documentation sites actually ship, because a physical cap repeated forty times down a reference page becomes visual noise. Set beside demo 01 so you can see exactly what you trade away and what you get back.

Published

Fluid Kbd Sizing with Em Units — preview
05 / 20Pure CSS

Fluid Kbd Sizing with Em Units

One class, three contexts. Every dimension on the cap — padding, radius, border, minimum width — is expressed in em, so the same markup renders correctly inside a large heading, ordinary body copy, and a small caption without a single size override. The demo puts all three on screen at once so the scaling is visible rather than asserted.

Published

Mac Command vs Windows Ctrl Toggle — preview
06 / 20Pure CSS

Mac Command vs Windows Ctrl Toggle

A visible platform switch that rewrites an entire shortcut list between Mac glyphs and Windows words, with no JavaScript at all. State lives in a hidden radio pair and the has() selector on the demo root swaps which span inside each key is displayed. The Mac side uses the real modifier glyphs in the canonical order that macOS itself renders them.

Published

Arrow Keys and Navigation Glyphs — preview
07 / 20Pure CSS

Arrow Keys and Navigation Glyphs

The inverted-T arrow cluster laid out in CSS Grid, next to the six-key navigation block. Arrows are real Unicode characters rather than images, each carrying a visually hidden name so the key announces as Arrow up instead of a bare glyph. The cluster uses explicit grid placement because the shape itself carries meaning that flex wrapping would destroy.

Published

Auto OS Detect Cmd or Ctrl Display — preview
08 / 20Light JS

Auto OS Detect Cmd or Ctrl Display

Detect the platform once, write it to a data attribute on the demo root, and let attribute selectors style every key on the page from that single value. Nine lines of script replace a per-key conditional, and if the script never runs the markup still renders a complete Windows-labelled list rather than an empty one.

Published

Function Keys and Wide Space Bar Caps — preview
09 / 20Pure CSS

Function Keys and Wide Space Bar Caps

Real keyboards specify key widths in units, and so does this demo. A single --u custom property defines one unit, and each wide cap multiplies it with its own --w value, exactly the way physical layouts are described. The function row, Tab, Backspace, Shift, Enter and a full-width Space bar all come from the same rule with one number changed.

Published

Icon Only Keys with Inline SVG — preview
10 / 20Pure CSS

Icon Only Keys with Inline SVG

Caps whose label is a mark rather than a word: search, escape, backspace, eject and power. Every icon is inline SVG drawn with currentColor so it inherits the cap's ink, and every key pairs an aria-hidden graphic with visually hidden text, because an icon-only key with no accessible name is an unlabelled control.

Published

Search Bar Shortcut Hint with Kbd — preview
11 / 20Pure CSS

Search Bar Shortcut Hint with Kbd

The trailing shortcut pill pinned inside a search field. The input is deliberately plain chrome; the cap is the subject. It sits optically centred against the field rather than mathematically centred, takes pointer-events: none so a click anywhere still lands in the input, and dims on focus because once you are typing the hint has done its job.

Published

Keyboard Shortcut Cheatsheet Grid — preview
12 / 20Pure CSS

Keyboard Shortcut Cheatsheet Grid

A grouped shortcut reference where the key column lines up across every section regardless of how long the labels are. One shared grid track does the alignment, so Navigation, Editing and View sit on the same measure instead of each group finding its own. It is a page section, not an overlay — two columns on desktop collapsing to one on narrow screens.

Published

Tooltip with Kbd Shortcut Hint — preview
13 / 20Pure CSS

Tooltip with Kbd Shortcut Hint

A toolbar button whose tooltip names the action and shows its shortcut. The tooltip is deliberately plain — one dark panel, no arrow theatre, no entrance choreography — because the cap is the subject. It opens on hover and on focus-visible, so a keyboard user reaching the button by tab sees exactly what a mouse user sees.

Published

App Settings Shortcut Mapping Table — preview
14 / 20Pure CSS

App Settings Shortcut Mapping Table

A real settings surface built as a semantic table, because shortcut mappings are tabular data — action, binding, scope, source — and a flex list throws all of that structure away. Includes a reset affordance per customised row and one row in a conflict state, flagged with an icon and a word rather than a red background alone.

Published

Live Key Press Feedback Display — preview
15 / 20Light JS

Live Key Press Feedback Display

The onboarding and screencast pattern: press a key and it appears on screen as a cap, then fades out on a timer. Under twenty lines of script handle the three real traps — event.key is not event.code, modifier-only presses need their own labels, and holding a key fires repeat events that would otherwise flood the stack with duplicates.

Published

Neumorphic Soft UI Keycap — preview
16 / 20Pure CSS

Neumorphic Soft UI Keycap

The soft-UI treatment done honestly: a matched pair of light and dark shadows on a mid-tone surface, extruded at rest and genuinely inset when pressed. It also states the limitation plainly, because a shadow-only edge does not meet the WCAG non-text contrast requirement, so each cap here keeps a faint border and a high-contrast label.

Published

Glassmorphic Translucent Keycap — preview
17 / 20Pure CSS

Glassmorphic Translucent Keycap

Frosted caps over a rich gradient: backdrop-filter blur with a saturate boost, a thin inner rim catching the light along the top edge, and a solid fallback declared first so engines without backdrop-filter get an opaque cap rather than an invisible one. The trap is documented too — an ancestor combining overflow hidden with a transform kills the effect silently.

Published

Retro Typewriter Round Keycap — preview
18 / 20Pure CSS

Retro Typewriter Round Keycap

Circular caps ringed in nickel, set with a serif label on a warm paper ground. The shadow is deep and hard rather than soft and modern, because a 1930s key sat on a metal arm and cast an edge, not a blur. Pressing a cap sinks it into the plate with the ring compressing on the way down.

Published

Terminal Monospace Kbd Key — preview
19 / 20Pure CSS

Terminal Monospace Kbd Key

Dev-tool treatment: monospace labels in phosphor green on near-black, square corners, and a faint scanline wash over the panel. The key reads as terminal output rather than as a physical object, which is the point — this is the register for CLI docs, REPL help screens and debugger overlays where a plastic cap would look out of place.

Published

Dark Mode Kbd Keys with CSS Variables — preview
20 / 20Pure CSS

Dark Mode Kbd Keys with CSS Variables

Theme-aware key tokens plus a working light and dark switch with zero JavaScript. State lives in a visually hidden checkbox and has() on the demo root rewrites the custom properties, so one checked state flips every colour at once. The OS-default block carries the opposite-base rule too, without which the switch silently does nothing for half your visitors.

Published

FAQ

Frequently asked questions

How do I style the kbd tag in CSS?
The <kbd> element ships with a browser default of monospace text and nothing else, so every keycap you have seen is author CSS. The recipe is short: a small inline-block with padding, a border, a background one step off the page surface, and a rounded corner. What separates a good cap from a bad one is the depth cue — a single box-shadow: 0 1px 0 in a darker tone reads as the key's side wall and does more work than any gradient. Two details are worth getting right immediately. Size the cap in em rather than px so it scales with whatever text it sits in; a key hardcoded to 12px looks broken inside a heading. And set line-height: 1 on the cap, because the inherited body line-height will otherwise make it taller than the text around it and push the line box open. Keep the label at 11px or above at the smallest — a key rendered smaller than that fails both legibility and contrast.
How do I mark up a keyboard shortcut like Ctrl + C?
Use one <kbd> per physical key and put the separator BETWEEN them, never inside: <kbd>Ctrl</kbd> + <kbd>C</kbd>. This matters for more than tidiness. A screen reader announcing a single key element containing the string "Ctrl+C" reads the punctuation as part of the key, whereas separate elements with the plus outside are announced as a combination. The HTML spec does allow nesting — a <kbd> wrapping several child <kbd> elements represents one composite input — and that is the most semantically precise form if you want it. For a sequential shortcut, where the user presses one key and then another rather than holding both, use the word "then" instead of a plus. That distinction is invisible in a screenshot but it is the difference between a working instruction and a confusing one, and almost no documentation gets it right.
Should keyboard keys be sized in px or em?
em, in almost every case. A keycap is inline content that sits inside running text, so its job is to match the type around it — and em resolves against the element's own font-size, which means one set of rules works in body copy, in a heading, and in a small caption without a single override. Express the padding, the border-radius and the minimum width in em too, or you get a cap whose text scales while its box does not. The exception is the border. A hairline is a visual constant rather than a typographic measure, so border-width belongs in px: a 1px key outline should stay 1px whether the surrounding text is 12px or 32px. The same reasoning applies to the depth shadow's offset. This is the single most common mistake in keycap CSS — everything scales except the two things that should not.
How do I show Mac and Windows shortcuts on the same page?
Two approaches, and they solve different problems. If you want the reader to choose, a radio pair plus :has() on the container does it with no JavaScript at all: check the Windows radio and every Mac glyph inside the container swaps to its Windows word through attribute-driven display rules. If you want the page to be correct on arrival, detect the platform once and set a data-os attribute on a wrapper, then let attribute selectors style every key from that single value. Feature-detect with navigator.userAgentData?.platform and fall back to navigator.platform, which is deprecated but still the only thing some browsers report. One caution worth stating plainly: user-agent sniffing is acceptable here because the consequence of getting it wrong is a cosmetically wrong label, not a broken or insecure page. Never make a capability or security decision the same way — and always give the reader a manual override, since plenty of people use a Mac keyboard on Windows and the reverse.
How do I make icon-only keys accessible?
An icon-only cap has no accessible name, so a screen reader announces nothing useful. Mark the SVG aria-hidden="true" and put visually-hidden text inside the key carrying the real label — "Escape", "Backspace", "Search". Use the clip-path visually-hidden pattern rather than display: none or visibility: hidden, because both of those remove the text from the accessibility tree entirely, which is precisely what you were trying to avoid. Two more points apply to any key that is also a control. If the cap is interactive it needs a genuine 44x44px target per WCAG 2.5.8, which usually means padding the hit area rather than growing the glyph. And it needs a visible :focus-visible ring at 3:1 contrast against its surroundings. A purely decorative cap — a specimen in documentation — is not interactive and should not be a button at all; a <kbd> is a label, not a control.
How do I lay out an arrow key cluster in CSS?
CSS Grid, with an explicit template — the inverted-T shape is exactly the case flexbox handles badly. Give the container three columns and two rows, place the up arrow in the middle of the top row, and let left, down and right fill the bottom row. A flex row with wrapping will not reproduce the shape reliably at any width, because the wrap point depends on available space rather than on the layout you intended. Use real Unicode arrow characters for the glyphs rather than images or an icon font; they are present in every system font, they inherit currentColor for free, and they scale with the cap. The navigation cluster — Home, End, Page Up, Page Down — is the same idea in a two-by-two grid. The one thing to watch on narrow screens is that a fixed-column grid cannot wrap, so the cluster must scale down through its font-size rather than reflow, or it will push the page sideways at 320px.
Why does my keycap look wrong inside a heading or a table?
Almost always one of three causes. First, absolute sizing: a cap with font-size: 12px and padding: 4px is correct in body copy and comically small in a 32px heading. Size in em and the problem disappears. Second, inherited line-height: a cap that does not set line-height: 1 inherits the paragraph's 1.6, which makes the key box taller than the text and visibly opens up the line it sits on. Third, and specific to tables, is width. A shortcut column holding combinations like <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> has a large minimum content width, so the table refuses to shrink below it and pushes the page sideways on mobile. The fix is not to shrink the keys — it is to wrap the table in a container with overflow-x: auto and let it scroll, because a shortcut table is tabular data and squeezing it destroys the alignment that makes it readable.
How do these port to React, Vue, Svelte and Tailwind?
The CSS ports unchanged — every .kbd-NN selector and custom property is framework-agnostic, and the eighteen pure-CSS demos need no JavaScript in any framework. Where behaviour exists the shape is small. Platform detection belongs in an effect rather than the component body: navigator does not exist during a server render in Next or Nuxt, so reading it at module scope throws at build time. Set the data-os attribute inside useEffect, or accept a brief first paint with the default glyphs. The live key-press demo attaches a keydown listener to the document, so in React it belongs in an effect with the removal returned as cleanup — otherwise a remount stacks listeners and every keystroke renders several caps. Vue uses onMounted with onBeforeUnmount; Svelte returns the teardown from onMount. For Tailwind, the cap is a short utility chain and the theme swap maps to dark: variants, though the :has() toggle here needs no variant at all.

Related collections

30 CSS Badges preview

30 CSS Badges

30 hand-coded CSS badges for status indicators, notifications, membership tiers, live-data displays, and SEO / DevOps / financial dashboards — upload progress, typing indicator, transit line status, Core Web Vitals, ECG heartbeat, CI/CD build pipeline, countdown ring, live price ticker, keycap shortcut, wax seal, conference lanyard, and holographic collectibles. Copy-paste HTML and CSS, WCAG 2.2 accessible, MIT licensed.

20 CSS Banners & Alerts preview

20 CSS Banners & Alerts

20 hand-coded CSS banner and alert bars for e-commerce storefronts, SaaS dashboards, marketing sites, and compliance-bound products. Covers GDPR cookie consent with a real preferences panel, promo bars with countdown timers, free-shipping threshold progress, app-install smart banners, maintenance and incident status bars, newsletter signup bars, age verification gates, limited-stock urgency banners, live event announcements, browser upgrade notices, geo and currency switchers, sticky top announcement bars, bottom cookie bars, inline form validation alerts, icon-aligned alert banners, left-border accent alerts, diagonal stripe promos, full-width hero banners, animated gradient border alerts, and a text-wrapping laboratory that shows five strategies for the unbreakable string that breaks more banners than anything else. Every bar is scoped under a .ba-NN prefix for no-collision pasting, guards prefers-reduced-motion, carries the correct aria-live and role semantics, and ports unchanged to React, Vue, Svelte, Astro, Next.js and Tailwind.

25 CSS Blockquotes preview

25 CSS Blockquotes

25 hand-coded CSS blockquote designs for SaaS testimonials, editorial pull quotes, documentation callouts, and developer engineering blogs: large decorative quotation marks with ::before / ::after glyphs, Tailwind CSS blockquote component, pure CSS callout / admonition boxes for Docusaurus / Mintlify / Nextra documentation, responsive center-aligned quote banners, modern minimalist left-border editorial style, animated CSS gradient border, classic left border, brutalist high-contrast, glassmorphism frosted card, glowing neon border, article pull quote with text-wrap, speech bubble chat-style, thick vertical accent rail, customer testimonial cards with avatar and star rating, inline highlighted text, marker highlight underline, floating drop-shadow, aurora gradient background, Twitter / X card style, multi-column newspaper editorial, IDE code-comment style, Markdown-compatible defaults, JavaScript testimonial quote slider, expandable read-more, and one-click copy button. 22 Pure CSS + 3 Light JS (slider, expand, copy). Every design scoped under .bq-NN prefix for no-collision pasting, prefers-reduced-motion guarded per WCAG 2.3.3, WCAG 2.2 AA accessible, framework-agnostic (React, Vue, Svelte, Astro, Next.js, Nuxt, Remix, SvelteKit).

Search CodeFronts

Loading…