Styling React components and ShadowDOM usage

Morning y'all, long time no see. Quite a while ago I removed the ShadowDOM implementation and injected the content script directly onto the root tree. I don't remember exactly why, I think it was an issue with font loading that I only got around when not using the shadow DOM. Anyways, that decision has ended up biting my ass back, and now I'm dealing with a lot of inconsistencies in the styling between sites due to the site styles bleeding into the extension. I've removed the getRootContainer export from my content script, and it's now in the Shadow DOM again... But it has absolutely no styling. Not from the site, not from the extension, nothing. It's just the HTML from the components. I believe this has something to do with how I'm importing the styles onto the React components used in the content script, but I'm not entirely sure why being in or out of the Shadow DOM affects this, so I want to double check. For react based content scripts, how do you style the components? I understand that there's the getStyle export, but that doesn't really work for more complex components that import other components with their own styles
61 Replies
Karstodes
Karstodes•2y ago
For reference, this is the previous getRootContainer method that I've removed
export const getRootContainer = async (): Promise<HTMLDivElement> => {
const body = document.querySelector("body")
const container = document.createElement("div")
container.style.cssText = `
z-index: 9999;
position: absolute;
`
body.appendChild(await getStyle())
body.appendChild(container)

return container
}
export const getRootContainer = async (): Promise<HTMLDivElement> => {
const body = document.querySelector("body")
const container = document.createElement("div")
container.style.cssText = `
z-index: 9999;
position: absolute;
`
body.appendChild(await getStyle())
body.appendChild(container)

return container
}
Also I'm importing the CSS (well, SASS) inside each component by just importing the file like in a regular React project. As an example:
import React from "react"

import "./this-component-style.scss"

const ExampleComponent = () => {
return (
<span className="example-class">This is a test!</span>
)
}
import React from "react"

import "./this-component-style.scss"

const ExampleComponent = () => {
return (
<span className="example-class">This is a test!</span>
)
}
.example-class {
color: red;
}
.example-class {
color: red;
}
lab
lab•2y ago
Fascinating. CSUI style are injected into the shadow DOM at point of entry. The way you have it works on extension pages but won't work on csui bc it's like SSR - you can't hydrate child style unless consolidated
Karstodes
Karstodes•2y ago
Alright, so using a Shadow DOM for isolation is not an option in this use case? I can't really change the way components are styled, not all of them at least. Some come from imported libraries, so I'd assume those wouldn't work What are some possible alternatives, either for style loading or for styling isolation?
lab
lab•2y ago
you will need to consolidate the style fragment somehow to inject them in the right place. One way to do so, is hack the plasmo's resolver and js transformer, see if it's possible to isolate those style and inject them into the designated style tag. basically, we need to study how the default css transformer is injecting styles, mark all styles being injected into csui as they are inside csui, and instead of being injected as top-level page style tag, get injected into plasmo's CSUI
Karstodes
Karstodes•2y ago
Interesting, I might take a look at it. Otherwise I hope there are libraries for CSS isolation that I can use if I'm forced to mount the script into the root body tag
lab
lab•2y ago
the easiest is to use css-in-js that's what I use for my extension project that also share component with webapp and native apps
Karstodes
Karstodes•2y ago
Yeah, but that gives me control only for the components I'm making if I'm using a component defined by a library and said component doesn't use css-in-js, I'm out of luck I assume
lab
lab•2y ago
yup but it will also force you to find css-in-js component lib xD
Karstodes
Karstodes•2y ago
@louis I've been digging about the topic and it seems that there are ways to make it work using the webpack style loader plugin, do you know if the webpack configuration is accessible in any convenient way to toy with it?
Karstodes
Karstodes•2y ago
Ugh, nevermind, we're using Parcel and not webpack Wait a second, wait a sec, hold the horses
Karstodes
Karstodes•2y ago
Bundle inlining
Parcel includes several ways to inline the compiled contents of one bundle inside another bundle.
Karstodes
Karstodes•2y ago
I assumed this kind of approach wouldn't work because I'd have to do it manually for each react component, so the components imported from libraries wouldn't work, but the docs say this:
Parcel will compile the resolved file as normal, including bundling all dependencies, and then inline the result as a string into the parent bundle.
I assume this means the SCSS dependencies (@import, @use...), but could there be a way to make it also fetch the CSS modules from dependant components?
lab
lab•2y ago
This is what the getStyle feature is yeah So one thing you can try to find is a postcss plugin That alter the style injection location behavior for parcel. And you can add a postcss.json to configure that feature
Karstodes
Karstodes•2y ago
There's postcss-import, but it doesn't seem to help in my particular scenario it resolves imports inside the CSS files, but the files themselves are independent from each other, they're linked by the component dependencies inside react
Want results from more Discord servers?
Add your server