Overview
TradingView runs two design registers out of one token set, and knowing which register you are in explains almost every decision. On marketing surfaces the brand speaks in Euclid Circular at 64–80px with tracking pulled to −0.02em and as far as −0.04em, corners at {rounded.md} (8px), and generous vertical rhythm measured in a named scale that reaches 200px between sections. On product surfaces — a symbol page, a screener, the chart — the display face disappears entirely, the base size drops to 14px in the operating system's own font, and corners tighten to {rounded.xs} (4px). The marketing page sells; the product page reports.
What holds the two together is the data layer. {colors.growing} (#089981) and {colors.falling} (#f23645) are the only colours in the system that do not change between the light and dark themes — a price that is up must be the same green whether the trader runs a bright office screen or a dark desk at night. Every other value flips: the canvas goes from white to pure black, ink from {colors.text-primary} to {colors.dark-text-primary}, dividers from {colors.divider} to {colors.dark-divider}.
The typographic tell is in the numbers. Quote figures carry font-feature-settings: "lnum", "tnum" — lining figures at tabular width — so that a column of prices aligns digit over digit and a changing last digit does not shift the row. It is a small setting that separates a financial interface from a website with numbers on it.
Key Characteristics:
- Two registers: Euclid Circular display for marketing, the system font stack for product UI.
- Radius encodes the register —
{rounded.md}(8px) dominates marketing,{rounded.xs}(4px) dominates product. {colors.growing}and{colors.falling}are theme-invariant; everything else inverts.- Tabular lining figures on every quote, so price columns align.
- The brand blue
{colors.brand}is a focus and link colour, not the primary CTA fill. - Body copy is 14px — a data-density decision, not a typographic one.
- A named vertical rhythm scale (
{spacing.rhythm-1}200px down to{spacing.rhythm-5}48px) with four responsive tiers. - One soft shadow only; separation is otherwise a 1px
{colors.divider}rule. - Green is the accessible
{colors.positive-content}on text, the brighter{colors.growing}on fills and charts.
Colors
Source pages analyzed: the German locale homepage (de.tradingview.com), the pricing surface, and the BTCUSD symbol page, plus the header and footer chrome shared across all three. The token set is identical across locales; only copy differs.
Brand & Accent
- TV Blue (
{colors.brand}— #2962ff): The brand. Used for focus rings, links, selected states and accent fills. It is deliberately not the primary button colour on marketing pages. - Blue Pressed (
{colors.brand-active}— #1848cc) and Blue Interim ({colors.brand-hover}— #1e53e5): The published press ramp. - Accent Wash (
{colors.bg-accent-light}— #e3effd) and Accent Tint ({colors.bg-accent-tint}— #bbd9fb): Selected rows and highlighted regions. - Symbol Cyan (
{colors.symbol-cyan}— #00bcd4): Reserved for symbol identity marks.
Market Data
The domain colours, and the reason this system exists:
- Growing (
{colors.growing}— #089981): Rising prices on fills, chart candles and badges. - Positive Content (
{colors.positive-content}— #06806b): The same green darkened for text, where the brighter value would not hold contrast. Quote changes render in this one. - Positive Pressed (
{colors.positive-active}— #056656). - Falling (
{colors.falling}— #f23645): Declining prices, on both fill and text. - Falling Pressed (
{colors.falling-active}— #cc2f3c); Falling Wash ({colors.falling-tint}— #ffebec) for alert rows. - Warning (
{colors.warning}— #f57c00 /{colors.warning-soft}— #fb8c00).
These six are the only values that hold their hex across both themes.
Surface — light
- Primary (
{colors.bg-primary}— #ffffff): The page. - Secondary (
{colors.bg-secondary}— #f9f9f9) and Tertiary ({colors.bg-tertiary}— #f2f2f2): Section bands, chips and secondary buttons. - Neutral (
{colors.bg-neutral}— #ebebeb): Pressed states and inset fills. - Dark (
{colors.bg-dark}— #2e2e2e): The inverted island — the header search field and dark promotional bands sitting inside an otherwise light page.
Surface — dark theme
- Primary (
{colors.dark-bg-primary}— #000000): Pure black, unlike the light theme's pure white counterpart being softened nowhere. - Secondary (
{colors.dark-bg-secondary}— #1f1f1f), Tertiary ({colors.dark-bg-tertiary}— #2e2e2e), Neutral ({colors.dark-bg-neutral}— #3d3d3d).
Text
- Primary (
{colors.text-primary}— #0f0f0f light /{colors.dark-text-primary}— #dbdbdb dark). - Secondary (
{colors.text-secondary}— #707070 /{colors.dark-text-secondary}— #8c8c8c). - Tertiary (
{colors.text-tertiary}— #9c9c9c): The one text value that is the same in both themes. - Disabled (
{colors.text-disabled}— #a8a8a8).
Hairlines & Borders
- Divider (
{colors.divider}— #ebebeb light,{colors.dark-divider}— #3d3d3d dark): The workhorse rule between table rows and sections. - Border Neutral (
{colors.border-neutral}— #a8a8a8) and Strong ({colors.border-strong}— #b8b8b8): Input and control outlines.
Brand Gradient
No gradient tokens in the interface. Gradients appear only inside promotional artwork on marketing pages, never on chrome, buttons or data surfaces.
Typography
Font Family
- Euclid Circular (weight 600 only, loaded as
EuclidCircularSemibold) — the display face. Marketing surfaces only; it does not appear anywhere in the product UI. - System stack —
-apple-system, system-ui, "Trebuchet MS", Roboto, Ubuntu, sans-serif. Everything else. Using the OS font is a deliberate density and rendering choice for a data interface, and the reason the product UI feels native on every platform. - Numeric rendering —
font-feature-settings: "lnum", "tnum"on quotes and tables.
Hierarchy
| Token | Size | Weight | Line Height | Letter Spacing | Use |
|---|---|---|---|---|---|
{typography.hero-xl} | 80px | 600 | 1 | -0.02em | Pricing hero — largest step. Euclid |
{typography.hero} | 64px | 600 | 1 | -0.04em | Homepage hero. Euclid, the tightest tracking in the system |
{typography.display} | 48px | 600 | 1.167 | -0.02em | Marketing section display. Euclid |
{typography.title-xl} | 48px | 600 | 1.167 | 0 | Product page title (symbol name). System font |
{typography.title-lg} | 28px | 600 | 1.286 | 0 | Section heading |
{typography.lead} | 28px | 400 | 1.43 | 0 | Marketing lead paragraph |
{typography.lead-sm} | 20px | 400 | 1.5 | 0 | Secondary lead |
{typography.title-md} | 20px | 600 | 1.2 | 0 | Card and panel heading |
{typography.title-sm} | 16px | 600 | 1.25 | 0 | Chip labels, inline quote change |
{typography.data} | 24px | 600 | 1.2 | 0 | Quote change value. Tabular lining figures |
{typography.body} | 14px | 400 | 1.286 | 0 | Base size. UI labels, table cells, buttons |
{typography.caption} | 14px | 400 | 1.286 | 0 | Table data. Tabular lining figures |
Principles
- The display face marks the register. Euclid appears only where the brand is selling. A product page that reaches for it is in the wrong register.
- Negative tracking is for Euclid only. The system font runs at zero tracking at every size; only the display steps are tightened, and the homepage hero at −0.04em is the extreme.
- Two weights carry everything: 400 and 600. There is no 500 and no 700 in the observed set.
- Body is 14px, not 16px. On a screen showing a watchlist, a chart and a news feed at once, the extra two pixels cost a row.
- Numbers get tabular figures. Any element rendering a price, a percentage or a volume takes
"lnum", "tnum". - Green splits by context.
{colors.growing}on fills,{colors.positive-content}on text. Red does not split —{colors.falling}already holds contrast as text.
Note on Font Substitutes
Euclid Circular is licensed from Swiss Typefaces. The closest free substitutes are Poppins (weight 600) or Plus Jakarta Sans (weight 600) — both geometric with a similar circular bowl. Add roughly −0.005em on top of the published tracking when substituting Poppins, whose default fit is slightly wider than Euclid at display sizes.
The system stack needs no substitute — it is the point. Keep -apple-system, system-ui, "Trebuchet MS", Roboto, Ubuntu, sans-serif verbatim so the interface resolves to the host platform's own UI font.
Layout
Spacing System
- Base unit: 4px, working scale 4 · 8 · 16 · 24 · 32 · 48.
- Vertical rhythm is its own named scale with four responsive tiers, and it is the distinctive part of the layout system:
| Token | Desktop | Laptop | Tablet | Phone |
|---|---|---|---|---|
{spacing.rhythm-1} | 200px | 160px | 120px | 80px |
{spacing.rhythm-2} | 160px | 120px | 88px | 64px |
{spacing.rhythm-3} | 120px | 88px | 64px | 48px |
{spacing.rhythm-4} | 80px | 64px | 48px | 48px |
{spacing.rhythm-5} | 48px | 40px | 32px | 32px |
Parallel header- and footer- scales govern the gap above and below a section's heading (120 / 100 / 80 / 56px for the largest) so that heading spacing scales independently of section spacing. Product surfaces ignore this scale entirely and work on the 4/8/16 grid.
Grid & Container
Marketing sections use a centred container with 20–40px inline padding. The product surfaces are full-width panel layouts rather than a centred column — a symbol page fills the viewport and splits into resizable regions.
Whitespace Philosophy
The two registers are opposites here, deliberately. Marketing pages are among the most generous in this collection, with up to 200px between sections. Product pages are among the tightest, because whitespace on a trading screen is information you are not seeing. The same brand, inverted priority.
Elevation & Depth
| Level | Treatment | Use |
|---|---|---|
| Flat | Background level change only | Sections, panels, table rows |
| Divider | 1px {colors.divider} | The default separation — rows, sections, panels |
| Soft shadow | 0 2px 4px rgba(0,0,0,.2) | Dropdowns, floating menus — the only shadow observed |
| Deep blur | --space-shadow-blur: 56px with rgba(0,0,0,.2) | Large promotional overlays on marketing pages |
Shadow philosophy. A data interface cannot afford shadows: they cost pixels and add visual noise between rows that must be scanned. TradingView uses exactly one soft shadow, for genuinely floating layers, and otherwise separates with a single-pixel rule. On marketing surfaces a much larger blur appears behind promotional artwork, which is decoration rather than elevation.
Decorative Depth
- Inverted islands. A
{colors.bg-dark}block inside a light page — the header search field, promo bands — is the main depth device on marketing surfaces. - No gradients on chrome.
Shapes
Border Radius Scale
| Token | Value | Marketing use | Product use |
|---|---|---|---|
{rounded.xs} | 4px | rare | dominant — 146 of 316 rounded elements on the symbol page |
{rounded.sm} | 6px | small controls | inputs |
{rounded.md} | 8px | dominant — 241 of 447 on the pricing page | secondary panels |
{rounded.lg} – {rounded.xl} | 12 / 14px | nested cards | popovers |
{rounded.xxl} | 16px | cards, media frames | large panels |
{rounded.xxxl} | 24px | feature cards | — |
{rounded.pill} | 40px | search field, on-media buttons | — |
{rounded.circle} | 50% | avatars, symbol marks | avatars, icon buttons |
Radius encodes the register. If you are unsure which side of the system you are building, the corner tells you: 8px is marketing, 4px is product.
Media Geometry
Marketing media sits in {rounded.xxl} (16px) frames; product charts and tables are square-cornered and edge-to-edge within their panel.
Components
Top Navigation
header — 64px, sticky, transparent over the page beneath it. Nav items are 14px system font. The right cluster carries a {component.search-field} — a {colors.bg-dark} pill even in the light theme, one of the inverted islands — plus a language selector and the trial CTA.
Buttons
button-secondary — The most common marketing action: {colors.bg-tertiary} fill, {colors.text-primary} label, {rounded.md}, 48px tall, 0 23px padding, {typography.body} at weight 400. Note the CTA is grey, not brand blue.
button-on-media — For dark hero sections: white fill, ink label, a 2px {colors.border-light} ring and {rounded.pill} on a 56px height.
chip-filter — Tab and filter chips: {colors.bg-tertiary}, {rounded.md}, 40px tall, {typography.title-sm} at weight 600.
search-field — {colors.bg-dark} fill, {rounded.pill}, 40px tall, placeholder in {colors.text-tertiary}.
Data Components
quote-change-up / quote-change-down — The heart of the system. A price change renders in {typography.data} (24px, weight 600, tabular lining figures) coloured {colors.positive-content} or {colors.falling}. The same pattern repeats at {typography.title-sm} for inline and list contexts. Colour and sign are always shown together — the value carries a leading + or − so the meaning survives without colour.
Cards & Containers
card-marketing — {rounded.xxl}, {colors.border-light} ring, generous padding. card-product — {rounded.xs}, {colors.divider} rule, tight padding. Same component, two registers.
Inputs & Forms
Text fields have a published token family (--color-text-field-*): transparent fill by default, {colors.border-neutral} border, focus border {colors.brand}, label {colors.text-secondary}, value {colors.text-primary}, disabled {colors.text-disabled}. Validation and error states were not surfaced on the analyzed pages — see ## Known Gaps.
Footer
footer — {colors.bg-primary}, links in {typography.body} at {colors.text-secondary}, separated by a {colors.divider} rule.
Do's and Don'ts
Do
- Decide which register you are in first, then pick the radius:
{rounded.md}for marketing,{rounded.xs}for product. - Keep
{colors.growing}and{colors.falling}identical in both themes. - Set
font-feature-settings: "lnum", "tnum"on every number a user might compare. - Use
{colors.positive-content}for green text and{colors.growing}for green fills. - Pair colour with a sign (
+/−) on every change value. - Reserve Euclid for marketing display; use the system stack everywhere else.
- Separate with a 1px
{colors.divider}rule before reaching for a shadow. - Run marketing sections on the rhythm scale and product layouts on the 4/8/16 grid.
Don't
- Don't use
{colors.brand}as the primary marketing CTA fill — the grey{component.button-secondary}is the pattern. - Don't invert the market colours for dark mode; a trader reads them as data, not as styling.
- Don't set body copy above 14px in product UI.
- Don't apply negative tracking to the system font — that is a display-face treatment only.
- Don't add shadows between table rows or panels.
- Don't rely on colour alone to signal direction.
- Don't bring the marketing rhythm scale into a product screen; 200px of air is lost information there.
Responsive Behavior
Breakpoints
Four named tiers drive the rhythm scale — phone, tablet, laptop, desktop. Vertical spacing drops by roughly 60% from desktop to phone ({spacing.rhythm-1} 200px → 80px) while the type scale holds far more steadily, so mobile pages compress in height rather than in size.
Touch Targets
Controls are 40px (chips, search) to 48px (buttons) tall on marketing surfaces; product controls run 32px, which is a desktop-density decision — the mobile apps are separate products.
Collapsing Strategy
- Header: the nav collapses to a hamburger; the search field and CTA persist.
- Sections: the rhythm scale steps down through its four tiers.
- Product panels: resizable regions stack rather than reflow.
Image Behavior
Marketing media keeps its {rounded.xxl} frame at all widths. Charts re-render at the container size rather than scaling as an image.
Iteration Guide
- State the register before writing any component: marketing or product. Every other choice follows.
- Work on one component at a time, addressed by its YAML key (
{component.quote-change-up},{component.button-secondary}). - Use
{token.refs}everywhere; never inline a hex once a token exists. - Document default and active/pressed states only — never hover.
- The two rules that define this system: market colours never change between themes, and numbers always carry tabular lining figures.
- Green has two values by context — fill versus text. Reaching for the wrong one is the most common error.
- Before adding elevation, add a divider.
Known Gaps
- Form validation and error states were not surfaced. The analyzed pages contained no form in an error condition; input styling is read from the published
--color-text-field-*token family rather than from a rendered example. - The chart itself was not analyzed. The charting canvas is a rendered application surface with its own palette (candle bodies, wicks, grid lines, drawing tools) that does not resolve as DOM tokens.
- Only the German locale was measured. The token set resolved identically to the documented values, but locale-specific typographic adjustments were not compared.
- The dark theme was read by switching the theme class and re-resolving tokens, not by browsing a rendered dark session; component-level dark styling is inferred from the token pairs.
- The spacing scale below the rhythm tokens is derived. TradingView publishes the vertical rhythm scale explicitly but no numbered inline spacing scale; the 4/8/16/24/32/48 set is the dominant measured one.
- Motion is thinly represented. One easing was observed in effect,
cubic-bezier(.67, 0, .34, 1)at 0.5s on layout transitions; button and state transitions resolved to the shorthandallwithout a published curve.