
Inline HTML Kbd Tag Basic Styling
Published
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.
Related20 CSS Code Blocks36 CSS Search Bars21 CSS Tooltips30 CSS Badges

Published

Published

Published

Published

Published

Published

Published

Published

Published
Published

Published

Published

Published

Published

Published

Published

Published

Published

Published

Published
<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.<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.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.: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.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.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.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..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.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 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 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).