0

I have a React webpage with HTML components, some of which are styled with CSS, and others of which are styled with javascript (Glamor). What I'd like is HTML code with inline CSS that exactly replicates the look of the page to send in an email.

I know I can inline CSS with a package like Styliner, but I'm wondering if it's possible to somehow convert the js-defined Glamor styles into plain CSS and inline that as well?

If it isn't possible, then I will probably explore a different route (taking a PDF snapshot of the page). Appreciate the help!

Bob Risky
  • 805
  • 1
  • 9
  • 22
  • 1
    What about copying the contents of the "Elements" tab in the developer's console as this window shows the rendered results after CSS and JavaScript processing? – Scott Marcus Jan 12 '18 at 22:10

2 Answers2

1

You can iterate document.styleSheets and set each CSS rule at style attribute of the element. CSS pseudo elements and classes set at HTML style attribute of HTML element are currently not rendered within the document.

guest271314
  • 1
  • 15
  • 104
  • 177
  • How would that pick up dynamically generated styles? – Scott Marcus Jan 12 '18 at 22:36
  • @ScottMarcus Iterating `document.styleSheets` should get all CSS rules, see https://stackoverflow.com/questions/41055047/javascript-get-css-prop-value-with-unit/, https://stackoverflow.com/questions/42619084/modify-element-before-css-rules-programmatically-in-react/ – guest271314 Jan 12 '18 at 22:38
  • I don't think you are following my question. The CSSOM will get your the static rules that have been written, but I don't think it will get you styles that were set via JavaScript, especially when the JavaScript sets an inline style. – Scott Marcus Jan 12 '18 at 23:04
  • Ah I see, thanks! I am able to access the CSSOM via Chrome Inspector, but for some reason when I try to access it programatically (I'm using headless Chrome), document.styleSheets just returns like an array of empty styles... – Bob Risky Jan 12 '18 at 23:08
  • @ScottMarcus The question is how to set the CSS inline within HTML. If the styles are already set inline at HTML part of the inquiry is already solved. Concatenate styles, if any, at `document.styleSheets` to existing `style` attribute. – guest271314 Jan 12 '18 at 23:10
  • No, you still misunderstand. I'm talking about styles set statically (in HTML) vs. styles that are generated dynamically. The CSSOM isn't going to pick up those. – Scott Marcus Jan 12 '18 at 23:12
  • @BobRisky If `document.styleSheets.length` is `0` the styles should already be set at HTML. – guest271314 Jan 12 '18 at 23:13
  • @guest271314 - ah the length was actually non-zero, i think headless chrome is unable to return the js object correctly, but I think I'm able to convert the CSSOM object into a string and then just return that. Thanks! – Bob Risky Jan 12 '18 at 23:21
0

Looking at the documentation, glamor seems to create style sheets in the DOM of the page using the package. So after all calls to glamor have finished, traversing document style sheets should pick up the results. A linked example of looking through style sheets is not exactly what is needed. Here is a example (modified from old style code) of getting CSS definitions as text that works in a browser:

function cssStyleRules(sheets) {
    var sheet;
    var list;
    var rule;
    var text="";

    if(sheets) {
        for(var i = 0; sheet = sheets[i++]; ) {
            list = sheet.cssRules;
            for( var j = 0; j < list.length; ++j) {
                rule=list[ j];
                if(rule.type == 1)  { // styleRule
                    text += rule.cssText + '\n';
                }
            }
        }
    }
    return text;
}
var css = cssStyleRules( document.styleSheets);
// write css to a file in a headless browser

Obviously the code needs to be run in a headless browser on the server which writes the CSS text to a file before being processed by Styleliner.


Update:

You've commented on not being able to get style sheets back from the headless browser as expected. This could be the browser's fault, but checking Glamor.md's implementation.md turned up

insert into stylesheet

We use our own abstraction over the browser's stylesheet to insert the rule into the dom. This abstraction also works on node, letting us do stuff like SSR, etc. It also uses different modes of inserting styles based on the environment, as detailed here

... but the link is a stub. I would suggest looking into implementaion details further and particularly what they mean by "this abstraction also works on node".

traktor
  • 17,588
  • 4
  • 32
  • 53