Vercel's interface is minimalism elevated to an engineering principle. Every pixel serves a purpose, every absence of ornament is a deliberate choice. The visual language strips away the superfluous — no gradients, no decorative borders, no color for color's sake — leaving behind a monochromatic canvas where content and function occupy the entire foreground. The background is a near-white rgb(250, 250, 250), text is a near-black rgb(23, 23, 23), and between them sits a precisely calibrated grayscale that communicates hierarchy without ever raising its voice.
What makes Vercel's design language remarkable is its relentless restraint. Color appears only when it must: blue rgb(0, 114, 245) marks interactive elements and focus states, and nothing else. Status indicators — greens, ambers, reds, purples — exist in small dot-sized badges (div.size-2.5), never as background fills or large swaths. The result is an interface that feels engineered rather than designed, where every visual decision can be justified by a functional requirement. Shadows replace borders. Weight replaces size. Spacing replaces dividers.
The atmosphere is one of quiet confidence — the kind of UI that a developer trusts instinctively because it never tries to impress. It communicates through density of information and precision of layout, powered by 96 custom CSS properties that form one of the most comprehensive design token systems on the web.
| Role | Value | CSS Source | Usage |
|---|---|---|---|
| Background (primary) | rgb(250, 250, 250) / #FAFAFA |
body backgroundColor |
Page canvas, surface base |
| Background (elevated) | rgb(255, 255, 255) / #FFFFFF |
card/link surfaces | Cards, modals, elevated panels |
| Background (recessed) | rgb(242, 242, 242) / #F2F2F2 |
switch control surface | Toggle tracks, input backgrounds |
| Text (primary) | rgb(23, 23, 23) / #171717 |
body color |
Headings, primary content |
| Text (secondary) | rgb(77, 77, 77) / #4D4D4D |
button color |
Navigation items, secondary labels |
| Text (muted) | rgb(143, 143, 143) / #8F8F8F |
grayLine surface | Decorative lines, disabled states |
| Interactive accent | rgb(0, 114, 245) / #0072F5 |
link color, focus ring |
Links, focus rings, active states |
| Focus ring (alt) | rgb(0, 95, 204) / #005FCC |
input focus outline |
Native input focus indicators |
These colors appear exclusively as small indicator dots (div.size-2.5 — approximately 10px) and never as large fills:
| Color | Value | Hex |
|---|---|---|
| Blue | rgb(0, 98, 209) |
#0062D1 |
| Cyan | rgb(82, 174, 255) |
#52AEFF |
| Teal (light) | rgb(69, 222, 197) |
#45DEC5 |
| Teal (dark) | rgb(6, 122, 110) |
#067A6E |
| Green (dark) | rgb(57, 142, 74) |
#398E4A |
| Green (medium) | rgb(69, 165, 87) |
#45A557 |
| Green (light) | rgb(108, 218, 117) |
#6CDA75 |
| Orange | rgb(255, 153, 10) |
#FF990A |
| Red | rgb(229, 72, 77) |
#E5484D |
| Pink | rgb(234, 62, 131) |
#EA3E83 |
| Purple (dark) | rgb(120, 32, 188) |
#7820BC |
| Purple (light) | rgb(191, 137, 236) |
#BF89EC |
| Token | Value | Role |
|---|---|---|
--ds-shadow-background-border |
0 0 0 1px var(--ds-background-200) |
Surface-aware border layer |
--ds-shadow-border-base |
0 0 0 1px #00000014 |
Universal border simulation |
--ds-shadow-border |
var(--ds-shadow-border-base), var(--ds-shadow-background-border) |
Combined default border |
--ds-focus-ring |
0 0 0 2px var(--ds-background-100), 0 0 0 4px var(--ds-focus-color) |
Double-ring focus pattern |
--ds-overlay-backdrop-color |
var(--ds-background-200) |
Modal/overlay backdrop |
--ds-overlay-backdrop-opacity |
.8 |
Backdrop transparency |
--geist-text-gradient |
linear-gradient(180deg, #000c 0%, #000 100%) |
Text gradient effect (marketing) |
--header-border-bottom |
0 1px 0 0 #0000001a |
Header separator shadow |
--header-import-flow-background |
#fafafacc |
Semi-transparent overlay |
Vercel is fundamentally achromatic. The interface operates within a 4-stop grayscale: #FAFAFA → #F2F2F2 → #EBEBEB → #171717. Blue (#0072F5) is the sole interactive accent — it appears in links, focus rings, and the skip-to-content indicator, and nowhere else. Every other color is confined to status indicator dots no larger than 10px, enforcing a strict hierarchy where chromatic information signals data, never decoration.
Vercel uses its proprietary Geist font family — a typeface designed specifically for developer tooling interfaces. Two variants serve distinct purposes:
- Geist Sans — all interface text (headings, body, navigation, buttons, labels)
- Geist Mono — code blocks and monospaced content, with fallback to
ui-monospace, SFMono-Regular, "Roboto Mono"
Both fonts enable OpenType ligatures via font-feature-settings: "liga".
| Element | Size | Weight | Line Height | Letter Spacing | Role |
|---|---|---|---|---|---|
h1 |
48px | 600 | 48px (1.0) | -2.28px | Hero headlines |
h3 |
32px | 600 | 40px (1.25) | -1.28px | Section titles |
h2 |
14px | 500 | 20px (1.43) | -0.28px | Subsection labels |
h5 |
14px | 400 | 20px (1.43) | normal | Tertiary headings |
body |
16px | 400 | normal | normal | Base reading text |
a |
16px | 400 | normal | normal | Inline links |
button |
14px | 400 | 14px (1.0) | normal | Button labels |
label |
14px | 400 | 20px (1.43) | normal | Form labels |
p |
12px | 400 | 16px (1.33) | normal | Small body text, captions |
code |
13px | 500 | 20px (1.54) | normal | Code snippets (Geist Mono) |
pre |
13px | 500 | 20px (1.54) | normal | Code blocks |
input |
13.3px | 400 | normal | normal | Form inputs |
Vercel uses exactly three font weights — and deliberately excludes bold (700):
| Weight | Name | Usage |
|---|---|---|
| 400 | Regular | Body text, links, buttons, labels, form elements |
| 500 | Medium | Code blocks, subsection headings (h2), UI emphasis |
| 600 | Semibold | Display headings only (h1, h3) |
There is no weight 700 anywhere in the system. This constraint is philosophical: Vercel considers semibold sufficient for emphasis, and true bold too heavy for a minimalist interface. Emphasis is communicated through size and spacing, not weight.
Vercel's most distinctive typographic trait is extreme negative tracking on headlines:
h1at 48px: -2.28px (approximately -4.75% of font size)h3at 32px: -1.28px (approximately -4% of font size)h2at 14px: -0.28px (-2% of font size)
This tightening creates a sense of density and precision at display sizes, reinforcing the engineered aesthetic. At body sizes (16px and below), letter-spacing returns to normal.
| Token | Value | Usage |
|---|---|---|
--geist-form-large-font |
1rem (16px) | Large form inputs |
--geist-form-large-line-height |
1.5rem (24px) | Large form line height |
--geist-form-font |
.875rem (14px) | Default form inputs |
--geist-form-line-height |
1.25rem (20px) | Default form line height |
--geist-form-small-font |
.875rem (14px) | Small form inputs |
--geist-form-small-line-height |
.875rem (14px) | Small form line height |
Vercel buttons follow a ghost-first pattern — default state is fully transparent, with hover and focus providing visual feedback:
| State | Background | Text Color | Box Shadow | Outline |
|---|---|---|---|---|
| Default | transparent |
rgb(77, 77, 77) |
none | none |
| Hover | rgb(235, 235, 235) |
rgb(23, 23, 23) |
none | none |
| Focus | ~transparent |
rgb(23, 23, 23) |
#FFF 0 0 0 2px, #0072F5 0 0 0 4px |
none |
Key observations:
- Hover fills with a subtle gray (
#EBEBEB) and promotes text from secondary to primary color - Focus applies the signature double-ring pattern: a 2px white inner ring creates separation from the element, then a 4px blue outer ring provides the visible indicator
- No
transform,opacity, ortransitionchanges — interactions are purely color-based
| Variant | Default Color | Focus Behavior |
|---|---|---|
| Standard link | rgb(23, 23, 23) |
outline: rgb(0, 114, 245) auto 2px |
| Navigation link | rgb(77, 77, 77) |
outline: rgb(0, 114, 245) auto 2px |
| Skip-to-content | rgb(0, 114, 245) |
opacity: 0 -> 1, double-ring focus |
| State | Background | Box Shadow | Outline |
|---|---|---|---|
| Default | transparent |
none | none |
| Focus | transparent |
none | rgb(0, 95, 204) auto 1px |
Note the focus blue for inputs (#005FCC) differs slightly from the button focus blue (#0072F5) — a darker shade for the thinner 1px outline ensures equivalent visual weight.
Vercel's most distinctive interaction pattern, defined as --ds-focus-ring:
0 0 0 2px var(--ds-background-100), /* White inner ring — gap */
0 0 0 4px var(--ds-focus-color) /* Blue outer ring — indicator */
This creates a 2px white buffer between the element and the blue focus ring, ensuring the ring is visible against any background — including elements that are themselves blue.
| Value | Usage |
|---|---|
6px |
Default component radius (--geist-radius) |
8px |
Marketing components (--geist-marketing-radius) |
12px |
Cards, elevated panels |
12px 12px 0px 0px |
Top-anchored panels (drawers, sheets) |
50% / 100% |
Avatars, circular indicators |
9999px / 64px / 100px |
Pill shapes (tags, badges, full-round buttons) |
| Size | Height Token | Value |
|---|---|---|
| Small | --geist-form-small-height |
var(--geist-space-small) = 32px |
| Default | --geist-form-height |
var(--geist-space-medium) = 40px |
| Large | --geist-form-large-height |
var(--geist-space-large) = 48px |
Vercel's spacing system uses a 4px base unit with multiplier naming:
| Token | Value | Multiplier |
|---|---|---|
--geist-space |
4px | 1x |
--geist-space-2x |
8px | 2x |
--geist-space-3x |
12px | 3x |
--geist-space-4x |
16px | 4x |
--geist-space-6x |
24px | 6x |
--geist-space-8x |
32px | 8x |
--geist-space-10x |
40px | 10x |
--geist-space-16x |
64px | 16x |
--geist-space-24x |
96px | 24x |
--geist-space-32x |
128px | 32x |
--geist-space-48x |
192px | 48x |
--geist-space-64x |
256px | 64x |
Note the scale is not linear — it jumps from 10x to 16x, skipping 12x and 14x. The usable range spans from 4px to 256px (a 64:1 ratio).
| Token | Value | Usage |
|---|---|---|
--geist-space-small |
32px | Small component height, compact sections |
--geist-space-medium |
40px | Default component height |
--geist-space-large |
48px | Large component height, generous sections |
--geist-space-gap |
24px | Default gap between elements |
--geist-space-gap-half |
12px | Tight gap |
--geist-space-gap-quarter |
8px | Minimal gap |
--geist-gap-double |
48px | Double-width gap |
Every spacing value has a corresponding negative token (e.g., --geist-space-4x-negative: -16px), enabling precise pull-back positioning for overlapping elements and negative margins — 15 negative tokens total.
| Token | Value | Usage |
|---|---|---|
--geist-page-width |
1200px | Standard content width |
--ds-page-width |
1400px | Design system / wider content |
--geist-page-margin |
24px (= --geist-space-gap) |
Horizontal page padding |
--geist-page-width-with-margin |
calc(1200px + 48px) |
Full width including margins |
--header-height |
64px | Fixed header height |
--header-sub-menu-height |
46px | Sub-navigation bar |
--banner-min-height |
64px | Announcement banner |
| Element | Padding | Gap |
|---|---|---|
main |
0 16px |
— |
header |
0 24px |
32px |
footer |
40px 24px |
— |
section |
0 |
— |
Vercel's most technically distinctive pattern: box-shadow replaces CSS border entirely. Instead of border: 1px solid, Vercel uses:
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08);This 0px 0px 0px 1px shadow — zero offset, zero blur, 1px spread — creates a visually identical border without affecting box-model dimensions. Benefits:
- No layout shift — borders add to element dimensions (unless using
box-sizing); shadows do not - Composable — multiple shadow layers can be stacked in a single
box-shadowdeclaration - Smooth transitions — shadows animate more smoothly than border-color changes
- Layered borders — a single element can have multiple "border" rings at different offsets
| Level | Token | Value | Usage |
|---|---|---|---|
| Border only | --ds-shadow-border |
0 0 0 1px #00000014, 0 0 0 1px var(--ds-background-200) |
Default card/container boundary |
| Small | --ds-shadow-border-small |
Border + 0px 2px 2px #0000000a |
Slightly raised elements |
| Medium | --ds-shadow-border-medium |
Border + 0px 2px 2px #0000000a, 0px 8px 8px -8px #0000000a |
Cards, dropdowns |
| Large | --ds-shadow-border-large |
Border + 0px 2px 2px #0000000a, 0px 8px 16px -4px #0000000a |
Popovers, floating panels |
| Tooltip | --ds-shadow-tooltip |
Border + 0px 1px 1px #00000005, 0px 4px 8px #0000000a |
Tooltip containers |
| Menu | --ds-shadow-menu |
Border + 0px 1px 1px #00000005, 0px 4px 8px -4px #0000000a, 0px 16px 24px -8px #0000000f |
Dropdown menus |
| Modal | --ds-shadow-modal |
Border + 0px 1px 1px #00000005, 0px 8px 16px -4px #0000000a, 0px 24px 32px -8px #0000000f |
Modal dialogs |
| Fullscreen | --ds-shadow-fullscreen |
Same as modal | Fullscreen overlays |
Every elevated shadow composes three layers:
- Border layer (
--ds-shadow-border-base):0 0 0 1px #00000014— the universal 1px "border" - Depth layer: Actual drop shadow with increasing blur/offset per elevation
- Background border (
--ds-shadow-background-border):0 0 0 1px var(--ds-background-200)— surface-aware ring
| Shadow | Semantic Role |
|---|---|
rgb(235, 235, 235) 0px 0px 0px 1px |
Light border ring (hover state, #EBEBEB) |
rgba(0, 0, 0, 0.08) 0px 0px 0px 1px |
Standard border simulation |
rgba(0, 0, 0, 0.04) 0px 2px 2px 0px |
Micro-elevation (subtle lift) |
rgb(255, 255, 255) 0px 0px 0px 2px, rgb(0, 114, 245) 0px 0px 0px 4px |
Focus double-ring |
| Complex 3-layer composite | Card with border + small shadow + background ring |
| Complex 5-layer composite | Menu/tooltip with border + multi-depth + background ring |
| Complex 6-layer composite | Elevated card with null resets + border + medium depth |
| Token | Value | Usage |
|---|---|---|
--ds-motion-timing-swift |
cubic-bezier(.175, .885, .32, 1.1) |
Snappy overshoot easing |
--ds-motion-overlay-scale |
.96 |
Overlay entrance scale |
--ds-motion-overlay-duration |
.3s |
Overlay animation duration |
--ds-motion-popover-duration |
.2s |
Popover animation (faster) |
The "swift" timing function overshoots slightly (ending value 1.1), creating a subtle bounce that makes overlays feel alive without being playful.
- Do use shadow-as-border — Replace
border: 1px solidwithbox-shadow: 0 0 0 1pxfor all container boundaries. This is Vercel's core visual technique. - Do limit font weights to 400/500/600 — Never use 700 (bold). Emphasis comes from size and spacing, not weight. Semibold (600) is reserved for display headings only.
- Do apply aggressive negative letter-spacing on headlines — Use approximately -4% to -4.75% tracking at 32px+ sizes. Headlines should feel dense and engineered.
- Do use the double-ring focus pattern — Always implement
0 0 0 2px white, 0 0 0 4px bluefor keyboard focus. The white inner ring ensures visibility on any background. - Do keep color achromatic — The interface is black, white, and gray. Blue (
#0072F5) is the only interactive color. Status colors appear only as small indicator dots. - Do compose shadows in layers — Build elevation by stacking border-shadow + depth-shadow + background-border in a single
box-shadowdeclaration. - Do use the 4px spacing base — All spacing should be multiples of 4px, using the
--geist-space-*token scale.
- Don't use CSS
borderfor containers — Borders affect box-model layout. Usebox-shadow: 0 0 0 1pxinstead for visual boundaries. - Don't use font-weight 700 or higher — The Geist type system caps at 600 (semibold). Bold text violates the minimalist aesthetic and creates unnecessary visual weight.
- Don't introduce new accent colors — The interface is achromatic by design. If you need a new status color, use it only at indicator-dot scale (approximately 10px), never as backgrounds or large fills.
- Don't use decorative gradients or patterns — The only gradient in the system is
--geist-text-gradient, a subtle black text effect. Background gradients, stripes, and patterns are absent. - Don't animate with
transformoropacityon interactive elements — Vercel buttons and links change onlybackground-colorandcoloron hover. No scale, translate, or fade effects. - Don't use rounded corners larger than 12px on functional UI —
border-radius: 6pxis the standard. 12px is for cards. Pill shapes (9999px) are for badges and tags only. - Don't add divider lines between sections — Vercel uses spacing (the
--geist-space-gapsystem) and subtle surface color changes to separate content, not<hr>or border lines.
Vercel uses an unusually granular set of 45 breakpoints, far exceeding the typical 5-7 breakpoints of most design systems. This is not arbitrary — it reflects component-level responsive tuning where individual components define their own adaptation points.
| px | Likely Target |
|---|---|
| 370, 374, 375 | iPhone SE / iPhone 12 mini |
| 383, 384 | Pixel 5 / narrow Androids |
| 400, 401 | Wide phone threshold |
| 427 | iPhone 14 Pro Max |
| 440, 450 | Phablet territory |
| 470, 480 | Large phone / small tablet boundary |
| 500 | Max mobile width |
| px | Likely Target |
|---|---|
| 600, 601 | Small tablet threshold |
| 610, 640 | Portrait tablet |
| 650, 660, 670 | Mid-tablet adjustments |
| 750 | Large portrait tablet |
| 768, 769 | iPad portrait (classic breakpoint) |
| 800 | Landscape phone / small landscape tablet |
| px | Likely Target |
|---|---|
| 960, 961 | Tablet landscape / small desktop |
| 992 | Bootstrap-legacy desktop |
| 1000, 1020 | Narrow desktop |
| 1024 | iPad landscape (classic) |
| 1036, 1050 | Sidebar-adjusted content |
| 1080, 1100 | Common laptop resolution |
| 1108, 1120 | Content width transitions |
| 1150, 1151 | Pre-max-width threshold |
| px | Likely Target |
|---|---|
| 1200 | --geist-page-width — standard content max |
| 1240, 1248, 1250 | Content-with-margin region |
| 1400 | --ds-page-width — wide content max |
| 1600 | Large desktop / external monitor |
| 2300 | Ultrawide / 4K displays |
The clustering of breakpoints around certain ranges reveals Vercel's approach:
- 13 breakpoints below 600px — mobile is not one target, it is thirteen. Each component adapts independently.
- Dense clustering at 1020-1150px — the critical laptop range gets per-component tuning where sidebar presence/absence creates many intermediate states.
- Single jump from 1600 to 2300 — large screens get minimal special treatment; content is capped at
--ds-page-width: 1400px.
Background: #FAFAFA
Text primary: #171717
Text secondary: #4D4D4D
Interactive blue: #0072F5
Focus blue: #005FCC
Border shadow: 0 0 0 1px rgba(0,0,0,0.08)
Focus ring: 0 0 0 2px #FFF, 0 0 0 4px #0072F5
Font: Geist Sans (400/500/600), Geist Mono (500)
Radius: 6px (default), 12px (cards), 9999px (pills)
Spacing base: 4px (use multiples: 8, 12, 16, 24, 32, 40, 48)
Page width: 1200px (standard), 1400px (wide)
Header height: 64px
Easing: cubic-bezier(.175, .885, .32, 1.1)
Prompt 1: Dashboard Card
"Create a dashboard metrics card. Background
#FFFFFF, border usingbox-shadow: 0 0 0 1px rgba(0,0,0,0.08), no CSS border. Corner radius6px. Title in Geist Sans 14px weight 500 color#171717. Value in 32px weight 600 with letter-spacing-1.28px. Subtitle in 12px weight 400 color#4D4D4D. Padding24px. Status indicator as a10pxcircle dot using the appropriate status color."
Prompt 2: Navigation Bar
"Build a fixed header, height
64px, background#FAFAFA, bottom border asbox-shadow: 0 1px 0 0 rgba(0,0,0,0.1). Navigation items in Geist Sans 14px weight 400 color#4D4D4D. On hover: background#EBEBEB, text color#171717. On focus: double-ring shadow0 0 0 2px #FFF, 0 0 0 4px #0072F5. Horizontal padding24px, gap between items32px. Logo area left-aligned."
Prompt 3: Dropdown Menu
"Design a dropdown menu using shadow elevation
--ds-shadow-menu:box-shadow: 0 0 0 1px rgba(0,0,0,0.08), 0 1px 1px rgba(0,0,0,0.02), 0 4px 8px -4px rgba(0,0,0,0.04), 0 16px 24px -8px rgba(0,0,0,0.06). Background#FFFFFF, radius12px. Menu items 14px weight 400, padding8px 16px. Hover state: background#FAFAFA. Entrance animation: scale from0.96to1.0over0.2swithcubic-bezier(.175, .885, .32, 1.1)easing."
Prompt 4: Form Input
"Create a text input, height
40px(--geist-form-height), font Geist Sans14pxweight 400. Border asbox-shadow: 0 0 0 1px rgba(0,0,0,0.08). Radius6px. Padding horizontal12px. On focus: outlinergb(0, 95, 204) auto 1px, remove shadow border. Placeholder color#8F8F8F. Background transparent."
Prompt 5: Achromatic Page Layout
"Build a page layout: max-width
1200px, centered with24pxhorizontal margin. Background#FAFAFA. Section spacing using32pxgaps. All text in Geist Sans. Hero heading: 48px weight 600, letter-spacing-2.28px, color#171717. Body text: 16px weight 400, line-height normal. Links in#0072F5, no underline by default. No decorative elements, no gradients, no colored backgrounds. Dividers as spacing only."
Generated by Sparkbites — extracted from live CSS analysis