tailwindcss-scoped-preflight: Scope Tailwind CSS Preflight Styles

Scope Tailwind CSS preflight to a selector with tailwindcss-scoped-preflight. Stop style conflicts with Ant Design, Vuetify, and other UI libraries.

tailwindcss-scoped-preflight is a Tailwind CSS plugin that scopes Tailwind’s global preflight reset to a specific CSS selector.

When you mix Tailwind with a component library like Ant Design, Vuetify, or any other UI framework, Tailwind’s preflight stylesheet applies a CSS reset to every element on the page.

This destroys the default styles that third-party libraries depend on and creates cascading conflicts that are painful to debug.

This plugin addresses that collision by locking preflight inside a container class you control, or by excluding a third-party zone from preflight’s reach.

Features

  • Scope Tailwind Preflight to one or more root containers.
  • Protect legacy markup from Tailwind reset rules.
  • Exclude nested third party content inside a Tailwind area.
  • Reapply scoped Preflight inside selected child containers.
  • Configure Tailwind CSS v4 projects directly from CSS.
  • Support JavaScript config for gradual migration and SCSS workflows.
  • Remove selected Preflight rules when a project needs stricter control.
  • Keep selected Preflight selectors untouched when required.

How to Use It

Install

Install the package with your preferred package manager.

npm install tailwindcss-scoped-preflight

Basic Usage

This minimal setup scopes Tailwind Preflight to .twp and keeps the reset away from the rest of the page.

/* app.css */
/* Import Tailwind theme tokens. */
@import "tailwindcss/theme";
/* Import Tailwind utilities. */
@import "tailwindcss/utilities";
/* Scope Preflight to the .twp container. */
@plugin "tailwindcss-scoped-preflight" {
  isolation-strategy: inside;
  selector: .twp;
}
<!-- Only this container receives scoped Tailwind Preflight styles. -->
<div class="twp">
  <section class="rounded-xl border p-6">
    <h2 class="text-xl font-semibold">Scoped Tailwind Area</h2>
    <p class="mt-2 text-sm text-gray-600">
      Existing page styles outside this wrapper stay separate from Tailwind Preflight.
    </p>
  </section>
</div>

Do not use @import "tailwindcss"; in this setup. That import includes the default global Preflight layer, so the scoped reset and the global reset would both appear in the output CSS.

Example 1: Scope Tailwind Inside a Widget Root

Use this example for an embeddable widget, browser extension panel, marketing popup, or CMS block that runs inside a larger page.

/* widget.css */
@import "tailwindcss/theme";
@import "tailwindcss/utilities";
/* Limit Tailwind Preflight to the widget shell. */
@plugin "tailwindcss-scoped-preflight" {
  isolation-strategy: inside;
  selector: .support-widget;
}
<aside class="support-widget fixed bottom-6 right-6 w-80 rounded-2xl bg-white p-5 shadow-xl">
  <h3 class="text-base font-semibold">Support Center</h3>
  <p class="mt-2 text-sm text-gray-600">
    Ask for help or browse common questions.
  </p>
  <button class="mt-4 rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white">
    Open Chat
  </button>
</aside>

The wrapper class matters. Every Tailwind styled element that needs scoped Preflight should live inside .support-widget.

Example 2: Exclude Third Party Markup Inside a Tailwind Area

Use except when a Tailwind container includes content that comes from a CMS editor, a markdown renderer, or a third party component.

/* dashboard.css */
@import "tailwindcss/theme";
@import "tailwindcss/utilities";
/* Apply Preflight inside .client-dashboard but skip .rich-text-content. */
@plugin "tailwindcss-scoped-preflight" {
  isolation-strategy: inside;
  selector: .client-dashboard;
  except: .rich-text-content;
}
<div class="client-dashboard p-6">
  <div class="rounded-xl border bg-white p-5">
    <h1 class="text-2xl font-bold">Client Report</h1>
    <p class="mt-2 text-sm text-gray-600">
      Tailwind controls the dashboard shell.
    </p>
  </div>
  <!-- CMS content keeps its own typography and element defaults. -->
  <article class="rich-text-content mt-6">
    <h2>Imported Article Title</h2>
    <p>This markup may come from a CMS, WYSIWYG editor, or external renderer.</p>
  </article>
</div>

This is where the plugin is most useful. The page can use Tailwind for layout and controls, while imported content keeps its expected element behavior.

Example 3: Protect a Legacy Container and Reapply Preflight for a Nested Tailwind Panel

Use outside when most of the page may use Tailwind, but one area needs protection from Preflight. Add plus when a Tailwind panel sits inside that protected area.

/* legacy-shell.css */
@import "tailwindcss/theme";
@import "tailwindcss/utilities";
/* Protect .legacy-area from Preflight. Reapply it inside .tailwind-panel. */
@plugin "tailwindcss-scoped-preflight" {
  isolation-strategy: outside;
  selector: .legacy-area;
  plus: .tailwind-panel;
}
<div class="legacy-area">
  <table class="old-report-table">
    <tr>
      <td>Legacy table styles stay under the old CSS rules.</td>
    </tr>
  </table>
  <div class="tailwind-panel mt-6 rounded-xl border p-4">
    <h2 class="text-lg font-semibold">New Tailwind Panel</h2>
    <button class="mt-3 rounded-md bg-slate-900 px-3 py-2 text-sm text-white">
      Review Changes
    </button>
  </div>
</div>

This pattern works well during phased redesigns. The older interface can remain stable, and the new Tailwind section can still receive Preflight.

Example 4: Use JavaScript Config During Migration

Use this approach when a project still depends on tailwind.config.js, SCSS preprocessing, or a gradual Tailwind CSS v4 migration.

// tailwind.config.js
import scopedPreflightStyles from "tailwindcss-scoped-preflight";
export default {
  plugins: [
    scopedPreflightStyles({
      // Use the v4 string based option names in JavaScript config.
      isolationStrategy: "inside",
      // Scope Preflight to the Tailwind application root.
      selector: ".admin-tailwind",
    }),
  ],
};
/* app.css */
@import "tailwindcss/theme";
@import "tailwindcss/utilities";
/* Load the JavaScript config from the CSS entry file. */
@config "./tailwind.config.js";

This option helps SCSS users because Sass can misread the CSS @plugin option block. A plain CSS file is still the cleaner choice for new Tailwind CSS v4 projects.

Configuration Options

  • isolation-strategy (string): Sets the isolation mode. Use inside to apply Preflight only inside the target selector. Use outside to protect the target selector from Preflight.
  • selector (CSS selector or comma separated selector list): Defines the container or protected area. Examples include .twp, [data-tailwind], or .twp, [twp].
  • except (CSS selector): Excludes nested elements from the inside strategy. This works well for CMS content, markdown output, or third party widgets inside a Tailwind root.
  • root-styles (string): Controls how root styles such as html, body, and :host move into the scoped selector. The default behavior moves them to the container.
  • plus (CSS selector): Reapplies Preflight to selected Tailwind content inside an area protected by the outside strategy.
  • ignore (comma separated CSS selector list): Leaves selected Preflight selectors untouched by the isolation strategy.
  • remove (comma separated CSS selector list): Removes selected Preflight rules from the generated output.

Related Resources

FAQs

Q: Why should I replace @import "tailwindcss"?
A: The full Tailwind import includes global Preflight. Use @import "tailwindcss/theme" and @import "tailwindcss/utilities" when you want this plugin to generate the scoped Preflight layer.

Q: Why are my scoped Preflight styles not applied?
A: Check that your Tailwind markup sits inside the selector defined in the plugin block. For example, a setup that uses selector: .twp; requires a parent element with class="twp".

Q: Can I use this plugin with SCSS?
A: Yes, but the safest setup uses a separate plain CSS file for Tailwind imports and the @plugin block. Import that CSS file from SCSS. You can also use @config and place the plugin options in tailwind.config.js.

Q: Does this plugin scope Tailwind utility classes too?
A: No. It scopes Preflight reset styles. Tailwind utilities still work through their normal class names, so you still need careful class naming when you embed Tailwind UI into pages with existing CSS.

Roman Kozodoi

Roman Kozodoi

Leave a Reply

Your email address will not be published. Required fields are marked *