'Chrome extension Tailwind CSS interferes with websites I visit

I am building a chrome extension. I am using React, Typescript, TailwindCSS, custom Webpack config. I've overwritten default action in manifest.json so clicking the toolbar icon triggers a message and opens content script, which injects layover on any site.

The issue I am facing is that my Tailwind styles affect every website I visit and sometimes otherwise. Eg. google search websites have smaller titles, on Reddit my extension has much smaller text.

I would like my extension styles to be applied only to my layover. I've already tried using React Shadow DOM but it didn't work, I might have done something wrong.

Here are my files:

manifest.json

{
    "name": "Intro",
    "description": "Intro extension",
    "version": "1.0.0",
    "manifest_version": 3,
    "icons": {
        "16": "icon.png",
        "48": "icon.png",
        "128": "icon.png"
    },
    "action": {
        "default_title": "Intro",
        "default_icon": "icon.png"
    },
    "permissions": ["alarms", "contextMenus", "storage"],
    "options_page": "options.html",
    "background": {
        "service_worker": "background.js"
    },
    "content_scripts": [
        {
            "matches": ["<all_urls>"],
            "js": ["contentScript.js"]
        }
    ]
}

contentScript.tsx

import React, { useEffect, useState } from 'react';
import ReactDOM from 'react-dom';
import { Messages } from '../utils/types';
import '@fontsource/roboto';
import { useDelayUnmount } from '../hooks/useDelayUnmount';
import App from '../App';
import './contentScript.css';

const mountedStyle = { animation: 'inAnimation 150ms ease-in' };
const unmountedStyle = {
    animation: 'outAnimation 170ms ease-out',
    animationFillMode: 'forwards',
};

const ContentScriptOverlay: React.FC<{}> = () => {
    const [isActive, setIsActive] = useState<boolean>(false);
    const showDiv = useDelayUnmount(isActive, 250);

    const handleMessages = (msg: Messages) => {
        if (msg === Messages.TOGGLE_OVERLAY) {
            setIsActive(!isActive);
        }
    };

    useEffect(() => {
        chrome.runtime.onMessage.addListener(handleMessages);
        return () => {
            chrome.runtime.onMessage.removeListener(handleMessages);
        };
    }, [isActive]);

    return (
        <>
            {showDiv && (
                <div
                    className="overlay top-0 right-0 bg-white backdrop-filter backdrop-blur-lg bg-opacity-70 h-screen overflow-auto shadow-md"
                    style={isActive ? mountedStyle : unmountedStyle}
                >
                    <App />
                </div>
            )}
        </>
    );
};

const root = document.createElement('div');
root.setAttribute('id', 'intro-extension');
document.body.appendChild(root);
ReactDOM.render(<ContentScriptOverlay />, root);

contentScript.css

@tailwind base;
@tailwind components;
@tailwind utilities;

#intro-extension ::-webkit-scrollbar {
    width: 0px;
    background: transparent;
}

.overlay {
    width: 376px;
    z-index: 9999;
    position: fixed;
    border-radius: '6px 0px 0px 6px';
}

@keyframes inAnimation {
    0% {
        right: -376px;
    }
    100% {
        right: 0;
    }
}

@keyframes outAnimation {
    0% {
        right: 0;
    }
    100% {
        right: -376px;
    }
}

I would honestly appreciate any help!



Solution 1:[1]

The PostCSS Parent Selector package will do this.

Make sure to create a postcss.config.js file in your project root and add the plugin like so.

module.exports = {
    plugins: {
        ...
        'postcss-parent-selector': { selector: '.parentclass' }
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tymo