foldout

Tailwind landing page checklist: what to check before you ship

Most landing-page bugs aren't visual. They're the unbuilt class, the form that posts to #, the dark mode that inverts a logo, the missing meta description. This is the list we run on our own templates.

Build

  1. The CSS is built, not the CDN. <script src="https://cdn.tailwindcss.com"> is for prototypes: 300 KB, runs in the browser, and Tailwind prints a warning about it. Ship the compiled file:
build once, minified
npx @tailwindcss/cli -i src/input.css -o assets/css/style.css --minify
  1. Every class you use exists in the output. Tailwind only emits classes it finds in your files. A class built from a string at runtime (bg-${color}-500) is never emitted. Search the built CSS for one suspicious class before assuming.

  2. No unused framework. No jQuery, no slider library for two testimonials. If the page needs JavaScript, it’s a few dozen lines you can read.

Dark mode

  1. Tokens, not utilities, for colour. bg-[color:var(--bg)] or plain CSS variables on :root, with a dark set under prefers-color-scheme: dark — and data-theme on <html> to override. The page then has one place to redesign the dark palette instead of a dark: variant on every element.

  2. The logo and the photos survive inversion. A black wordmark on a dark background is the classic. Use currentColor for the logo; check every image on a dark background once.

  3. The theme is set before first paint. A two-line inline script in <head> that reads localStorage and sets data-theme; otherwise the page flashes light before going dark.

Typography and layout

  1. One <h1>. Headings in order after it. <h3> under <h2>, not because it looks smaller.
  2. Body text at 16–18 px, line length 60–75 characters. max-w-prose is 65ch; use it on paragraphs, not on the section.
  3. 360 px wide works. Not 375, not 390 — 360 is the width a lot of Android phones report. Nothing overflows horizontally; check with document.documentElement.scrollWidth.
  4. Tap targets 44 px. Buttons h-11 or more; nav links with padding, not just text.
  1. The form posts somewhere. action="#" is a placeholder. Point it at your form handler and test a submission.
  2. Every input has a <label>. Placeholder text is not a label; it vanishes when you type.
  3. External links have rel="noopener". And target="_blank" only when you mean it.
  4. No dead anchors. href="#" on a “Learn more” is a broken promise; link to the section or remove the button.

Performance

  1. Images have width and height. Layout doesn’t shift when they load. Add loading="lazy" below the fold and decoding="async".
  2. The hero image is under 200 KB. WebP or AVIF, sized for the largest slot it fills, not the original 4000 px.
  3. Fonts: two files at most, font-display: swap, preloaded. Or system fonts — nothing to load, no flash.
  4. Zero third-party requests you don’t need. Analytics, chat widgets and tag managers each cost more than the page.

Accessibility

  1. Contrast at 4.5:1 for text, in both themes. Muted grey on off-white fails more often than you’d think; measure it.
  2. Visible focus. :focus-visible { outline: 2px solid … } and never outline: none without a replacement. Tab through the whole page once.
  3. Alt text that says what the image is for, and alt="" on decorative ones.

SEO metadata

  1. Title, description, canonical, OG image, favicon. The description under 160 characters and specific to the page; the OG image 1200×630 and actually present at the URL. Then the two lines everybody forgets:
in <head>
<link rel="canonical" href="https://example.com/">
<meta name="theme-color" content="#FBFAF8" media="(prefers-color-scheme: light)">

The one-minute version

Open the page in a private window at 360 px wide with dark mode on and JavaScript off. If it still looks right, reads in order, and the form submits, you’ve passed most of this list.