Luxury website design, as a specification

The luxury look written as values: a Didone and grotesque pairing, a 1.414 type scale, golden ratio spacing and one curve at 900ms.

Very thin, elegant, widely spaced vertical glass forms standing in black space with enormous gaps between them, raked by pale gold light
One object, one light, most of the frame empty. The restraint is the product.

The luxury look has a recipe and the recipe has been stable for ninety years: a high contrast Didone for display, a neutral grotesque for text, light weights, wide tracking on the small stuff. Vogue has set Didot since 1947. Harper's Bazaar has since Alexey Brodovitch took over art direction in 1934. Valentino and Elle use Bodoni or a close derivative, Armani uses Didot, Louis Vuitton uses Futura, Estée Lauder uses Optima.

A Didone puts a hairline next to a heavy stem, the same contrast a tailored seam makes against fabric, and a reader who has never heard the word has been trained by three generations of covers to read it as expensive.

What the category fails at online is everything under the typeface. The call, before the detail: specify the absences, not the adjectives. Luxury is defined by what is missing, and a model asked for elegance adds rather than subtracts. The Thanor library exists because the absences have to be written down as rules.

The overuse of blue and purple gradient fills on the landing page is a telltale sign of AI slop

A developer on Hacker News

The face pairing, with fallback stacks#

Two faces in total. One for display at 36px and above, one for everything else, and no third face anywhere on the site including the footer and the legal line.

  • Display, classical. Didot, substituting Bodoni Moda. Ship Didot, "Didot LT STD", "Bodoni Moda", "Hoefler Text", Garamond, serif.
  • Display, warmer. Canela, substituting Playfair Display. Ship Canela, "Playfair Display", Georgia, serif.
  • Text, grotesque. Neue Haas Grotesk, substituting Helvetica Neue. Ship "Neue Haas Grotesk Text", "Helvetica Neue", Helvetica, Arial, sans-serif.
  • Text, geometric. Avenir Next, substituting Jost. Ship "Avenir Next", Avenir, Jost, "Century Gothic", sans-serif.

Bodoni Moda is the substitute worth knowing because it ships a variable optical size axis, opsz, running 6 to 96. Set font-optical-sizing: auto and the hairlines thicken as the size drops, which is the single failure mode of a Didone on screen: a true Didot at 18px loses its thin strokes to the pixel grid and the page looks cheap in exactly the way you were avoiding.

Canela, from Klim, is the softer alternative: flared serifs rather than true Didone hairlines, so it survives smaller sizes and reads warm rather than imperious. Pick one and delete the other. The two display entries above are alternatives, not a pairing, and the same is true of the two text entries.

One setting matters as much as the choice. Turn on oldstyle figures with font-feature-settings: "onum" 1 for any number inside running text: lining figures in a Didone stand as tall as the capitals and punch holes in a paragraph.

The scale, an augmented fourth#

Ratio 1.414 from 18px. Because 1.414 squared is 2, the ladder doubles every two steps, which is what produces the violent display to body contrast the look is built on.

StepSizeLine heightTrackingFaceUsed for
-113px18px0.18emtexteyebrows, all caps labels
018px31px0.005emtextbody copy
125px36px0textlead paragraph
236px42px-0.01emdisplayh3, product name
351px56px-0.015emdisplayh2
472px76px-0.02emdisplayh1
5102px102px-0.025emdisplaythe one hero line

The 0.18em tracking on step -1 does more work than any other value in the table. All caps at 13px with default letterfit looks like a spreadsheet header. At 0.18em it looks like a label on something that cost money.

  • Display weight: 300 above 51px, 400 below it. A Didone at 700 is not luxury, it is a poster.
  • Text weight: 400 only, with 500 permitted on a button label.
  • Measure on body copy: 58ch to 66ch, narrower than a normal site, because narrow columns in wide space is the magazine signal.
A split frame with thick heavy glass forms packed close together on the left and three hairline thin forms with vast space around them on the right
The ratio between the headline and the column is the whole composition. Both sizes come off one ladder.

The palette, and why it is not black#

Five values on a near black ground. Pure #000000 flattens photographic shadow into a hole, which is fatal when the product is the image.

RoleHexContrast on groundWhere it goes
Ground#0B0B0Fthe page
Raised#141419cards, the sticky header once scrolled
Ink#EFEBE316.52:1all display and body type
Muted#8A857B5.35:1captions, prices, meta
Accent#B08D576.36:1one hairline rule, one link underline

The ink is warm off white, not #FFFFFF. On a dark ground a pure white behaves like a light source and vibrates against the background at small sizes, and the warmth is what keeps a page reading as printed rather than as a screen.

The raised value is only #141419, three steps off the ground, and that narrowness is deliberate. A card that separates from the page by a visible jump in lightness has become a component, and the look depends on surfaces reading as one continuous material with a hairline drawn on it.

The accent appears at most twice per viewport. That is a hard rule and it is the one people break: a bronze used on a button, a rule, an icon and a hover state stops being an accent and becomes a theme. No gradients at all, anywhere, including on images, including as an overlay. Where an image needs its top darkened for legible type, use a flat rgba(11, 11, 15, 0.45) and let the type carry the edge.

Motion at the right two speeds#

One entrance curve, cubic-bezier(0.16, 1, 0.3, 1), an ease out expo, which leaves almost instantly and arrives over a long tail. That asymmetry is what reads as mass.

  • Section entrance: 900ms, opacity 0 to 1, translateY 32px to 0, triggered at 20% of viewport, once.
  • Stagger between siblings: 140ms, capped at five items.
  • Image reveal: 1200ms, scale(1.06) to scale(1) inside an overflow clip, so the frame is still while the picture settles.
  • Hover: 380ms on cubic-bezier(0.33, 1, 0.68, 1). Nav letter spacing moves 0.14em to 0.18em, and nothing translates.
  • Reduced motion: entrances resolve instantly, image reveals do not scale, hovers drop to 1ms.

Three more values complete the system, and each one is a place a generated page reaches for a default instead:

  • Header: transparent over the hero, then #141419 with a 1px hairline in the accent at 0.3 alpha once the scroll passes 64px. The change itself takes 520ms.
  • Page transition: a flat #0B0B0F panel wiping from the bottom, 680ms out on cubic-bezier(0.83, 0, 0.17, 1) and 680ms back. No spinner, no percentage counter, because a luxury page does not report on itself.
  • Cursor: native. A custom cursor is a signature of a different look, and borrowing it here is the most common way a luxury brief ends up reading as a portfolio site.

The mistake nearly everyone makes is applying the slow entrance duration to interaction. A 900ms hover is not luxurious, it is a page that does not answer. Slow is for what arrives, fast is for what responds.

Spacing, and the section order#

Spacing runs on a golden ladder, each step roughly 1.618 times the last: 12, 20, 32, 52, 84, 136, 220. Section padding is 220px top and bottom on desktop, 136px on tablet, 84px on a phone. That is far more air than a normal site and the air is the budget: emptiness is the only thing on a web page that is visibly expensive and impossible to fake.

The order, and why:

  1. Full bleed image, one line of type over it. The line is step 5. Nothing else in the first viewport, no button, no scroll hint.
  2. The statement, a single centred paragraph at step 1, 58ch wide. It exists to slow the scroll before anything is sold.
  3. The object, one large frame, one caption at step -1 in muted.
  4. Three details, a triptych on a 12 column grid, gap 32px, each with a step 2 title and two lines of body.
  5. Provenance, the maker, the material, the place, as a two column text block. This is where a luxury page earns its price and where a generated one has nothing to say.
  6. The editorial pair, one image against one column, alternating side.
  7. The ask, alone on the ground colour, one line and one link with the accent underline. Not a filled button.

Proof goes late here, which inverts the normal rule. A luxury page that opens with logos and review counts has told you it needs the reassurance.

The verdict on building this with a model#

Hand a model the eight values and it builds a luxury page on the first pass. Ask it for luxury and it builds a dark page with a gold gradient, a serif from the safe list, a shadow on every card and a 300ms fade on nine sections. The gap between those two outcomes is entirely the specification, not the model.

What has to be written down, because it will not be inferred:

  • The exact face stack, with the substitute named, and font-optical-sizing.
  • 0.18em on the all caps step, and the weight per size band.
  • The five hex values with the accent limited to twice per viewport.
  • No gradients, stated as a prohibition, and a flat scrim value instead.
  • 900ms in, 380ms on hover, and the fact that those are different.
  • 220px of section padding, and that it does not compress per section.

Writing that list is the job, and it is the same list at the start of every luxury project, on every brief, whatever the product turns out to be. Every prompt in the Thanor library carries it already, for whichever model you build in. If the reference you actually want is a magazine rather than a maison, the editorial specification is the tighter, more textual version of the same discipline, and the general expensive look is the lighter one. When you are ready to skip the day of decisions, browse the Thanor library.

Questions this raises

What fonts do luxury websites use?

A high contrast Didone for display and a neutral grotesque or geometric sans for text. Vogue has set its masthead in Didot since 1947, Harper's Bazaar since Alexey Brodovitch arrived in 1934, and Valentino and Elle use Bodoni or close derivatives.

What type scale suits a luxury website?

An augmented fourth, ratio 1.414, from 18px. It gives 13, 18, 25, 36, 51, 72 and 102 pixels, and because 1.414 squared is 2 the size doubles every two steps, which is what produces the dramatic display to body contrast the look depends on.

Should a luxury site be dark?

Usually, and never pure black. A near black around #0B0B0F with a warm off white ink at #EFEBE3 gives 16.52:1 of contrast and keeps a photographic shadow readable, which pure black flattens.

How slow should luxury motion be?

900ms on cubic-bezier(0.16, 1, 0.3, 1) for a section entrance, 1200ms for an image reveal, and 380ms for hover. Slow entrances read as weight. Slow hovers read as broken, which is the mistake almost everyone makes.

Why does AI generated luxury design usually fail?

Because luxury is defined by what is absent, and an unprompted model adds. A gradient, a second accent, a shadow on everything. Naming the absences as rules is the only instruction that holds.

Can I get this as a prompt instead of building the system myself?

Yes. The Thanor library is available now and its prompts carry the face pairing, the scale, the tracking, the palette, the durations and the section order as literal values.

Part of

The expensive look

What makes a site read as expensive, written as values rather than adjectives: the type scale, the spacing, the curve and its duration, and the order the sections run in.