Comments (11)
@remysabliet I have used two options successfully.
import as string with css-to-string-loader
.my-style {
background-color: red;
}
test: /\.css$/,
use: [
{loader: 'css-to-string-loader'},
{loader: 'css-loader'},
],
import stylesheet from './styles.css';
const SomewhereInsideReactShadow = () => (
<div>
<style dangerouslySetInnerHTML={{__html: stylesheet}}/>
<div class="my-style">
</div>
);
Dynamic import with style-loader
This one is more complex. The normal way to import CSS is to use style-loader, which drops your <style>
tag into document.head
. Obviously that doesn't work for shadow DOM things since the <style>
needs to be inside the shadow DOM.
Fortunately, style-loader has an insertInto
option that lets you specify where you want your styles imported.
use: [
{
loader: 'style-loader',
options: {
insertInto: () => {
return document.querySelector('#my-shadow-dom-anchor').shadowRoot;
},
},
},
{loader: 'css-loader'},
],
Yay! You don't need to make your own <style>
element anymore. The downside here is that the element with ID my-shadow-dom-anchor
needs to exist BEFORE the
import './styles.css';
statement is reached, and it needs to already have a shadow root attached. I wasn't able to get it working with ReactShadow, but you can do it if you make the shadow DOM yourself.
// MyComponentInsideAShadowDOM.jsx
import './styles.css';
const MyComponentInsideAShadowDOM= () => (
<div class="my-style"/>
);
// App.jsx
import ReactDOM from 'react-dom';
import retargetEvents from 'react-shadow-dom-retarget-events';
// Create your anchor div. Must have same ID that style-loader will be looking for.
const anchor = document.createElement('div');
anchor.id = 'my-shadow-dom-anchor';
// Give it a shadow DOM tree
const shadowRoot = anchor.attachShadow({mode: 'open'});
retargetEvents(shadowRoot);
// Add it to the <body>
document.body.appendChild(anchor);
// Now you can import your component and render it inside the shadow DOM anchor
const Component = (await import(
/* webpackMode: "eager" */
'./MyComponentInsideAShadowDOM.jsx'
)).default;
ReactDOM.render(<Component/>, anchor);
You may need babel-plugin-syntax-dynamic-import.
from reactshadow.
There is no build for the CSS in the example.
It uses the include
attr on <ReactShadow />
but of course you could use Webpack to import
the CSS, or use a CSS-in-JS solution such as styled-components
without any problems.
from reactshadow.
Thank you for your quick answer.
Well, in my understanding of shadow dom, we can apply like a full css file to a shadow DOM node ( maybe I am wrong?). If I start declaring all in-line, with a huge amount of css code it would be pretty ugly (too many css properties).
Considering the first assumption to be true, now if for example I wanna apply a whole css file to a component and its child (the whole component embedded by <shadowDOM include.. >
, when building the application with Webpack, using a standard css loader, he won't include the css file in the built version and so it won't work as your include={} attribute is not an import.
So i was wondering how did you built your example ?
In webpack I am having below conf for css :
{ test: /\.css$/, use: [ 'style-loader', 'css-loader' ] }
would you have an idea? ( i am pretty new to web-dev so this question will probably looks simple for you)
from reactshadow.
I don't have an example off-hand as I don't use it in the example, but yes your assumption is correct and so your component could well be something like the following with the correct Webpack setup:
import styles from './styles.css';
With the JSX as:
<section>
<div>
<style type="text/css">{styles}</style>
etc...
</div>
</section>
from reactshadow.
I see, so I will try to make my webpack works better than, thanks ;)
from reactshadow.
I forget which one it is exactly, but if you use either css-loader
or style-loader
on their own, you'll get the desired import
behaviour, otherwise one of them automatically injects the CSS into the html.
from reactshadow.
Let’s say I have a simple react project with 2 files:
src/index.js
import "./stylesheets/slide3.css";
...
<ShadowDOM include="./stylesheets/slide3.css">
<div id="div1">
<p> First Div </p>
<div id="div2">
<p> second Div </p>
</div>
</div>
</ShadowDOM>);
src/stylesheets/slide3.css
#div1 p{
color: blue;
}
#div2 p{
color: red;
}
How would you manage that file import to works in both local (react-scripts start ) and also compatible after having build the application (react-scripts build ) and launch the server in local (serve –s build)?
Why that question is that, by looking at your code, it considers the file passed in include property as an URL. So if i refers to a local file in my workspace ( include=”./stylesheets/slide3.css”) it wont work and i will get the error in console:
GET http://localhost:3000/stylesheets/slide3.css 404 (Not Found)
Obviously this URL doesn’t exist and even if I would try the full URL (including absolute path on my laptop) it would give something like this, and it doesn’t work either):
GET http://localhost:3000/Users/remysabliet/proj/react-proj/remysabliet/src/stylesheets/slide3.css 404 (Not Found)react-shadow.js:844
Moreover, If we deploy using react build, the website structure is different and give something like below:
https://ibb.co/eCgM5U
Subsequently, i would set <shadowDOM include=”static/css/stylesheets/slide3.css”> ...
but it is not working either, can't retrieve the css file.
I am looking for a simple solution to make it works contextly (like import './stylesheets/slide3.css’
How would you advice me to do so?
I have also tried your second solution using
import slide3 from './stylesheets/slide3.css'
and declaring <slide..>{slide3}</style>
Example on sandbox: https://codesandbox.io/s/k0qky1loy5
and I am getting below error :
_invariant Violation
Objects are not valid as a React child (found: object with keys {}). If you meant to render a collection of children, use an array instead.This is some text!
Thanks in advance for your support
from reactshadow.
I already passed 2 days on this before posting. I wonder how people succeeded to make it work that simple, except by doing all in-line code.
from reactshadow.
Hello bcanseco,
Thank you for your help, really appreciate it.
I succeeded to make your Solution 1 works 👍
I have make some research about this dangerouslySetInnerHTML property , as far as I have understood, it allows XSS attack.. but as far as we include only CSS styles, is there a security issue?
As a countermeasure, there is the DOMPurify plugin which allows to sanitarize injected HTML, but I guess we don't need it as far as we only include CSS, am I wrong ?
Regarding method 2 I understand that you are not using ReactShadow anymore but regular JS, I would go this way only if can't make sure that the dangerouslySetInnerHTML is not that dangerous in our case (Injecting CSS Style).
If you have some feedback on it, looking forward to hear it :)
from reactshadow.
@pactera-admindev-remy Afaik you're correct. As long as you only use dangerouslySetInnerHTML
for styles and no user-submitted input, you should be good. Still not an ideal solution but it works.
from reactshadow.
Documented applying CSS styles in the new version.
from reactshadow.
Related Issues (20)
- Can useLayoutEffect() be used instead of useEffect() to make rendering synchronous? HOT 3
- How to use ReactShadow with ChakraUI Drawers? HOT 1
- Is there any chance to have a working example with CRA and TS? HOT 1
- Lib stopped working on iOS 15? HOT 1
- Shadow tree inheriting from parent HOT 2
- Does it support new mui lib?
- [feature request] allow consumers to pass options to emotion
- global requires a polyfill. Shall we replace global with globalThis? HOT 2
- styled-components is not defined as a peer dependency HOT 1
- Update dependency to React 18? HOT 5
- Trouble Loading Custom Font Into Shadow DOM in my Chrome Extension
- template content is empty with react HOT 1
- Example links in readme are both broken
- Children of the shadow root cannot get retrieved at parent level within a useEffect
- Failed to execute 'attachShadow' on 'Element': Shadow root cannot be created on a host which already hosts a shadow tree HOT 1
- Remove react-use dependency due to package size
- shadowroot has been depricated need to update with shadowrootmode in template element HOT 2
- Next.js v13 failed to build "TypeError: e.createContext is not a function" HOT 1
- Css Variables from External URL link inside of a shadow dom not getting recognized
- Warning: z: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from reactshadow.