Styling with Tailwind CSS 4
Master zero-config Tailwind CSS 4, theme.json CSS variable integration, dynamic prose styling, and Gutenberg editor compatibility.
ForgeWP themes use Tailwind CSS 4 for styling. Unlike earlier versions of Tailwind that required complex configuration files (tailwind.config.js), PostCSS pipelines, and custom asset build scripts, Tailwind CSS 4 in ForgeWP is zero-config and CSS-native.
In this guide, you will learn how Tailwind CSS 4 integrates with ForgeWP, how to synchronize design tokens with WordPress theme.json, and how to style both React components and dynamic WordPress Gutenberg content.
CSS-First Configuration
In Tailwind CSS 4, all design tokens, theme customizations, and plugin registrations live directly inside your CSS file (src/app/globals.css) via the @theme directive. There is no tailwind.config.js or tailwind.config.ts to maintain.
Zero-Config Architecture
Every new ForgeWP theme includes a streamlined src/app/globals.css that imports the core Tailwind engine and animation plugins:
1@import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&display=swap");
2@import "tailwindcss";
3@plugin "tailwindcss-animate";
4
5@theme {
6 /* Font Family Mappings */
7 --font-sans: var(
8 --wp--preset--font-family--sans,
9 "Segoe UI",
10 system-ui,
11 sans-serif
12 );
13 --font-heading: "Space Grotesk", var(--font-sans);
14
15 /* Color Palette Mappings linked to WordPress presets */
16 --color-brand: var(--wp--preset--color--brand, #0f172a);
17 --color-brand-foreground: #ffffff;
18 --color-secondary: var(--wp--preset--color--secondary, #4f46e5);
19 --color-accent: var(--wp--preset--color--accent, #f59e0b);
20 --color-background: var(--wp--preset--color--background, #ffffff);
21 --color-foreground: var(--wp--preset--color--text, #09090b);
22
23 /* UI Borders and Surfaces */
24 --color-border: #e4e4e7;
25 --color-muted: #f4f4f5;
26 --color-muted-foreground: #71717a;
27}This single stylesheet achieves three key goals:
- Zero build boilerplate: Vite processes
@import 'tailwindcss'natively with instantaneous Hot Module Replacement (HMR). - Gutenberg Design Token Sync: CSS variables defined in
theme.json(such as--wp--preset--color--brand) are bound directly into Tailwind's utility class generator. - Full Utility Availability: All Tailwind classes (
bg-brand,text-foreground,font-heading,border-border) automatically become available across your React components.
How ForgeWP Syncs Tailwind with WordPress theme.json
A frequent pain point in headless or hybrid WordPress development is maintaining two sets of design tokens: one in CSS/Tailwind for developers, and one in theme.json for Gutenberg site administrators.
ForgeWP solves this with a unified design token pipeline:
Source of Truth:
wp.config.ts -> defineConfig({ settings: { color: { palette: [...] } } })
Target 1: WordPress Block Editor (theme.json)
- Variable: var(--wp--preset--color--brand)
- Consumer: WordPress block editor controls and block content
Target 2: React Theme Components (globals.css)
- Utilities: bg-brand, text-brand, border-brand
- Consumer: React components in src/app/WordPress generates CSS custom properties from the exported theme.json presets. Tailwind utilities that reference those properties use the generated value. Manage the theme-wide palette in wp.config.ts and export it to your PHP-backed hybrid theme.
Essential Layout Utilities for Theme Builders
Modern WordPress themes require responsive, adaptable grid and flexbox layouts. Here are the core patterns used across ForgeWP themes:
1. Responsive Multi-Column Grids
1export function ArchiveGrid({ children }: { children: React.ReactNode }) {
2 return (
3 <div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:gap-8">
4 {children}
5 </div>
6 )
7}grid-cols-1: 1 column on mobile phones (< 640px).sm:grid-cols-2: 2 columns on tablets (≥ 640px).lg:grid-cols-3: 3 columns on desktop monitors (≥ 1024px).gap-6 xl:gap-8: Spacing automatically expands on extra-large screens.
2. Header and Sticky Navigation
1export function SiteHeader() {
2 return (
3 <header className="sticky top-0 z-50 w-full border-b border-zinc-200 bg-white/80 backdrop-blur-md">
4 <div className="mx-auto flex h-16 max-w-7xl items-center justify-between px-4 sm:px-6 lg:px-8">
5 <a href="/" className="text-xl font-bold tracking-tight text-zinc-950">
6 Studio<span className="text-zinc-500">Press</span>
7 </a>
8 <nav className="hidden items-center gap-8 text-sm font-medium text-zinc-600 md:flex">
9 <a href="/about" className="transition hover:text-zinc-950">
10 About
11 </a>
12 <a href="/services" className="transition hover:text-zinc-950">
13 Services
14 </a>
15 <a href="/work" className="transition hover:text-zinc-950">
16 Work
17 </a>
18 <a href="/contact" className="transition hover:text-zinc-950">
19 Contact
20 </a>
21 </nav>
22 </div>
23 </header>
24 )
25}sticky top-0 z-50: Pins the header to the top of the viewport during scrolling.bg-white/80 backdrop-blur-md: Glassmorphism effect that blurs content scrolling underneath.hidden md:flex: Hides desktop navigation on mobile viewports so a mobile drawer can take over.
3. Aspect-Ratio Media Containers
WordPress users upload images with varying resolutions and orientations. To prevent layout shifts (CLS), wrap thumbnails in responsive aspect-ratio containers:
1export function PostThumbnail({ src, alt }: { src: string; alt: string }) {
2 return (
3 <div className="relative aspect-video w-full overflow-hidden bg-zinc-100">
4 <img
5 src={src}
6 alt={alt}
7 className="h-full w-full object-cover transition-transform duration-500 hover:scale-105"
8 loading="lazy"
9 />
10 </div>
11 )
12}Styling WordPress Post Content with Typography (prose)
When rendering the body of a WordPress post or page, content is generated by Gutenberg blocks and contains arbitrary HTML: paragraphs, headings, blockquotes, unordered lists, and embedded images.
In React, this content is passed to your component and rendered using dangerouslySetInnerHTML:
1import { useWpContent, useWpTitle } from "@forgewp/react"
2
3export default function SinglePost() {
4 const title = useWpTitle()
5 const content = useWpContent()
6
7 return (
8 <main className="mx-auto max-w-3xl px-6 py-16">
9 <h1 className="text-4xl font-black tracking-tight text-zinc-950 sm:text-5xl">
10 {title}
11 </h1>
12
13 {/* Styled with Tailwind Typography prose classes */}
14 <article
15 className="prose prose-zinc prose-headings:font-bold prose-headings:tracking-tight prose-a:text-zinc-900 prose-a:underline prose-img:rounded-none prose-img:border mt-8 max-w-none"
16 dangerouslySetInnerHTML={{ __html: content }}
17 />
18 </main>
19 )
20}The @tailwindcss/typography plugin provides the prose class family, which automatically applies sensible, beautiful typographic hierarchy to raw HTML:
Class Purpose proseActivates typographic sizing, margins, line-heights, and vertical rhythm. prose-zincApplies neutral zinc shades to text, headings, blockquotes, and code blocks. max-w-nonePrevents the default 65ch width restriction so the content fills the parent container. prose-headings:font-boldEnforces bold weight on h1, h2, h3, and h4 tags generated by Gutenberg.prose-img:borderAdds a crisp border around embedded post images for clean contrast. |
|---|
Gutenberg Block Editor Compatibility
When WordPress loads your theme inside the Gutenberg block editor (for full-site editing or post editing), it renders the content inside an iframe with the class .editor-styles-wrapper.
Standard CSS resets that set min-height: 100vh on body can cause an infinite height feedback loop inside the Gutenberg editor iframe. ForgeWP's globals.css protects against this:
1@layer base {
2 *,
3 ::before,
4 ::after {
5 border-color: var(--color-border);
6 }
7
8 body {
9 @apply bg-background font-sans text-foreground antialiased;
10 }
11
12 /* Apply 100vh only in front-end preview, NOT inside the Gutenberg editor iframe */
13 body:not(.editor-styles-wrapper):not(#tinymce):not(.mce-content-body) {
14 min-height: 100vh;
15 }
16}
17
18/* Prevent Gutenberg editor iframe height feedback loop */
19.editor-styles-wrapper {
20 min-height: auto !important;
21}Next Step: Interactivity & State
Proceed to State, Interactivity & Auto-Hydration to learn how ForgeWP detects interactive islands and handles client hydration without manual directives. For advanced typography and design token configuration, explore Styling & Design System.