pnpm create plasmo inject-ui cd inject-ui touch content.tsx
const Overlay = () => (<h1>HELLO WORLD</h1>) export default Overlay
Load the extension in Chrome, refresh and you should see
HELLO WORLD injected into the top of the webpage.
Browser extensions can inject DOM elements into a website using a content script. However, the injected element might inherit the website's style without proper encapsulation. This is often undesirable for any site-agnostic browser extension.
There are 3 solutions to the problem above:
A. Render the element with a style tag that does css unset.
A is often seen employed by ad. It works well for self-contained, simple components that render images. However, it is very hard to leverage a design system that has inherited styling, since the unset cascades down. Unless you have a dedicated style injection scheme, it is very difficult to use and the extra style tag makes the code not very clean.
B. Render the element inside an iframe.
B isolates the element well and is the go-to technique of many old browser extensions. However, the iframe container can be hard to work with when trying to blend the injected component seamlessly into the website. Iframe's elements are nested inside an inner document within its frame, with its own head and body. This makes it tricky to style and control elements inside the iframe, as well as align them with the elements of the website.
C. Render the element inside a Shadow DOM.
C is the best technique for web extension. Introduced as the key part of the web component API, the idea is that the shadow DOM is a separate DOM attached to the underlying main DOM. Nothing inside it can affect the main world. The Plasmo framework uses this technique behind the scene to enable seamless injection of React component into any webpage. We call this feature "content script UI."