Build · Craft
Grids and fluid type

Grids and fluid type

The Vercel homepage that shipped in October 2023 is documented in What will you ship? (December 2023), presented by Rauno Freiberg with Henry Heffernan, Glenn, and Alasdair Monk. The goals were performance, constraint in visual flair, and bridging pages aesthetically.

A literal frame on every page#

The foundation was a typeface family Basement made for Vercel that year, Swiss inspired and optimised for displays. Asking what pairs with a grotesque sans led to the Swiss design movement, “the raw exposure to the creation of design; blocks, grids, modularity,” and to a metaphor: Vercel is infrastructure for frameworks, so show a literal frame on every page. Design began after Guillermo Rauch’s Config 2023 talk, so Figma variables carried Kevin Rupert’s accessibility-optimised colour system.

The frame does work. Kept in place across navigation, it shows what content swaps out and how fast, lessens pseudo layout shift, and “highlights incredible performance of server rendering.” Crosshairs inspired by print center marks guide the eye. At 1080 wide, columns of 360 give a readable line length for 14 to 16px text, and because everything is a block the layout collapses into mobile. The hero gradient runs the full colour wheel as a metaphor for creativity.

Drawing guides with display: contents#

Drawing the guides was the hard part of Grid.System. Bordering every cell on two sides lacks the grid’s own top and left borders and requires every cell to be filled. The answer was on a guides wrapper holding rows times columns absolutely positioned cells, so they do not interfere with real children. Passing auto as a row or column still works, crosses can sit on any cell, and the grid is server rendered.

CSSRauno Freiberg, What will you ship?
.grid {  display: grid;  grid-template-columns: repeat(var(--columns), 1fr);  grid-template-rows: repeat(var(--rows), 1fr);  border: 2px solid #666;  border-right: none;  border-bottom: none;  position: relative;}.grid-guides {  display: contents;}.grid-guide {  inset: 0px;  position: absolute;  grid-column-start: var(--x);  grid-column-end: span 1;  grid-row-start: var(--y);  grid-row-end: span 1;  border: 2px solid #666;  border-left: none;  border-top: none;}

The grid also sets a rhythm. “If every element made repetitive use of a strong accent color, the color would no longer feel as significant,” and the same holds for the cross motif and for animation. The essay maps the page orange for high novelty (a graph tooltip animating a long distance, icons pixelating on hover) and blue for low (floating cursors, icons scaling on hover); each animation gets an interlude, and high-novelty ones never sit in consecutive sections. That is as a layout decision.

Grid lines and fluid type on Next.js#

The grid lines on the Next.js site, from Crafting the Next.js Website, are absolutely positioned pseudo elements that flex with content. Rauno borrowed the dotted line from Stripe: a repeating linear gradient gives more control than a dotted border, and a mask fades the ends.

CSSRauno Freiberg, Crafting the Next.js Website
.gridLine {  --height: 1px;  --width: 5px;  --fade-stop: 90%;  --offset: -100px;  background: linear-gradient(    to right,    var(--color),    var(--color) 50%,    transparent 0,    transparent  );  background-size: var(--width) var(--height);}h1 {  font-size: clamp(48px, 5vw, 76px);}

The same essay holds his first use of clamp. He had always adjusted type at manual breakpoints; the hero instead scales between 48px and 76px at 5vw, which “helps to responsively adjust any property between a minimum and maximum value.” In the figure below, watch where the line goes flat at each end.

Viewport
1280px
Preferred
64.0px
Resolved
64.0px
160 px3201920viewport

Scaling with the viewport: 5vw sits between the two limits.

font-size: clamp(48px, 5vw, 76px);switches at 960px and 1520px
Adjust
Figure 3. Fluid type with clamp(). Drag the dot across the chart, or use the slider, and watch the size move through three regimes: pinned at the minimum, scaling with the viewport, pinned at the maximum. The shaded bands are where clamp() pins; the dimmed line is the curve before your last change. The defaults are the Next.js site's hero values.Constants from the source

Container, viewport, reader setting#

The Vercel visuals answer to their container. All are built in code without external libraries, for quality, control, and responsiveness. With stable, a widget responds to the space it actually has. The orbit rings move an element on offset-path: content-box, which uses the parent as trajectory and respects its radius; as of 2023 it misbehaved in Safari and Firefox, Safari 17.2 fixed it on 12/12, and an SVG circle path string was the fallback.

CSSRauno Freiberg, What will you ship?
.root {  container-type: inline-size;}@container (max-width: 560px) {  .scope {    display: none;  }}

Andrew Swank’s personal site is built from scratch “to show how design and engineering can work together to create a better experience for both parties.” Its features are CSS decisions: layout and type sized from the viewport with vmin and rem; “Predictable sizing via max() and round() to snap to a 4-pixel grid”; HSL custom properties so colours animate without dulling; and Roboto Flex animated with font-variation-settings.

What rem is relative to is Paco Coursey’s subject in px vs rem in font-size (2022). On html there is no parent, so the reference is the browser’s font scaling, 16px by default but adjustable from 9 to 72; zoom (⌘+ and ⌘-) scales additively on top. Almost all sites ignore scaling; cnn.com did it well, scaling main content with rem and leaving navigation alone.

Get the browser default font size (2023) gives the probe: font-size: medium resolves to the default, typically 16px; with Chromium set to Very Large it reads 24px. If you reach for rem, leave the root size alone so that setting reaches the page.

CSSPaco Coursey, Get the browser default font size
.measure-element {  font-size: medium;}