4

I have a React app that's loaded into a parent document via some shim JavaScript that:

  • creates an <iframe> element
  • creates a <div>
  • injects a <style> tag into the <head> in order to style the inserted <div>

Roughly, this works using the below:

// example.jsx

// Require the css using css-loader
const styles = require('../styles/example.css');

// Find the parent document
const doc = window.parent.document;

// Inject our stylesheet for the widget into the parent document's
// HEAD as a style tag
const css = styles.toString();
const style = doc.createElement('style');
style.type = 'text/css';
if (style.styleSheet) {
  // This is required for IE8 and below.
  style.styleSheet.cssText = css;
} else {
  style.appendChild(document.createTextNode(css));
}
doc.head.appendChild(style);

This uses css-loader in our Webpack config in order to have the require().toString() work for setting the cssText dynamically.

While this works, I don't know if this ideal. And we'd prefer to write Sass and get the benefits of @import to bring in other CSS (like resets), and get the benefits other tooling for Sass.

Is there a better way that we can achieve the same result of injecting <style> text into this parent document without sacrificing our ability to use the tooling we prefer?

Josh Smith
  • 14,674
  • 18
  • 72
  • 118
  • Have you taken a look at react-helmet? It helps in management of the and is fairly lightweight. – Nathan Christian Jul 06 '18 at 17:59
  • @NathanChristian do you know if it would be able to manage the `` of the parent document for the `iframe` that actually loads the app (and not the `iframe` itself)? – Josh Smith Jul 06 '18 at 18:06
  • It uses `document.head` or, if it can't find one, an element with a selector of `head`. – Nathan Christian Jul 06 '18 at 18:42
  • Do you need to specifically insert the css as a style tag, or would simply importing it globally do the trick? Because if that is the case, then you can manage your specificity within the module and then have that scss file imported by the parent or the module itself. – Nathan Christian Jul 09 '18 at 14:17
  • @NathanChristian our app basically loads in a customer's page: `
    ` where `iframe`'s `src` is our React app and `#react-root` is where the app renders. We need to be able to have the styles apply to the parent document, not the `iframe`. The way it's accomplished doesn't matter so much, but I don't personally know how to accomplish this outside of manual injection of the CSS text.
    – Josh Smith Jul 09 '18 at 19:22

1 Answers1

1

Install react-helmet and then try this in your react component:

<Helmet>
    <style>
        // Insert CSS string here
    </style>
</Helmet>

The other option is to load the sass directly in the parent but gate all of its styling behind a sass function that checks if #react-root exists.