postcss-prefixwrap
A PostCSS plugin that wraps every CSS rule in a container selector to scope styles safely.
Repository Health
Technical Analysis
postcss-prefixwrap is a PostCSS plugin that prepends a chosen CSS selector to every rule in a stylesheet, effectively wrapping the entire file’s styles so they only apply inside a specific container element. This is the common fix for embedding one site’s or widget’s CSS inside another page without the two style sheets bleeding into each other.
Beyond simple prefixing, the plugin handles the edge cases that make CSS scoping hard in practice: html/body/:root selectors are rewritten into the container class instead of being left dangling, @keyframes percentage selectors are left untouched, and nested rules produced by plugins like postcss-nested are skipped via a configurable nested marker. Whitelist/blacklist options let you scope prefixing to specific files by path, ignoredSelectors exempts specific selectors (strings or regex) from being wrapped, and a prefixTransform callback gives full custom control over how each selector is rewritten.
It supports both the PostCSS v7 and v8 plugin APIs transparently (detecting which one it’s given at runtime) and ships prebuilt for Node.js, Bun, and Deno, with TypeScript types included.
What You Get
- A single-purpose PostCSS plugin: pass a container selector and it wraps every rule in the processed stylesheet under that selector.
- Automatic handling of
html,body, and:rootselectors, which are rewritten into the container rather than left broken. - Whitelist and blacklist options (regex-matched file paths) to scope prefixing to specific stylesheets in a build.
ignoredSelectors(string or RegExp) to exempt selectors like:rootor third-party IDs from being wrapped.- A
nestedoption to skip selectors already nested under&when combined with plugins like postcss-nested. - A
prefixTransformcallback for full custom control over how each selector is rewritten, instead of simple string concatenation. - Dual support for the PostCSS v7 and v8 plugin APIs, detected automatically at runtime from the
postcssinstance passed in.
Common Use Cases
- Embedding a widget’s or third-party component’s stylesheet into a host page without its rules affecting the rest of the page.
- Publishing a design system or admin panel’s CSS for reuse inside a client’s existing site under a wrapping container class.
- Isolating legacy CSS so it can be maintained without editing every selector by hand, per the maintainer’s own ‘Maintainable Legacy CSS’ use case.
- Building multi-tenant or white-label front ends where each tenant’s theme CSS needs to be scoped to a specific container per page.
Under The Hood
Architecture
The package is a thin, well-separated pipeline: PostCSSPlugin.ts inspects the postcss instance handed to it (via isPostCSSv8, which checks for a Root export) and dispatches to either PostCSS7Plugin.ts (wrapping the legacy postcss.plugin() factory) or PostCSS8Plugin.ts (returning a plugin object with an Once hook), both of which delegate the actual work to a shared PostCSSPrefixWrap class. That class walks the stylesheet’s rules and hands each one to internal/domain/CSSRuleWrapper.ts, which in turn defers selector-level decisions (root tags, keyframes, ignored selectors, custom transforms) to small pure functions in internal/domain/CSSSelector.ts and file-scoping decisions to FileIncludeList.ts. The domain layer has no dependency on the plugin-adapter layer, so the core rewriting logic is fully decoupled from which PostCSS API version is in use.
Tech Stack
Written in TypeScript against the postcss peer dependency (accepting any version via peerDependencies: { postcss: "*" }), built with tsc into a build/ output with bundled .d.ts types, and tested with Jest via ts-jest. Tooling is modern and cross-runtime: the project explicitly targets Node.js, Bun, and Deno, uses pnpm for local development, husky for git hooks, and prettier/sort-package-json for formatting and lint checks enforced in CI.
Code Quality
The test suite is extensive relative to the package’s scope: sixteen dedicated spec files cover standard prefixing, blacklist/whitelist file scoping, nested selectors, keyframe percentages, media queries, HTML/body tag replacement, ignored and exact-match selectors, custom prefix transforms, and selectors with special characters, each backed by fixture CSS files comparing raw input against expected output. Types are used throughout the public and internal APIs (PostCSSPrefixWrapOptions, PostcssV7, PostCSSAcceptedPlugin), and CI runs lint, test, and build steps across three separate runtimes (Bun, Deno, and two Node.js versions) on every push and pull request.
What Makes It Unique Rather than treating PostCSS API compatibility as an afterthought, the plugin detects the installed PostCSS major version at runtime and transparently adapts its own plugin shape, so a single published package supports both v7 and v8 consumers without requiring separate installs. Its handling of edge cases most naive selector-prefixing scripts miss — keyframe percentages, root-tag rewriting, nested-selector awareness, and a fully custom transform hook — reflects a library that has been hardened against real-world stylesheet embedding problems over many small releases rather than built once and left alone.
Used by 4 apps in this directory
Cal.diy
Scheduling
The 100% MIT-licensed, community-driven scheduling platform — self-host your own booking infrastructure with no enterprise strings attached.
GraphQL Hive
Developer Tools · Devops · Monitoring
Open-source GraphQL schema registry and observability platform with breaking change detection, federation support, and CI/CD integration for teams of any size.
Metabase
Analytics
The open-source BI platform that lets anyone ask questions and build dashboards without writing SQL — with an embedded analytics SDK and AI-powered query assistant included.
Zulip
Team Chat
Topic-based team chat that brings the structure of email threads to real-time messaging, so distributed teams never lose context across hundreds of concurrent conversations.