Design Lounge
Install

Nº 156 of 520

Testimonials wall grid

A four-column Pebble quote wall: seven short cards, two spanning two columns, initials discs, and a 4px hover lift that reveals tenure.

Preview

Open full size
1280 × 800 · 7.3 KB · 123 lines

Use it

Free to use · credit appreciated

1 Once, in your project

npx skills add SusanAcharya/Design-Lounge

2 Then ask

Using the Design Lounge skill, build "Testimonials wall grid" (piece testimonials-wall-grid) in my stack. Match its brief; restyle it onto my product's theme.

No skill? Paste the brief instead. It carries the numbers, tokens and behaviour.

Brief

194 lines

Build brief for a coding agent. Rebuild this piece in the reader’s stack. If they haven’t said which stack, ask once, then default to semantic HTML + CSS + a little vanilla JS. Match the numbers below; don’t “improve” them.

What it is

A testimonials section for Pebble, a notes app. Seven short quotes sit in a 4-column × 8-row CSS grid that reads as masonry: two cards span two columns, the rest occupy single cells of uneven height. Every card has a 28px initials disc, a name, a role, and a tenure (14 months, 9 months, …) that is invisible until hover or focus. One family only — Plus Jakarta Sans at 400 and 600. No serif, no second face. The feeling is a soft noticeboard, not a carousel and not a logo wall.

Reference behaviour

  1. Initial state: cool mist page #EEF1F3, 56px nav (irregular 14px pebble mark + Pebble + Notes / Share / Pricing + pill “Start a notebook”). Lead line: kicker “FROM THE NOTEBOOKS”, 28px heading “People who keep notes in Pebble”, right meta “7 notes · 4 columns · 2 wide cards”. The wall fills the remaining height. Card 1 (Mina, eucalyptus wash) spans columns 1–2, rows 1–4. Card 5 (Eva, sand wash) spans columns 2–4, rows 5–8. Quote 01 is already the largest type (20px).
  2. Hover a card: it lifts translateY(-4px) over 240ms, border becomes --ink, a 10px/24px shadow at 8% ink appears. The tenure on the right of the footer fades in and rises 4px over 160ms.
  3. Keyboard-focus a card (tabindex="0"): the same lift, border, shadow, and tenure. Outline is none because the ink border is the focus cue; a 2px eucalyptus ring still appears on nav chrome via :focus-visible.
  4. Leave the card: lift, border, shadow, and tenure reverse on the same clocks.
  5. Hover “Start a notebook”: fill changes from --ink to --euc over 0ms (colour only).
  6. No click handler. Cards do not expand, flip, or navigate.
  7. prefers-reduced-motion: reduce sets all transition durations to 1ms and cancels the 4px lift; tenure still appears.

Structure

1280 × 800
┌──────────────────────────────────────────────────────────────────────┐
│ (pebble) Pebble    Notes   Share   Pricing         Start a notebook  │ 56
│                                                                      │
│ FROM THE NOTEBOOKS                          7 notes · 4 columns ·    │
│ People who keep notes in Pebble             2 wide cards             │
│                                                                      │
│ ┌───────────────────┬──────────┬──────────┐                          │
│ │ Mina (wide, euc)  │ Rafi     │ Asha     │  rows 1–4 / Asha 1–3     │
│ │                   │          ├──────────┤                          │
│ │                   │          │ Theo     │  rows 4–6                │
│ ├────────┬──────────┴──────────┼──────────┤                          │
│ │ Jun    │ Eva (wide, sand)    │          │  rows 5–8 / Theo 4–6     │
│ │        │                     ├──────────┤                          │
│ │        │                     │ Noor     │  rows 7–8                │
│ └────────┴─────────────────────┴──────────┘                          │
└──────────────────────────────────────────────────────────────────────┘
  pad 48    gap 12    radius 14
  • <nav> 56px: .brand, three .links a, .cta pill.
  • <section aria-label="Customer quotes">: .lead (kicker + h1 + .meta) then .wall.
  • .wall is display:grid; grid-template-columns:repeat(4,1fr); grid-template-rows:repeat(8,1fr); gap:12px; flex:1.
  • Seven <article class="card"> with explicit grid placement (.c1–.c7). Wide cards also have .wide.
  • Each card: <p> quote, <footer> with .av, name/role, <time class="when">.

Placement and copy:

ClassGridWashQuoteName · roleTenureInitials
.c11/3, 1/5#E4EDE8I stopped opening a new doc for every meeting. The pebble from Tuesday is still the one I am writing in on Friday.Mina Kade · Product · Orchard14 months#4A7C74 MK
.c23/4, 1/5cardThe weekly review is just the notes I already wrote.Rafi Lutz · Eng · North Dock9 months#3D4A62 RL
.c34/5, 1/4cardShared a pebble with my pair. We did not fork a copy.Asha Holm · Design · Vale1 year#C4786A AH
.c41/2, 5/9cardTags I actually use: eleven of them. The rest never made it out of the picker.Jun Cho · Research · Kiln6 months#6B5A46 JC
.c52/4, 5/9#EFE6D8Sunday night is the inbox. Monday morning is an outline I did not have to rebuild.Eva Solberg · Editor · Field & Desk16 months#2F4A58 ES
.c64/5, 4/7cardOffline on the train. Synced at the office door.Theo Park · Ops · Harbor7 months#5A6B4A TP
.c74/5, 7/9cardSearch hit the sentence I half-remembered.Noor Wade · Counsel · Pine & Co10 months#7A5348 NW

Tokens

:root {
  --bg: #eef1f3;          /* page mist */
  --card: #fffcf8;        /* default card */
  --ink: #1c2328;         /* text, CTA, hover border */
  --ink-2: #5c666e;       /* secondary */
  --ink-3: #8a939a;       /* tenure */
  --line: #d7dce0;        /* card border */
  --line-2: #c3c9ce;
  --euc: #4a7c74;         /* kicker, mark, CTA hover, focus */
  --euc-soft: #e4ede8;    /* Mina wash */
  --rose: #c4786a;        /* Asha disc */
  --sand: #efe6d8;        /* Eva wash */
  --slate: #3d4a62;       /* Rafi disc */

  --font: "Plus Jakarta Sans", system-ui, sans-serif;

  --nav-h: 56px;
  --pad: 48px;
  --r: 14px;
  --gap: 12px;
  --av: 28px;

  --t-fast: 160ms;
  --t-lift: 240ms;
  --ease: cubic-bezier(.2, .7, .2, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
}

Typography

One family. Two optical sizes on the quotes (16px single, 20px wide), two weights.

RoleFamilySizeWeightLine-heightTrackingCase
Body / linksPlus Jakarta Sans13–14px4001.450sentence
BrandPlus Jakarta Sans15px6001−0.02emsentence
CTAPlus Jakarta Sans13px60010sentence
KickerPlus Jakarta Sans11px6001+0.14emUPPERCASE
HeadingPlus Jakarta Sans28px6001.15−0.03emsentence
MetaPlus Jakarta Sans13px400 / 6001.40sentence
Quote (single)Plus Jakarta Sans16px4001.4−0.015emsentence
Quote (wide)Plus Jakarta Sans20px4001.35−0.02emsentence
AuthorPlus Jakarta Sans12px6001.20sentence
RolePlus Jakarta Sans11px4001.30sentence
TenurePlus Jakarta Sans11px4001+0.02emsentence
InitialsPlus Jakarta Sans10px6001+0.03emUPPERCASE

Motion

ElementTriggerPropertyFrom → ToDurationEasingNotes
.cardhover / focus-visibletransform0 → translateY(-4px)240ms--ease
.cardsameborder-color--line → --ink160ms--ease
.cardsamebox-shadownone → 0 10px 24px rgba(28,35,40,.08)240ms--ease
.whensameopacity, translateY0, 4px → 1, 0160ms--easestays in the footer layout

Reduced motion: transition-duration: 1ms on .card and .when; hover/focus must not translate. Tenure still appears. No looping animation.

States

  • Card rest: --card fill (or wash), 1px --line, radius 14px, padding 18px 18px 16px.
  • Card hover / focus-visible: lift 4px, border --ink, shadow as above, tenure visible. outline: none on the card itself.
  • Nav / CTA / brand focus-visible: 2px --euc outline, 3px offset.
  • CTA rest: 34px pill, --ink fill, --card text, 14px horizontal padding.
  • CTA hover: fill --euc.
  • Link hover: colour --ink.
  • There is no selected, loading, or empty state.

Accessibility

  • Section labelled aria-label="Customer quotes".
  • Cards are focusable (tabindex="0") so keyboard users get the same lift and tenure as pointer users. They are not buttons and do not fire an action.
  • Tenure is a real <time datetime> so the string “14 months” has a machine date (2025-11, etc.).
  • Decorative pebble mark is aria-hidden="true".
  • Tab order: brand → Notes → Share → Pricing → CTA → Mina → Rafi → Asha → Jun → Eva → Theo → Noor (source order, not visual masonry order).
  • Contrast: --ink on --bg ~13:1; --ink on --card ~14:1; --ink-2 on --card ~5.8:1; --euc on --bg ~4.7:1 (kicker 11px/600). Initials are #FFFCFA on the disc colours, all ≥ 5:1.
  • Hit targets: CTA 34× auto (≥ 40px wide with padding). Cards are large regions. Tenure is not a separate control.

Responsive rules

  • ≥ 1280: 4 columns, 8 equal rows filling the leftover height, --pad: 48px, wide quotes 20px.
  • 1024–1279: --pad: 28px, single quotes 15px, wide quotes 17px. Placement classes stay.
  • 768–1023: wall becomes 2 columns, grid-auto-rows: minmax(140px, auto), placement classes are ignored (grid-column:auto; grid-row:auto) except .wide which still spans 2. Nav links hide.
  • < 640: same 2-column stack; both wide cards remain full width. Heading 24px if it wraps. Do not drop to one column until 480 if the host page needs it; the demo’s hard floor is 2.

Acceptance checklist

  • First frame is a filled 4-column wall on #EEF1F3 with heading “People who keep notes in Pebble”.
  • Exactly seven cards; Mina spans 2 columns (rows 1–4); Eva spans 2 columns (rows 5–8).
  • Mina wash is #E4EDE8; Eva wash is #EFE6D8; the other five are #FFFCFA.
  • Wide quotes are 20px/400; single quotes are 16px/400; one family only (Plus Jakarta Sans at 400 and 600).
  • Hover or focus lifts a card 4px over 240ms and reveals tenure on the right.
  • Tenure is hidden at rest (opacity:0) but remains in the DOM.
  • CTA is a 34px pill that turns eucalyptus on hover.
  • Focus-visible rings (2px #4A7C74, 3px offset) appear on brand, links, and CTA.
  • prefers-reduced-motion: reduce removes the lift; tenure still appears.
  • No images, no second font family, no emoji, no dummy copy, no JS required.
  • Demo fills 1280×800 with no page scrollbar and starts with the piece header comment.

Implementation notes

Masonry without a library. Use a fixed 4×8 track grid and place each card by line numbers. Do not use masonry or JS measuring:

.wall { display: grid; grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(8, 1fr); gap: 12px; flex: 1; }
.c1 { grid-column: 1 / 3; grid-row: 1 / 5; }
.c5 { grid-column: 2 / 4; grid-row: 5 / 9; }

Footer sticks to the bottom of every card so short quotes do not leave the name floating mid-card:

.card { display: flex; flex-direction: column; }
.card footer { margin-top: auto; padding-top: 14px; }

Tenure stays in flow. Fade it; do not display:none, or the footer will shift on hover:

.when { opacity: 0; transform: translateY(4px); }
.card:hover .when, .card:focus-visible .when { opacity: 1; transform: none; }

Common mistakes: loading a serif “for the quotes”; equal-height cards that read as a boring 4-up; drop shadows at rest; a carousel hidden inside the wall; using grid-auto-flow: dense without explicit spans so the screenshot order changes between browsers.

Details

Palette
Type
Plus Jakarta Sans
Motion
Subtle motion
Build
One session
Designed bySusan AcharyaKathmandu

Studied

Linear

Show the product doing the work. Fade it at the edges and keep one colour for what matters.

All sources