Preflight
Purpose and Scope
Preflight is Tailwind CSS’s base reset layer: an opinionated stylesheet that makes browser defaults more predictable before utility classes are applied. The official documentation describes it as built on top of modern-normalize and automatically included when a project imports Tailwind. In repository terms, the behavior is centered on the standalone stylesheet at packages/tailwindcss/preflight.css, while upgrade-time compatibility for one of the most visible reset changes is handled by the PostCSS codemod in packages/@tailwindcss-upgrade/src/codemods/css/migrate-preflight.ts. Together, these files explain both the current reset contract and the migration story for projects moving from v3 assumptions to v4 defaults.
Sources: packages/tailwindcss/preflight.css, packages/@tailwindcss-upgrade/src/codemods/css/migrate-preflight.ts
Preflight matters because utility-first styling depends on a stable baseline. A class like border is easier to reason about when every element starts with predictable box sizing, margin, padding, and border style behavior. The reset also prevents typography and layout from accidentally depending on user-agent styles that are outside the design system. That is why headings are intentionally unstyled, links inherit color and text decoration, tables collapse borders, and the root font defaults are expressed through Tailwind theme-backed custom values rather than through browser-specific defaults.
Relevant Source Files
packages/tailwindcss/preflight.css— Defines Tailwind’s base reset rules for box sizing, margin, padding, borders, root typography defaults, headings, links, tables, focus outlines, and other browser normalization behavior visible in the supplied stylesheet excerpt.packages/@tailwindcss-upgrade/src/codemods/css/migrate-preflight.ts— Defines the upgrade codemod that detects Tailwind imports in CSS, injects v3 compatibility styles when needed, substitutestheme(...)values, and removes obsolete--border-colortheme declarations.
Base Reset Behavior
The first major rule in Preflight applies to every element and key pseudo-elements: *, ::after, ::before, ::backdrop, and ::file-selector-button. It sets box-sizing: border-box, removes margin and padding, and resets borders with border: 0 solid. This is the reset that makes Tailwind’s spacing and border utilities opt-in. Instead of inheriting browser-provided margins on headings or paragraphs, authors add spacing utilities explicitly. Instead of relying on browser border styles, authors can add width, color, and style through Tailwind classes against a known starting point.
Sources: packages/tailwindcss/preflight.css
The root rules for html and :host establish typography and interaction defaults. The stylesheet sets a consistent line-height, prevents iOS text-size adjustment, uses a readable tab size, and disables iOS tap highlights. It also routes the default sans font family, font feature settings, and font variation settings through Tailwind’s theme-aware --theme(...) function, with fallbacks to common system font stacks and normal feature or variation settings. This keeps the reset aligned with the CSS-first theme model rather than hard-coding all typography choices outside the design system.
Sources: packages/tailwindcss/preflight.css
Several element-level rules remove surprising browser defaults while preserving semantic HTML. Headings from h1 through h6 inherit font size and weight, so semantic heading structure does not automatically impose a visual scale. Anchors inherit color and text decoration so links can be styled intentionally. Code-like elements use the configured mono font family and related feature settings. Tables reset indentation, inherit border color, and collapse borders. These are not utility classes; they are the baseline that makes later utilities produce consistent results across projects and browsers.
Sources: packages/tailwindcss/preflight.css
Import Model and Layering
The official installation flow tells users to add @import "tailwindcss"; to their input CSS, and the Preflight documentation expands that import into layered pieces: theme, base, and utilities. Preflight lives in the base layer, between theme variables and generated utilities. That ordering is important: theme values are available to the reset where needed, but utilities still win later in the cascade. If a project wants to override an opinionated reset, the recommended pattern is to add custom base CSS rather than fighting individual utilities or depending on browser defaults.
@layer theme, base, components, utilities;
@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/preflight.css" layer(base);
@import "tailwindcss/utilities.css" layer(utilities);Although the source file is plain CSS, it is designed to be consumed as part of Tailwind’s layered build. For day-to-day application authors, this means Preflight is normally present without a separate decision once Tailwind is imported. For integration authors and advanced users, it means packages/tailwindcss/preflight.css is the reference point for what the base layer contributes before utilities are generated. When debugging a reset issue, first determine whether the behavior comes from Preflight, a custom @layer base rule, or a utility applied later in the cascade.
Sources: packages/tailwindcss/preflight.css
Migration Compatibility
The upgrade codemod focuses on a specific Preflight migration concern: the default border color change in Tailwind CSS v4. The code defines DEFAULT_BORDER_COLOR as currentcolor and includes a compatibility CSS block explaining that v4 changed the default border color to currentcolor, while v3 projects may have depended on the older theme(borderColor.DEFAULT) behavior. The codemod only injects this compatibility CSS when it is operating in a v3 migration context and when the user’s default border color differs from the v4 default.
Sources: packages/@tailwindcss-upgrade/src/codemods/css/migrate-preflight.ts
The codemod is implemented as a PostCSS plugin named @tailwindcss/upgrade/migrate-preflight. Its OnceExit handler scans CSS @import rules and only proceeds when the root imports either tailwindcss or tailwindcss/preflight. This avoids appending compatibility CSS to unrelated stylesheets. When it does proceed, the plugin wraps generated compatibility styles in an @tw-bucket compatibility block, parses that block with PostCSS, substitutes theme(...) calls where necessary, and appends the result to the root stylesheet.
Sources: packages/@tailwindcss-upgrade/src/codemods/css/migrate-preflight.ts
A second migration cleanup removes --border-color declarations from @theme rules. After removing those declarations, the codemod deletes an empty @theme rule if no nodes remain. This is a useful signal for maintainers: Preflight migration is not only about adding compatibility CSS, but also about cleaning obsolete theme variables that would otherwise preserve v3-era assumptions. The result is a stylesheet that can keep old visuals stable during upgrade while moving the project toward the v4 base reset and theme model.
Sources: packages/@tailwindcss-upgrade/src/codemods/css/migrate-preflight.ts
Practical Guidance
When Preflight surprises you, identify whether the reset is intentionally removing a browser default or whether a third-party component expects that default to exist. Common examples include elements that relied on margins, headings that expected browser font sizes, or embedded widgets that assume default border styles. The right fix is usually explicit CSS in the base layer or explicit utility classes at the component boundary. For example, a third-party map widget that breaks because all borders start as 0 solid can be scoped with a base-layer override instead of disabling Tailwind globally.
@layer base {
.google-map * {
border-style: none;
}
}For new projects, treat Preflight as part of Tailwind’s contract: import Tailwind, write semantic markup, and opt into visual decisions with utilities or base-layer styles. For upgrades, run the upgrade tooling and inspect any compatibility output around border color. If the compatibility block preserves a visual dependency you still need, replace that dependency with explicit border color utilities or scoped CSS before removing the compatibility styles. Next, read the Theme page for how --theme(...) defaults connect to design tokens, and the Upgrade Guide for the broader v3-to-v4 migration flow.