At a glance
Grindr, in one page
Grindr's iOS app is an unapologetically dark, photo-first grid. The canvas is pure black (#000000) — not the softened "not-quite-black" of media apps, but true black, because the entire screen is wallpapered with profile photography and black is the frame that makes skin tones, lighting, and faces pop. The signature surface is the cascade: a dense, edge-to-edge 3-column grid of square profile thumbnails sorted by physical proximity, the closest person top-left. There is almost no chrome between you and the grid — Grindr's product thesis is immediacy, and the UI is built to disappear behind the photos.
The accent system is a single high-voltage color: Grindr Yellow (#FFDE00), the exact hue of the brand mask logomark. It is rationed hard. Yellow appears on the primary action (the "Tap" / send-interest button, the active send arrow), on the active bottom-tab item, on unread badges, and on the brand mask itself. Online presence uses a separate semantic green dot (#4CD964) overlaid on the thumbnail corner. Everything else is white, gray, or near-black surface. The restraint is what makes the yellow read as "act now."
Typography is a clean grotesque — Grindr's product type, rendered here with Inter as the closest free substitute, at weights 400 / 700. The hierarchy is compact and overlay-driven: most text lives *on top of* photos as small, high-contrast labels (a display name at 15pt bold, a distance tag at 12pt bold), protected by a subtle bottom gradient scrim so it stays legible over any image. There are no large editorial headlines — the photos are the headline. The most expressive type moment is the profile sheet, where the display name jumps to 24pt bold over the hero photo.
Key Characteristics:
- True-black canvas (
#000000) — the photo grid *is* the interface - Grindr Yellow (
#FFDE00) as the only accent — Tap action, active tab, badges, mask logo - Dense cascade: edge-to-edge 3-column square thumbnail grid sorted by proximity
- Online green dot (
#4CD964) — presence indicator overlaid on the thumbnail corner - Distance label overlaid bottom-left on each tile ("220 ft", "0.4 mi") with a gradient scrim
- Profile sheet — full-bleed hero photo, slides up from the grid
- Mask logomark — flat yellow, the single brand mark
- Lazy-load fade — thumbnails decode and fade in as you scroll the cascade
- Tap action — the signature interest gesture, a yellow flame/tap button
Do's and don'ts
Do
- Use pure black
#000000as the canvas — the photo grid needs a true-black frame - Reserve Grindr Yellow (
#FFDE00) for the Tap action, active tab, badges, and the mask logo - Use black text/icons (
#000000) on yellow — it is intentional for maximum contrast - Build the cascade as a 3-column edge-to-edge square grid with a 2pt gutter and 0pt tile radius
- Overlay name + distance on a
rgba(0,0,0,0.65)bottom scrim so text reads over any photo - Use the green dot (
#4CD964) for online presence; absence of the dot means offline - Make overlay text weight 700 — never thin or unprotected over imagery
- Fade thumbnails in (180ms) as they decode while scrolling the cascade
- Use Inter (or the Grindr grotesque) at weights 400/700 only
Don't
- Don't use a softened off-black canvas — Grindr is true
#000000, the photos demand it - Don't add accent colors beyond yellow + the green presence dot — restraint makes yellow urgent
- Don't round the cascade tiles — the square, near-touching grid is the brand
- Don't place light or unscrimmed text over a profile photo — always scrim + bold
- Don't show a gray "offline" dot — offline is simply the absence of the green dot
- Don't use semibold or thin weights — the ramp is 400/700 only
- Don't box or letterbox profile photos — they go full-bleed
- Don't use yellow as a text color outside the active tab label — yellow is a fill
- Don't animate the grid aggressively — the only ambient motion is the lazy-load fade
Copy this into your AI builder
Paste it as-is. Every value below was measured from the original site, not guessed.
Assembled from the measured tokens — the source document has no prompt block.
Build a page in the Grindr design language. Follow the measured tokens below — do not substitute your own palette.
Colors:
- Grindr Yellow: #ffde00
- Yellow Pressed: #e6c700
- Yellow Tint: #fff2a8
- Canvas Black: #000000
- Surface 1: #1a1a1a
- Surface 2: #222222
- Surface 3: #2c2c2c
- Divider: #2c2c2c
- Text Primary: #ffffff
- Text Secondary: #999999
Type:
- families: Inter, Fallback Stack
- scale: 10, 11, 12, 13, 15, 16, 18, 22, 24
- weights: 400, 700
Shape:
- radius: 0, 12, 18, 22
Spacing: 8, 12, 20
Rules:
- Use pure black `#000000` as the canvas — the photo grid needs a true-black frame
- Reserve Grindr Yellow (`#FFDE00`) for the Tap action, active tab, badges, and the mask logo
- Use black text/icons (`#000000`) on yellow — it is intentional for maximum contrast
- Build the cascade as a 3-column edge-to-edge square grid with a 2pt gutter and 0pt tile radius
- Overlay name + distance on a `rgba(0,0,0,0.65)` bottom scrim so text reads over any photo
- Use the green dot (`#4CD964`) for online presence; absence of the dot means offline
Avoid:
- Don't use a softened off-black canvas — Grindr is true `#000000`, the photos demand it
- Don't add accent colors beyond yellow + the green presence dot — restraint makes yellow urgent
- Don't round the cascade tiles — the square, near-touching grid is the brand
- Don't place light or unscrimmed text over a profile photo — always scrim + bold
- Don't show a gray "offline" dot — offline is simply the absence of the green dot
- Don't use semibold or thin weights — the ramp is 400/700 only
Keep every value literal. If a token is given, use that exact value.
The specification
Colour paletteRead the full spec
Primary
- Grindr Yellow (
#FFDE00): Primary CTA, "Tap" button, send arrow active, active bottom-tab item, unread badge, mask logomark. - Yellow Pressed (
#E6C700): Active/pressed state for yellow CTAs. - Yellow Tint (
#FFF2A8): Subtle yellow highlight on selected chips or focused fields (used sparingly).
Canvas & Surfaces (Dark-only)
- Canvas Black (
#000000): Primary canvas — the cascade grid background, behind all photos. - Surface 1 (
#1A1A1A): Card backgrounds, list rows, the tab bar fill. - Surface 2 (
#222222): Higher elevation — sheets, modals, message bubbles (incoming). - Surface 3 (
#2C2C2C): Pressed state on dark surfaces, hairline-adjacent fills. - Divider (
#2C2C2C): Hairline between list rows and message groups. - Text Primary (
#FFFFFF): Display names, headlines, primary UI text. - Text Secondary (
#999999): Distance, metadata, timestamps, placeholders, inactive tabs. - Text Tertiary (
#5C5C5C): Disabled labels, very low-emphasis captions.
Photo Overlay
- Scrim Gradient: Bottom-anchored vertical gradient on each thumbnail from
rgba(0,0,0,0)(top) torgba(0,0,0,0.65)(bottom ~40%) so overlaid name/distance text stays legible over any photo. - Overlay Text (
#FFFFFF): Name and distance labels rendered on the scrim.
Semantic
- Online Green (
#4CD964): Active "online now" presence dot on the thumbnail corner and profile. - Fresh Yellow (
#FFDE00): "New here" / fresh-profile ribbon (reuses the brand yellow). - Error Red (
#FF3B30): Connection lost, blocked-user states, failed send. - Info Blue (
#3D8BFF): Links in settings and policy text.
Light Mode (Limited Use)
Grindr's iOS app is effectively dark-only — the photo grid demands a black frame. A light variant exists only for static / embed contexts.
- Light Canvas (
#FFFFFF) - Light Text (
#000000)
Type scaleRead the full spec
Font Family
- Primary: Grindr product grotesque (custom; brand-aligned)
- Substitute / Fallback:
Inter— closest free grotesque match - Fallback Stack:
-apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Helvetica Neue', Helvetica, Arial, sans-serif - Overlay legibility: All on-photo text is weight 700 with a scrim behind it — never thin over imagery
Hierarchy
| Role | Font | Size | Weight | Line Height | Letter Spacing | Notes |
|---|---|---|---|---|---|---|
| Profile Name (Hero) | Inter | 24pt | 700 | 1.15 | -0.3pt | Display name on the profile sheet hero |
| Screen Title | Inter | 22pt | 700 | 1.2 | -0.2pt | "Messages", "Taps", nav titles |
| Section Header | Inter | 18pt | 700 | 1.25 | -0.1pt | "Online now", "New near you" |
| Tile Name (Overlay) | Inter | 15pt | 700 | 1.2 | 0pt | Display name overlaid on a grid tile |
| List Row Title | Inter | 16pt | 700 | 1.3 | -0.1pt | Name in a message/tap list row |
| Body | Inter | 15pt | 400 | 1.45 | 0pt | Profile "About", message text |
| Message Text | Inter | 16pt | 400 | 1.35 | 0pt | Chat bubble copy |
| Metadata | Inter | 13pt | 400 | 1.3 | 0pt | "Active 5 min ago", row subtitle |
| Distance Tag (Overlay) | Inter | 12pt | 700 | 1.0 | 0.2pt | "220 ft" / "0.4 mi" on the tile scrim |
| Caption / Count | Inter | 12pt | 400 | 1.3 | 0pt | "12 new", small counts |
| Label (UPPER) | Inter | 11pt | 700 | 1.2 | 0.6pt | "ONLINE NOW" section labels |
| Button (Primary) | Inter | 16pt | 700 | 1.0 | 0.2pt | Yellow "Tap" / "Send" buttons |
| Tab Label | Inter | 10pt | 700 | 1.0 | 0.2pt | Bottom tab bar labels |
Principles
- Weights at 400 / 700 only: Regular for body and metadata, bold for names, titles, and all overlay text — no semibold, no thin
- Overlay text is always bold + scrimmed: never place light or unprotected text over a photo
- Negative tracking on large titles: -0.3pt at 24pt; body sits at 0pt; overlay tags get +0.2pt for legibility
- Dynamic Type respected on lists and chat: grid overlay labels are pinned (layout-sensitive over photos)
- Yellow text is reserved for the active tab label; elsewhere yellow is a fill, not a text color
Components and layoutRead the full spec
Buttons
Primary "Tap" Button (The Yellow Interest Action)
- Shape: Circle or pill, 56pt diameter (circular on profile) / full-pill (in action rows)
- Background:
#FFDE00 - Icon/Text:
#000000(intentionally black for max contrast on yellow) - Icon: flame / tap glyph 24pt, or "Tap" label in 16pt w700
- Pressed: scale 0.92, background
#E6C700, with haptic - Sent state: brief scale bounce + glyph swap to a filled check, then fades to a "Tapped" outline state
Primary Pill (Send / Chat / Unlock)
- Background:
#FFDE00 - Text:
#000000 - Padding: 12pt vertical, 28pt horizontal
- Corner radius: 500pt (full pill)
- Font: Inter, 16pt, weight 700, +0.2pt tracking
- Pressed:
#E6C700, scale 0.97
Outline Pill ("Tapped" / "Blocked")
- Background: transparent
- Text:
#FFFFFF - Border: 1pt solid
#999999 - Padding: 12pt vertical, 24pt horizontal, corner radius 500pt
- Font: Inter, 15pt, weight 700
- Pressed: border
#FFFFFF
Icon Action (Tap, Favorite, Block, More, Photo)
- Size: 24pt glyph, 44pt hit area
- Default:
#FFFFFF(on photo) /#999999(on dark surface) - Active:
#FFDE00(tapped, favorited) - Spacing: 20pt between icons in the profile action bar
Text Button ("See all", "Edit profile")
- Font: Inter, 14pt, weight 700
- Color:
#999999 - No background, no underline, 44pt hit area
Cards & Containers
Cascade Grid Tile (The Signature)
- Square, 3-column edge-to-edge grid, 2pt gutter
- Corner radius: 0pt (tiles touch — a wall of presence)
- Content: full-bleed profile photo, cover-cropped
- Overlay (bottom): a
rgba(0,0,0,0.65)scrim, name (15pt w700 white, 1-line) + distance (12pt w700 white, +0.2pt) - Top-right: online green dot (
#4CD964), 10pt, 2pt black ring - Top-left (optional): "NEW" yellow ribbon for fresh profiles
- Pressed: scale 0.97 + subtle dim, opens the profile sheet
Profile Sheet
- Full-bleed hero photo (device width, ~480pt tall), swipeable photo carousel with dot indicators
- Slides up from the cascade with a shared-element photo transition
- Below the fold: name (24pt w700) + age, distance row, "About" body (15pt w400), stats grid
- Bottom action bar pinned: Favorite, large yellow "Tap" / "Chat" button, Block/More
- Background below the photo:
#000000
Message List Row
- Height: 72pt
- Layout: 52pt circular avatar (with online dot) → name (16pt w700) + last message preview (13pt w400
#999999, 1-line) → trailing timestamp (12pt) + unread yellow dot - Background:
#000000; Pressed:#1A1A1A - Unread: name stays white, preview brightens, a
#FFDE008pt dot trails
Chat Bubble
- Incoming: background
#222222, text#FFFFFF, corner radius 18pt (4pt on the tail corner) - Outgoing: background
#FFDE00, text#000000, corner radius 18pt (4pt on the tail corner) - Max width 76% of screen, 10pt vertical / 14pt horizontal padding
- Timestamp: 11pt
#999999below the last bubble in a group
Filter / Tag Chip
- Background:
#1A1A1Adefault /#FFDE00selected - Text:
#FFFFFFdefault /#000000selected - Padding: 8pt vertical, 16pt horizontal, corner radius 500pt
- Font: Inter, 13pt, weight 700
Navigation
Bottom Tab Bar
- Height: 52pt + safe area
- Background:
rgba(0,0,0,0.94)with.regularMaterialblur, 0.5pt top divider#2C2C2C - Tabs: Browse, Taps, Messages, Profile
- Icon size: 26pt
- Active color:
#FFDE00(icon + label) - Inactive:
#999999 - Labels: Inter 10pt w700, always shown
- Badge: yellow
#FFDE00pill with black count text on Taps / Messages
Top Bar (in-grid)
- Height: 44pt + safe area
- Left: yellow mask logomark (24pt)
- Center: location / cascade title (18pt w700) or filter chip row
- Right: filter icon (22pt) + settings (22pt),
#FFFFFF - Translucent black blur on scroll
Input Fields
Message Composer
- Background:
#1A1A1A, corner radius 22pt, min height 44pt - Placeholder: "Send a message", 16pt w400
#999999 - Leading photo/camera icon (22pt
#999999), trailing send arrow - Send arrow:
#999999when empty →#FFDE00filled circle when text present - Focused: 1pt
#FFDE00ring (subtle)
Search Field
- Background:
#1A1A1A, height 44pt, corner radius 12pt - Leading
magnifyingglass18pt#999999 - Placeholder: "Search", 16pt w400
#999999 - Focused: background
#222222, 1pt#FFDE00ring
Distinctive Components
Proximity Thumbnail Cascade
- The defining surface: an edge-to-edge wall of square photos, sorted nearest-first, 3 columns, 2pt gutter, 0pt radius
- Infinite scroll, virtualized; new tiles decode and fade in (180ms opacity) as you reach them
- Each tile fuses a photo + a presence dot + a scrimmed name/distance overlay into one tap target
Online Presence Dot
- 10pt circle,
#4CD964, 2pt#000000ring, top-right of every tile and avatar - Solid = online now; absent = offline (no gray dot — absence is the offline state)
Distance Scrim Label
- The bottom ~40% of each tile carries a
rgba(0,0,0,0.65)gradient so the 12pt bold distance and 15pt bold name read over any photo without a solid bar
Tap Send Animation
Responsive behaviourRead the full spec
Device Sizes
| Device | Width | Key Changes |
|---|---|---|
| iPhone SE (3rd gen) | 375pt | 3-col cascade (~124pt tiles); profile hero ~420pt |
| iPhone 13/14/15 | 390pt | Standard 3-col cascade (~129pt tiles) |
| iPhone 15/16 Pro | 393pt | Dynamic Island accommodated in the top bar |
| iPhone 15/16 Pro Max | 430pt | Optional 4-col cascade toggle; hero ~520pt |
| iPad | 768pt+ | 5–6 col cascade; profile opens as a side panel, not a full sheet |
Dynamic Type
- Chat text, message-list names, profile body: full scale
- Grid overlay name + distance: pinned (layout-sensitive over photos)
- Tab labels: fixed 10pt
- Profile hero name: scales up to 28pt before clamping
Orientation
- Cascade / Messages / Profile: portrait-locked (the grid is tuned for portrait density)
- Full-screen photo viewer: rotates to fit landscape images
- iPad: all orientations, cascade recolumns fluidly
Touch Targets
- Cascade tile: full tile tappable (~129pt) — the entire photo is the target
- Tap button: 56pt circle — large and central on the profile
- List rows: 72pt height, full-row tappable
- Tab bar icons: 26pt glyph, 44pt effective hit
- Send arrow / icon actions: 24pt glyph, 44pt hit area
Safe Area Handling
- Top: top bar + filter chips respect safe area and Dynamic Island
- Bottom: tab bar respects the home indicator; chat composer floats above the keyboard
- Cascade: goes edge-to-edge horizontally (intentional), respects top/bottom safe area
- Profile hero: extends under the status bar with a top scrim for control legibility
Drop-in CSS variables
The same values as a theme block. Add the class to <body> and the site repaints.
body.theme-grindr {--page-bg: #000000;
--page-bg-gradient: none;
--text-color: #ffffff;
--heading-color: #ffffff;
--link-color: #ffde00;
--link-hover-color: #ccb200;
--border-color: #2e2e2e;
--card-bg: #000000;
--card-shadow: 0 1px 2px rgba(255,255,255,0.06);
--card-hover-shadow: 0 6px 18px rgba(255,255,255,0.12);
--header-bg: #141414;
--header-text-color: #ffffff;
--header-shadow: none;
--footer-bg: #000000;
--footer-text-color: #a6a6a6;
--button-bg: #ffde00;
--button-text-color: #000000;
--button-hover-bg: #ccb200;
--button-border: none;
--button-border-radius: 18px;
--button-secondary-bg: #0f0f0f;
--button-secondary-text-color: #ffffff;
--button-secondary-hover-bg: #1f1f1f;
--button-secondary-border: 1px solid #2e2e2e;
--prompt-bg: #0d0d0d;
--prompt-text-color: #ffffff;
--base-font: var(--font-inter);
--heading-font: var(--font-inter);
--card-border-radius: 18px;
}
Visually close to
Measured with a deterministic colour + geometry comparison across 958 styles. Not a hand-picked list.
- coffee meets bagel 83.1%
- clubhouse 83.0%
- 1616arita 80.1%
- graphpaper 76.0%
- walmart 75.9%
Where this came from
- Source document
ios/design-md/dating/grindr/DESIGN.md· 20.7 KB- Repository
- Meliwat/awesome-ios-design-md
- Licence
- MIT
Source text is reproduced under its original licence. Tokens, similarity scores and page structure are ours.