Published on 2026-03-22
responsive font-weight with tailwind
I love the IBM Plex Mono font, but the normal font weight (400) is too heavy for my taste.
Yet, on a standard display, with 72 or 96 DPI, the lighter weights are too thin. Colors fade and the text becomes harder to read.
On a HiDPI display, with 200+ DPI, the lighter weights look much better. And on an ultra HiDPI display, with 300+ DPI, the lightest weights look amazing.
So I decided to make the font weight responsive!
| DPI | normal | bold || ------------------ | ------ | ---- || Standard (72-96) | 400 | 600 || HiDPI (200+) | 300 | 500 || Ultra HiDPI (300+) | 200 | 400 |
To achieve this, we need to do 3 things:
- Custom
@font-facerules - Responsive Tailwind theme variables for font weight.
- Responsive preload of font files.
Custom @font-face rules
Custom @font-face rules using font-display: block to prevent flash of
unstyled text (FOUT). The @fontsource package defaults to
font-display: swap, which can’t be overridden via CSS cascade.
See: https://fontsource.org/docs/getting-started/display
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-display: block; font-weight: 200; src: url("@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-200-normal.woff2") format("woff2"), url("@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-200-normal.woff") format("woff"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}@font-face { font-family: "IBM Plex Mono"; font-style: italic; font-display: block; font-weight: 200; src: url("@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-200-italic.woff2") format("woff2"), url("@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-200-italic.woff") format("woff"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}/* And the same for weights 300, 400, 500, 600 */
Responsive Tailwind theme variables for font weight
@theme { /* restrict to only the weights you use */ --font-weight-*: initial; --font-weight-normal: 400; --font-weight-bold: 600;}@layer base { body { /* browser default "normal" is hardcoded 400 */ @apply font-normal; } /* override for HiDPI, e.g. MacBook Pro Retina */ @media (min-resolution: 2dppx) { :root { --font-weight-normal: 300; --font-weight-bold: 500; } } /* override for ultra HiDPI, e.g. iPhone, iPad Pro */ @media (min-resolution: 3dppx) { :root { --font-weight-normal: 200; --font-weight-bold: 400; } }}
Responsive preload of font files
If you use Astro it’s done as follows:
// layout.astroimport latin200italic from "@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-200-italic.woff2?url";import latin200normal from "@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-200-normal.woff2?url";import latin300italic from "@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-300-italic.woff2?url";import latin300normal from "@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-300-normal.woff2?url";import latin400italic from "@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-400-italic.woff2?url";import latin400normal from "@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-400-normal.woff2?url";import latin500italic from "@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-500-italic.woff2?url";import latin500normal from "@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-500-normal.woff2?url";import latin600italic from "@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-600-italic.woff2?url";import latin600normal from "@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-600-normal.woff2?url";<!doctype html><html lang="en"> <head> <!-- ... --> <!-- smaller than 2dppx: normal=400, bold=600 --> <link rel="preload" href={latin400normal} media="(resolution < 2dppx)" as="font" type="font/woff2" crossorigin /> <link rel="preload" href={latin400italic} media="(resolution < 2dppx)" as="font" type="font/woff2" crossorigin /> <link rel="preload" href={latin600normal} media="(resolution < 2dppx)" as="font" type="font/woff2" crossorigin /> <link rel="preload" href={latin600italic} media="(resolution < 2dppx)" as="font" type="font/woff2" crossorigin /> <!-- 2dppx to 3dppx: normal=300, bold=500 --> <link rel="preload" href={latin300normal} media="(resolution >= 2dppx) and (resolution < 3dppx)" as="font" type="font/woff2" crossorigin /> <link rel="preload" href={latin300italic} media="(resolution >= 2dppx) and (resolution < 3dppx)" as="font" type="font/woff2" crossorigin /> <link rel="preload" href={latin500normal} media="(resolution >= 2dppx) and (resolution < 3dppx)" as="font" type="font/woff2" crossorigin /> <link rel="preload" href={latin500italic} media="(resolution >= 2dppx) and (resolution < 3dppx)" as="font" type="font/woff2" crossorigin /> <!-- 3dppx+: normal=200, bold=400 --> <link rel="preload" href={latin200normal} media="(resolution >= 3dppx)" as="font" type="font/woff2" crossorigin /> <link rel="preload" href={latin200italic} media="(resolution >= 3dppx)" as="font" type="font/woff2" crossorigin /> <link rel="preload" href={latin400normal} media="(resolution >= 3dppx)" as="font" type="font/woff2" crossorigin /> <link rel="preload" href={latin400italic} media="(resolution >= 3dppx)" as="font" type="font/woff2" crossorigin />