A live page in this style is not built yet — the CSS variables and the prompt below are enough to reproduce it.
At a glance
Twitch, in one page
Twitch's iOS app is a live-first surface built on a near-black canvas (#0E0E10) that keeps the focus on streamer video and the constant motion of chat. The background is a true near-black with the faintest cool tint, and elevated surfaces (#18181B, #1F1F23) step up in cool grays so cards, the chat column, and sheets separate without borders. The interface is dense and kinetic: thumbnails are live previews, viewer counts tick, the LIVE pill pulses, and chat scrolls continuously. The chrome is deliberately quiet so the energy comes from content and community.
The accent system is a duo with strict roles. Twitch Purple (#9146FF) is the brand and primary-action color — Follow, Subscribe, the active tab, links, and focus. Live Red (#EB0400) is reserved exclusively for liveness — the "● LIVE" pill and the now-live indicator. The two never blur: purple is "act," red is "this is happening right now." Everything else is white, cool gray, or near-black. This split is the core of Twitch's visual language — community action vs. live status.
Typography is Roobert (Twitch's brand typeface), rendered here with an Inter fallback that keeps its rounded-grotesque warmth. The hierarchy is compact and functional: 11-28pt at weights 400 / 600 / 700. There are no oversized editorial headlines — the live video and the streamer's thumbnail are the spectacle. Type labels and identifies: stream titles at 15-16pt weight 600, channel names at 14-15pt weight 700, metadata (game, viewers) at 12-13pt weight 400 in gray, section headers at 20-22pt weight 700. The most expressive type moment is the channel page, where the streamer's display name sits at 22pt weight 700 beside a live avatar ring.
Key Characteristics:
- Near-black canvas (
#0E0E10) with the faintest cool tint — quiet chrome, kinetic content - Twitch Purple (
#9146FF) for brand + primary action; Live Red (#EB0400) only for liveness - Live thumbnail cards — preview image + red "● LIVE" pill + viewer count + game/category tag
- Stream view with a docked chat column — video on top, continuously scrolling chat below
- Channel card — circular avatar with a purple/red live ring, display name, category
- Emote chips — inline emote/badge tokens in chat and the emote picker
- Live chat overlay — the signature community surface, semi-transparent over video in theater/landscape
- Roobert typeface (Inter fallback), weights 400/600/700
- LIVE pill pulse and viewer-count ticking — motion signals "happening now"
- Bottom tab bar: Following, Browse, Search, Notifications, Profile
Do's and don'ts
Do
- Use
#0E0E10near-black canvas — faint cool tint, quiet chrome so content/chat carry energy - Keep the color split strict: Twitch Purple (
#9146FF) = brand/action; Live Red (#EB0400) = liveness only - Use off-white
#EFEFF1for primary text — softer than pure white for long chat reading - Put the red "● LIVE" pill top-left and the black viewer-count pill bottom-left on live thumbnails
- Encode presence in the avatar ring — purple normally, red when currently LIVE
- Keep chat dense (4pt lines) and let live cards breathe (16pt gaps)
- In theater/landscape, float chat as a blurred 72%-opaque overlay on the right
- Make the active tab purple (icon + label) — purple is the indicator
- Treat emotes as first-class type tokens, baseline-aligned
Don't
- Don't use pure black
#000000for the app canvas — that's the theater/player surface only - Don't use Live Red for anything except liveness — it must always mean "happening now"
- Don't use Twitch Purple for the LIVE state — purple is action/brand, never status
- Don't use pure white
#FFFFFFfor body text —#EFEFF1is the intentional softer choice - Don't use thin or medium weights — Roobert here is 400 / 600 / 700 only
- Don't space chat loosely — community throughput depends on tight 4pt lines
- Don't introduce visible card borders — elevation is cool-gray surface-step + translucency
- Don't over-animate — card scale is subtle (1.03); the continuous motion is the LIVE pulse and chat scroll only
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 Twitch design language. Follow the measured tokens below — do not substitute your own palette.
Colors:
- Twitch Purple: #9146ff
- Purple Pressed: #772ce8
- Live Red: #eb0400
- Live Red Pressed: #c20300
- Canvas: #0e0e10
- Deep Black: #000000
- Surface 1: #18181b
- Surface 2: #1f1f23
- Surface 3: #2a2a2d
- Divider: #2a2a2d
Type:
- families: Roobert, Fallback Stack, Numerals
- scale: 10, 11, 12, 13, 14, 15, 16, 20, 22
- weights: 400, 600, 700
Shape:
- radius: 4, 6, 8
- elevation: Shadow: `rgba(145,70,255,0.35) 0 6px 18px` on the channel-page primary CTA
Spacing: 4, 8, 16
Rules:
- Use `#0E0E10` near-black canvas — faint cool tint, quiet chrome so content/chat carry energy
- Keep the color split strict: Twitch Purple (`#9146FF`) = brand/action; Live Red (`#EB0400`) = liveness only
- Use off-white `#EFEFF1` for primary text — softer than pure white for long chat reading
- Put the red "● LIVE" pill top-left and the black viewer-count pill bottom-left on live thumbnails
- Encode presence in the avatar ring — purple normally, red when currently LIVE
- Keep chat dense (4pt lines) and let live cards breathe (16pt gaps)
Avoid:
- Don't use pure black `#000000` for the app canvas — that's the theater/player surface only
- Don't use Live Red for anything except liveness — it must always mean "happening now"
- Don't use Twitch Purple for the LIVE state — purple is action/brand, never status
- Don't use pure white `#FFFFFF` for body text — `#EFEFF1` is the intentional softer choice
- Don't use thin or medium weights — Roobert here is 400 / 600 / 700 only
- Don't space chat loosely — community throughput depends on tight 4pt lines
Keep every value literal. If a token is given, use that exact value.
The specification
Colour paletteRead the full spec
Primary
- Twitch Purple (
#9146FF): Brand color, primary CTA (Follow / Subscribe), active tab icon + label, links, focus ring, live avatar ring. - Purple Pressed (
#772CE8): Pressed/active state for purple CTAs and toggles. - Purple Glow (
rgba(145,70,255,0.35)): Soft glow under the primary CTA and around a focused live card.
Liveness (Reserved)
- Live Red (
#EB0400): The "● LIVE" pill and now-live indicator — used for nothing else. - Live Red Pressed (
#C20300): Pressed state if the LIVE pill is interactive (jump-to-live).
Canvas & Surfaces
- Canvas (
#0E0E10): Primary near-black app background — faint cool tint. - Deep Black (
#000000): Full-screen / theater video background. - Surface 1 (
#18181B): Card backgrounds, sheets, the chat column, elevated rows. - Surface 2 (
#1F1F23): Higher elevation — modals, active rows, chat input, chip default. - Surface 3 (
#2A2A2D): Pressed state on dark surfaces, hairline divider tone. - Divider (
#2A2A2D): 1pt separators between settings rows and list blocks.
Text
- Text Primary (
#EFEFF1): Stream titles, channel names, screen headers (intentionally off-white, not pure#FFFFFF). - Text Secondary (
#ADADB8): Metadata (game · viewers), descriptions, section subtitles. - Text Tertiary (
#6F6F7B): Disabled labels, very low-emphasis captions, placeholder text.
Semantic
- Online Green (
#00C16E): "Online" presence dot on the Following list (channel currently up but not the LIVE pill). - Mention Purple Tint (
rgba(145,70,255,0.20)): Highlighted chat message background when you're @mentioned. - Sub Badge Gradient (
#9146FF → #772CE8): Subscriber-badge accent in chat. - Error Red (
#EB0400): Playback errors, stream-offline, connection-lost (shares the live red hue).
Light Mode (Limited Use)
Twitch's iOS app is effectively dark-only — the live-streaming atmosphere depends on the near-black canvas. A light variant is not part of the core product.
- Light Canvas (
#FFFFFF) - Light Text (
#0E0E10)
Type scaleRead the full spec
Font Family
- Primary:
Roobert(Twitch brand typeface) — rounded grotesque with friendly terminals - Fallback Stack:
'Inter', -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', Roboto, Helvetica, Arial, sans-serif - Numerals: Tabular figures for viewer counts, timestamps, and follower totals
Hierarchy
| Role | Font | Size | Weight | Line Height | Letter Spacing | Notes |
|---|---|---|---|---|---|---|
| Screen Title (Large) | Roobert | 28pt | 700 | 1.15 | -0.4pt | "Browse", "Following" large nav title |
| Channel Name (Hero) | Roobert | 22pt | 700 | 1.2 | -0.3pt | Streamer display name on channel page |
| Section Header | Roobert | 20pt | 700 | 1.2 | -0.3pt | "Live channels", "Recommended" |
| Stream Title | Roobert | 16pt | 600 | 1.25 | -0.1pt | Stream/VOD title on a card or channel |
| Channel Label | Roobert | 15pt | 700 | 1.25 | -0.1pt | Channel name under a card |
| Body | Roobert | 15pt | 400 | 1.45 | 0pt | Stream "About", panel text |
| Chat Message | Roobert | 14pt | 400 | 1.35 | 0pt | Chat line body (username bolded inline) |
| Chat Username | Roobert | 14pt | 700 | 1.35 | 0pt | Colored display name in a chat line |
| Metadata | Roobert | 13pt | 400 | 1.3 | 0pt | "Just Chatting · 12.4K viewers" |
| Card Subtitle | Roobert | 12pt | 400 | 1.3 | 0pt | Game/category line under a thumbnail |
| Label (UPPER) | Roobert | 11pt | 700 | 1.2 | 0.6pt | "LIVE CHANNELS" eyebrow labels |
| Button (Primary) | Roobert | 15pt | 700 | 1.0 | 0.2pt | Purple "Follow" / "Subscribe" |
| Button (Secondary) | Roobert | 14pt | 600 | 1.0 | 0pt | "Following", outline buttons |
| Tab Label | Roobert | 10pt | 600 | 1.0 | 0.2pt | Bottom tab bar labels |
| Badge | Roobert | 11pt | 700 | 1.0 | 0.4pt | "LIVE", viewer-count pill, sub badge |
Principles
- Weights concentrated at 400 / 600 / 700: Regular for body/metadata/chat, semibold for titles, bold for names, headers, CTAs — no thin, no medium, no black
- Off-white primary text:
#EFEFF1, not pure#FFFFFF— softer on the near-black canvas for long chat-reading sessions - Density for community: No hero display type; live video + scrolling chat are the energy
- All-caps only for eyebrows and the LIVE badge: never for titles or chat
- Color split is structural: purple = action/brand, red = liveness — never decorative, never swapped
Components and layoutRead the full spec
Buttons
Primary CTA (Follow / Subscribe — The Purple Button)
- Shape: Rounded rectangle, height 40pt (auto-width) or full-width on sheets
- Background:
#9146FF - Text:
#FFFFFF - Icon: optional SF Symbol
heart.fill(Follow) /star.fill(Subscribe) 14pt leading,#FFFFFF - Corner radius: 6pt
- Font: Roobert 15pt weight 700, letter-spacing 0.2pt
- Shadow:
rgba(145,70,255,0.35) 0 6px 18pxon the channel-page primary CTA - Pressed: background
#772CE8, scale 0.97, with.impactOccurred(.light)haptic
Following / Subscribed (active state)
- Background:
#1F1F23 - Text:
#EFEFF1with a small leadingcheckmarkorheart.fillin#9146FF - Height: 40pt, corner radius 6pt
- Font: Roobert 14pt weight 600
- Pressed: background
#2A2A2D
Icon Actions (Share, Notifications bell, More)
- Size: 22pt glyph, 44pt hit area
- Default:
#ADADB8 - Active:
#9146FF(notifications on, in a clip) - Layout: trailing the channel header, 20pt gap
Live / Jump-to-Live Pill (interactive variant)
- Background:
#EB0400 - Content: white
●dot + "LIVE", Roobert 11pt weight 700 uppercase - Height: 22pt, corner radius 4pt, horizontal padding 8pt
- Pressed:
#C20300
Text Button ("See all")
- Font: Roobert 13pt weight 600
- Color:
#ADADB8 - No underline, 44pt hit area, trailing each section header
Cards & Containers
Live Thumbnail Card (Horizontal rail / grid)
- Width: 280pt (rail) or full-width minus margins (grid 1-col)
- Aspect: 16:9 live preview
- Corner radius: 6pt on the thumbnail
- Overlays on the thumbnail: red "● LIVE" pill top-left, viewer-count pill (
rgba(0,0,0,0.6)+ white● 12.4K) bottom-left - Below: avatar (32pt circle) + stream title (16pt w600, 2-line clamp) + channel name (13pt w400
#ADADB8) + game/category tag (12pt w400#ADADB8) - Press: scale 1.03 with focus lift
rgba(0,0,0,0.5) 0 12px 28pxand a subtle purple ring; thumbnail begins live preview after ~600ms
Channel Card (compact, Following list)
- Layout: 44pt circular avatar with a 2pt purple ring (red ring if currently LIVE) → display name (15pt w700) + "playing Game · 8.1K" (13pt w400
#ADADB8) → trailing red LIVE pill or gray "offline" time - Background: transparent (
#0E0E10), pressed#18181B - Height: 64pt
Stream View (video + docked chat)
- Top: 16:9 video player (full-bleed width), tap to reveal controls over a
rgba(0,0,0,0.5)scrim - Under video: channel bar — avatar + name + Follow/Subscribe purple CTA + viewer count + LIVE pill
- Below: docked chat column filling the rest of the screen — continuously scrolling messages on
#18181B, chat input pinned at the bottom - Landscape/theater: video goes full-screen and chat becomes a semi-transparent overlay on the right (
rgba(14,14,16,0.72)with blur)
Chat Message Row
- Layout: inline badges (sub/mod/verified) → colored username (14pt w700, user's chosen chat color) → ": " → message body (14pt w400
#EFEFF1) → inline emote chips - Padding: 4pt vertical, 12pt horizontal; no row background by default
- @mention to you: row background
rgba(145,70,255,0.20)with a 2pt leading purple bar - Emote: 24-28pt inline image token, baseline-aligned
Chat Input
- Background:
#1F1F23, height 44pt, corner radius 8pt - Leading emote-picker icon (
face.smiling) 20pt#ADADB8, trailing send/paperplane.fill(purple when text present) - Placeholder: "Send a message", 15pt w400
#ADADB8
Navigation
Bottom Tab Bar
- Height: 52pt + safe area
- Background:
rgba(14,14,16,0.94)with.regularMaterialblur - Tabs: Following, Browse, Search, Notifications, Profile
- Icon size: 24pt
- Active color:
#9146FF(icon + label both turn purple — purple is the indicator) - Inactive:
#ADADB8 - Labels: Roobert 10pt w600, always shown
- Active tab icon: filled SF Symbol; inactive: outlined
- Notifications tab: red dot badge when unread
Channel Header
- 48pt + safe area, transparent over the video; back chevron left, Share + More right
- On scroll into the channel page: solid
rgba(14,14,16,0.94)with display name centered
Player Controls Overlay
- Tap video → controls fade in over
rgba(0,0,0,0.5) - Center: 56pt circular
rgba(255,255,255,0.16)play/pause; for live, a "● LIVE / jump to live" pill replaces the scrubber's end - Bottom: live progress is a thin red line at the live edge; for VODs, a purple scrubber (2pt track
rgba(255,255,255,0.3),#9146FFfill, 14pt thumb) - Top: title + close; bottom-right: quality, captions, chat-toggle, AirPlay
Input Fields
Search Bar
- Background:
#1F1F23 - Height: 44pt, corner radius 8pt
- Leading SF Symbol
magnifyingglass18pt#ADADB8 - Placeholder: "Search", 16pt w400
#ADADB8 - Text color:
#EFEFF1 - Focus: 1.5pt
#9146FFring
Category / Filter Chip
- Background:
#1F1F23default /#9146FFselected - Text:
#EFEFF1default /#FFFFFFselected - Height: 36pt, corner radius 500pt (full pill), horizontal padding 16pt
- Font: Roobert 14pt weight 600
Distinctive Components
Live Chat Overlay
Responsive behaviourRead the full spec
Device Sizes
| Device | Width | Key Changes |
|---|---|---|
| iPhone SE (3rd gen) | 375pt | 240pt rail cards; 1-col browse grid |
| iPhone 13/14/15 | 390pt | Standard 280pt rail cards |
| iPhone 15/16 Pro | 393pt | Dynamic Island accommodated in transparent channel header |
| iPhone 15/16 Pro Max | 430pt | 320pt rail cards; chat column taller in stream view |
| iPad | 768pt+ | 2-3 col browse grid; stream view = video + persistent side chat column |
Dynamic Type
- Stream titles, channel names, chat messages, "About": full scale
- Card subtitle / metadata / viewer pills: scales but clamps at +2 steps (layout-sensitive)
- LIVE pill, tab labels, scrubber times: fixed (never scale)
- Chat: respects Dynamic Type but caps growth to keep throughput readable
Orientation
- Following / Browse / Search / Channel: portrait-locked
- Stream view: rotates to landscape → theater mode — video full-screen, chat becomes the overlay
- Clips player: rotates to landscape
Touch Targets
- Follow / Subscribe CTA: 40pt height — generous tap
- Live cards: full-card tappable, ≥ 110pt tall hit
- Channel rows: 64pt height, full-row tappable
- Chat send / emote picker: 44pt hit area
- Tab bar icons: 24pt icon, 44pt effective hit
Safe Area Handling
- Top: transparent channel header respects safe area / Dynamic Island over the video
- Bottom: tab bar floats above home indicator; chat input docks above it; theater overlay insets from edges
- Sides: 16pt content margins; rails bleed to the right edge intentionally
Drop-in CSS variables
The same values as a theme block. Add the class to <body> and the site repaints.
body.theme-twitch {--page-bg: #0e0e10;
--page-bg-gradient: none;
--text-color: #efeff1;
--heading-color: #efeff1;
--link-color: #9d5aff;
--link-hover-color: #7f27ff;
--border-color: #373739;
--card-bg: #0e0e10;
--card-shadow: 0 1px 2px rgba(239,239,241,0.06);
--card-hover-shadow: 0 6px 18px rgba(239,239,241,0.12);
--header-bg: #212123;
--header-text-color: #ffffff;
--header-shadow: none;
--footer-bg: #0e0e10;
--footer-text-color: #a0a0a2;
--button-bg: #9146ff;
--button-text-color: #ffffff;
--button-hover-bg: #7313ff;
--button-border: none;
--button-border-radius: 6px;
--button-secondary-bg: #1c1c1e;
--button-secondary-text-color: #efeff1;
--button-secondary-hover-bg: #29292b;
--button-secondary-border: 1px solid #373739;
--prompt-bg: #19191b;
--prompt-text-color: #efeff1;
--base-font: var(--font-sans);
--heading-font: var(--font-sans);
--card-border-radius: 6px;
}
Visually close to
Measured with a deterministic colour + geometry comparison across 958 styles. Not a hand-picked list.
Where this came from
- Source document
ios/design-md/video/twitch/DESIGN.md· 22.3 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.