Chrome Extension Tailwind CSS — Developer Guide
3 min readTailwind CSS for Chrome Extensions
Tailwind CSS brings utility-first styling to Chrome extension development, offering rapid UI with minimal CSS. This guide covers integrating Tailwind into extension contexts while handling unique browser extension constraints.
Setting Up Tailwind
Install and initialize:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
Configure tailwind.config.js:
module.exports = {
content: [
"./src/**/*.{html,js,ts,jsx,tsx}",
"./popup/**/*.{html,js,ts,jsx,tsx}",
"./options/**/*.{html,js,ts,jsx,tsx}",
],
theme: { extend: {} },
plugins: [],
}
Popup and Options Pages
Popup and options pages run in privileged extension contexts, making Tailwind setup straightforward. These pages behave like standard web pages without page style interference.
<div class="w-80 p-4 bg-white dark:bg-gray-900">
<h1 class="text-lg font-semibold">Extension</h1>
<button class="mt-2 px-4 py-2 bg-blue-600 text-white rounded">Click Me</button>
</div>
Content Scripts with Shadow DOM
Content scripts face a challenge: injected styles leak into the host page. Shadow DOM with adoptedStyleSheets provides isolation.
Create a shadow DOM wrapper:
const host = document.createElement('div');
host.id = 'my-extension-root';
document.body.appendChild(host);
const shadow = host.attachShadow({ mode: 'open' });
Inject styles:
import styles from './tailwind.css?inline';
const styleSheet = new CSSStyleSheet();
styleSheet.replaceSync(styles);
shadow.adoptedStyleSheets = [styleSheet];
shadow.innerHTML = `<div class="p-4 bg-white rounded">Action</div>`;
This keeps your Tailwind styles isolated from page CSS.
Using shadcn/ui Components
shadcn/ui provides accessible components built on Radix UI. Install dependencies:
npm install tailwindcss-animate class-variance-authority clsx tailwind-merge
Configure tailwind.config.js:
module.exports = {
darkMode: ['class'],
content: ['./src/**/*.{ts,tsx}', './components/**/*.{ts,tsx}'],
plugins: [require('tailwindcss-animate')],
}
Use components:
import { Button } from '@/components/ui/button';
import { Card } from '@/components/ui/card';
export function ExtensionPopup() {
return (
<Card className="w-72 p-4">
<h2 className="text-xl font-bold">My Extension</h2>
<Button className="w-full">Get Started</Button>
</Card>
);
}
Preventing Style Conflicts
Use a scoped prefix to avoid collisions:
module.exports = { prefix: 'ext-' }
Apply prefixed classes: <div class="ext-flex ext-items-center">.
Build Size Optimization
Extensions demand aggressive optimization:
export default {
plugins: [
require('tailwindcss'),
require('autoprefixer'),
cssnano({ preset: ['default', { discardComments: { removeAll: true } }] }),
],
}
This removes unused styles and keeps your extension package lean.
Extension-Specific Configuration
Popups max out around 400x600 pixels. Configure Tailwind:
module.exports = {
theme: {
extend: {
maxWidth: { popup: '360px' },
maxHeight: { popup: '600px' },
},
},
}
Use these constraints in your popup layout for responsive designs within extension viewport limits.
For more extension development patterns and tools, explore the resources at zovo.one.
Related Articles
Related Articles
Part of the Chrome Extension Guide by theluckystrike. Built at zovo.one.