본문으로 건너뛰기
oh-my-design

NewsPicks DESIGN.md

DESIGN.md

Design System Inspiration of NewsPicks (ニューズピックス)

Overview

Visual Theme & Atmosphere

NewsPicks is a Japanese business-news platform where journalism sits next to expert commentary. The surface is white, very dense — 19,523 characters on one screen — and set almost entirely at 12px (138 of 286 text-bearing elements). Ink is #222222, not black, and it does nearly all the work: 176 elements at full strength and 99 more at an alpha.

The token set is the reason this reference is here. 220 custom properties and not one of them belongs to a framework. The architecture is the same one JAL uses — four parallel families named for what is being painted — but NewsPicks carries it further:

--palette-<hue>-<step>        84   the raw ramp, five hues
--surface-color-<role>-…      53   fills
--text-color-<role>-…         22   labels
--object-color-<role>-…       19   glyphs
--border-color-<role>-…       19   lines

And then a layer that no framework would ever generate, because it is made of this product's own nouns: a Premium green, an AI purple, a BookPicks cream, a read/unread pair, and a brand colour for each third-party sign-in.

Primary tasks

  • Read the feed, switch between topic tabs, open a story and its picks.
  • Sign in, or start a free Premium trial.

Brand Narrative

NewsPicks is a feed where a story is followed by named experts arguing about it, sold partly behind a Premium tier. The token set reads exactly like that product: a colour for the paid tier, a colour for machine-written text, a colour for whether you have read something, a full role set for one editorial category, and the brand blue of every service you can sign in with.

The rest is restraint. No webfont, no type scale, no shadow, 12px almost everywhere — the design spends nothing on surface and all of it on telling one kind of thing from another.

Principles

  • Four families over one palette. Surface, text, object, border.
  • Ink at alpha, never grey.
  • If the product has a noun, the system has a token for it.

Personas

Not researched. No persona claim is made from a UI capture.

Colors

Measured 2026-09-22 with getComputedStyle on newspicks.com.

Accent

  • Accent (#146af5) — --surface-color-accent-primary, --text-color-accent, --object-color-accent, --border-color-information, and --palette-blue-600. One value under five names, one per family.
  • Accent Hover (#0032ca) — and it is the measured hover on the Premium button.
  • Accent Inverse (#4b9dfa) — the accent for dark grounds, also --text-color-bookmark.
  • Accent Surface (#ebf3ff) and its hover #d6e6ff — the pale wash behind an accent.

Ink

  • Foreground (#222222) — --text-color-base-primary, --object-color-base-primary, --brand-color-default, --body-color-inverse, --surface-color-inverse-primary. Secondary ink is the same value at alpha: rgba(34,34,34,.7), .62, .4, .24, .16, .12, .08, .05.
  • Disabled (#a3a3a3) — --text-color-base-primary-disabled, and the placeholder colour.
  • Inverse Hover (#474747) — the one lighter step off the ink.
  • Canvas (#ffffff).

Status

Caution (#de3535) → hover #ab0000, surface #fff0f0 → hover #ffdbdb. Success (#018a26) → hover #044f20, surface #e8ffe8. Recommend (#ed5353) — a fourth red, distinct from caution, used for reposts.

The families made of product nouns

This is what separates the reference from a generic semantic system.

  • Premium (#00b357) → hover #007d3c, surface #f0faf5. The paid tier has its own green, and it is not the success green. Plus a campaign pair: --premium-campaign-surface-color-secondary #ffc800 on #222.
  • AI (#9b2cc1) — --surface-color-ai-primary and --text-color-ai-primary, with a 5% wash. A purple reserved for machine-generated content.
  • BookPicks (#f7f3eb) — a cream surface for the book vertical, with a translucent twin.
  • Highlight (#ffe86b) — the colour of a highlighted passage.
  • Unread (#ebf3ff) → hover #d6e6ff — read state as a token, which a news product needs and a component library would not think to publish.
  • Investment Gold (#886c0f) — --brand-category-color-*-investment-gold, a whole role set (text, border, inverse surface) for one editorial category.
  • Third-party sign-in: Facebook #0866ff · LinkedIn #2967b2 · BizD #0081cc · Apple #000000 · Twitter #000 — the last recorded as found, and worth noticing because it is the post-rebrand black rather than the old blue.

Palette

84 tokens across five hues at eleven steps. Blue #d6e6ff · #4b9dfa · #2986ff · #146af5 · #0040e0; gray #e6e6e6 · #616161 · #333333; red #fff0f0 · #ffdbdb · #fa7373 · #d41717; green #d0f2d0 · #239e2f · #037020; plus yellow.

Two entries resolve to CSS keywords rather than hex — --palette-gray-400 is grey and --text-color-base-primary-visited is grey. Recorded as found; not promoted.

Typography

Font family

Absent. No webfont loaded, and the rendered stack begins at -apple-system on all 286 text-bearing elements. There is no --font-* token in the set. A dense reading product that spends its whole token budget on colour and none on type.

Scale

Rendered: 12px ×138 · 14px ×43 · 16px ×42 · 10px ×20 · 13px ×12 · 18px ×11 · 11px ×10 · 20px ×4. Every control label is 12px. Weights are two: 400 on 174 and 700 on 112.

The scale is not tokenised either — these are readings, not declarations.

Layout

  • Four families, one per painted thing, over one raw palette. A glyph takes --object-color-*, never --text-color-*.
  • Ink at alpha, eight steps deep, instead of a grey ramp for secondary text and washes.
  • Name the product's nouns. Premium, AI, BookPicks, unread, and each sign-in provider get tokens because the product has those things.

Responsive Behavior

Not measured. Desktop 1440×1100 only.

Elevation & Depth

No shadow was observed on any measured control and no shadow token exists among the 220. Separation is the rgba(34,34,34,.12) / .16 border pair and the pale surface washes.

Motion & Easing

No motion token exists. Durations are written inline and differ by control: background-color 0.1s linear on the buttons, and color 0.3s, text-decoration 0.3s, background-color … on the tabs. The tabs transition three times slower than the buttons, and nothing names either value.


Tier 1 sources: https://newspicks.com/ (live product surface — 220 custom properties read via getComputedStyle, none belonging to a framework; four controls measured at rest, hover, pressed and focus, 2026-09-22); https://newspicks.com/zz-this-does-not-exist (nonsense-path control — returns a real HTTP 404 of 89 characters, establishing that the host is not a catch-all and that the homepage reading is a real route, 2026-09-22)

Components

Four controls measured, each with focus read for every control before the mouse moved.

One hover rule, two fills

The outline controls — the login button and an unselected tab — both take rgba(34,34,34,0.05) on hover and pressed. That is --surface-color-base-primary-hover rgb(34 34 34/5%) exactly: ink at 5%, not a grey.

The filled control — the Premium button — goes #146af5 → #0032ca, which is --surface-color-accent-primary-hover.

Token and render agree three times: the accent rest, the accent hover, and the 5% ink wash.

Login

#ffffff, #222222 label, 1px solid #222222, 4px radius, 73×32, 12px/400, transition: background-color 0.1s linear.

Premium trial

#146af5 fill, #ffffff label, 4px radius, 160×32, 12px/400.

Worth noting: the button that sells Premium is accent blue, not the Premium green. The green #00b357 is the product's colour; the blue is the action's.

Feed tabs — a pill, and only one of them responds

The selected tab is a 20px-radius blue pill, 58×40. The unselected one is transparent with a 1px solid #222222 outline at the same radius and height.

The selected tab changes nothing on hover or pressed — :hover matched true while the reading was taken. The unselected one takes the 5% wash. The current tab does not respond to the pointer, which is a deliberate and legible choice.

Focus

All focusable controls render outline: rgb(0, 95, 204) auto 1px — Chrome's default ring. The auto style is the tell; an authored ring names a style and a width. No focus token is recorded, and the set declares none. The selected tab does not report :focus-visible at all.

Radius

Rendered: 4px ×51 — the house value — then 50% ×29 (avatars), 20px ×28 (the tab pills), 2px ×18, 8px ×2.

States

All four components carry measured hover and pressed; hover and pressed are identical on every one of them, so the system distinguishes "pointer is here" and not "pointer is down".

The selected tab is the interesting case. It changes nothing while :hover matches true — measured, not missed. A control that is already current has nothing to offer the pointer.

Focus is Chrome's on everything. No focus value is recorded. Disabled exists thoroughly in the tokens — --surface-color-*-disabled, --text-color-base-primary-disabled #a3a3a3, --border-color-* — but was not observed on a rendered control, so no disabled component is declared.

Do's and Don'ts

Do

  • Wash with ink at 5% (rgba(34,34,34,0.05)) for a neutral hover — that is the system's rule and it is measured on two different control shapes.
  • Keep Premium green and success green apart. #00b357 is a product tier; #018a26 is a state.
  • Take the whole role when you take one — base-primary, its -hover, and its -disabled are published together.

Don't

  • Don't copy the focus ring. Every control shows Chrome's auto 1px; NewsPicks authors none.
  • Don't use #146af5 for Premium. The Premium button is blue but Premium itself is green.
  • Don't build a grey ramp for secondary text. The system uses #222222 at alpha.

Voice & Tone

Not assessed as authored voice. 19,523 characters on the measured surface, almost all of it headlines and comment excerpts.

Agent Prompt Guide

Quick Color Reference

#146af5 accent · #0032ca accent hover · #4b9dfa accent inverse · #ebf3ff/#d6e6ff accent surface · #222222 ink (at .7/.62/.4/.24/.16/.12/.08/.05) · #a3a3a3 disabled · #00b357/#007d3c/#f0faf5 Premium · #9b2cc1 AI · #f7f3eb BookPicks · #ffe86b highlight · #886c0f investment gold · #de3535/#ab0000 caution · #ed5353 recommend · #018a26/#044f20 success · #ffc800 campaign

Example Component Prompts

  • "A 32px outline button: white, #222222 12px/400 label and 1px border, 4px radius, hover fill rgba(34,34,34,0.05)."
  • "A 40px filter pill: 20px radius; selected is #146af5 with white 12px label and does not react to hover; unselected is transparent with a #222222 outline and the 5% ink wash."

Governance

Known Gaps

  • Contrast, tab-inactive. Text #222222 on #00000000 measures 1.32:1, below the WCAG AA 4.5:1 minimum for normal-size text. Recorded as measured, not adjusted.

색상

브랜드

면과 글자

상태

그 밖의 색

단계별 색

palette-blue100–700

palette-gray100–700

palette-red50–700

palette-green100–700

타이포그래피

타입 스케일

  1. headingThe largest rendered step20px
  2. titleSection titles18px
  3. leadHeadlines in the feed; 42 elements16px
  4. readingArticle summaries; 43 elements14px
  5. bodyComment body13px
  6. baseThe page's default — 138 of 286 text-bearing elements, including every control label12px
  7. captionThe smallest label step11px
  8. microTimestamps and pick counts; 20 rendered elements10px

여백과 모양

모서리 반경

  • xs2px
  • sm4px
  • md8px
  • pill20px
  • circle9999px

컴포넌트

  • button-login
    button-login채움 #ffffff · 글자 #222222 · 테두리 1px solid #222222 · 반경 4px · 높이 32px · 안쪽 여백 0 12px · 글자 크기·굵기 12px / 400
    • 호버 rgba(34,34,34,0.05)
    • 누름 rgba(34,34,34,0.05)
  • button-premium
    button-premium채움 #146af5 · 글자 #ffffff · 반경 4px · 높이 32px · 안쪽 여백 0 12px · 글자 크기·굵기 12px / 400
    • 호버 #0032ca
    • 누름 #0032ca
  • tab-active
    tab-active채움 #146af5 · 글자 #ffffff · 반경 20px · 높이 40px · 안쪽 여백 0 16px · 글자 크기·굵기 12px / 400
    • 호버 #146af5
    • 누름 #146af5
  • tab-inactive
    tab-inactive채움 transparent · 글자 #222222 · 테두리 1px solid #222222 · 반경 20px · 높이 40px · 안쪽 여백 0 16px · 글자 크기·굵기 12px / 400
    • 호버 rgba(34,34,34,0.05)
    • 누름 rgba(34,34,34,0.05)