简体   繁体   中英

Convert external CSS to Inline on button press with javascript

I am currently developing a page that needs to be displayed on the screen as well as be sent out as HTML email.

I have created all the style in a separate (external) CSS file like I usually do.

This page has multiple different templates, all sharing the same classes styled using CSS, which makes it quite a long and tedious job to go and manually inline all the CSS.

I was wonder if there's a way to automatically get the css and convert it to inline.

I have done some reseach and some code test as well.

This is how far I got:

  • I can get the css using a GET request
  • I have the HTML of the page cleaned (removed all the unwanted parts)

and now i'd like to automatically inline the properties when a class is found in the css and html.

I have made this attempt here https://codepen.io/NickHG/pen/wqyzGj?editors=1010

var classMatches, cls, css, cssRule, el, html, i, j, k, l, len, len1, len2, len3, len4, len5, listOfClasses, m, n, o, parsedCss, parsedHtml, parser, ref, res, v;

css = ".inside1{background:red;}.inside2{background:purple;}";

parser = new cssjs();

parsedCss = parser.parseCSS(css);

html = $('.outside').html();

parsedHtml = $.parseHTML(html);

listOfClasses = [];

for (k = i = 0, len = parsedHtml.length; i < len; k = ++i) {
  v = parsedHtml[k];
  listOfClasses.push(v.className);
}

classMatches = [];

for (k = j = 0, len1 = parsedCss.length; j < len1; k = ++j) {
  v = parsedCss[k];
  for (l = 0, len2 = listOfClasses.length; l < len2; l++) {
    cls = listOfClasses[l];
    if ("." + cls === v.selector) {
      console.log("matching class - ", v.selector);
      ref = v.rules;
      for (m = 0, len3 = ref.length; m < len3; m++) {
        cssRule = ref[m];
        res = cssRule.directive + ':' + cssRule.value + ';';
        classMatches.push({
          "class": cls,
          css: res
        });
      }
    }
  }
}

console.log(classMatches);

for (k = n = 0, len4 = parsedHtml.length; n < len4; k = ++n) {
  v = parsedHtml[k];
  debugger;
  for (o = 0, len5 = classMatches.length; o < len5; o++) {
    el = classMatches[o];
    if (v.className === el["class"]) {
      if (v.attributes['style'] != null) {
        v.attributes['style'].value = el.css;
      }
    }
  }
}

$('.outside').html(parsedHtml);

(the code above is a compiled version of CoffeeScript)

but it's not working correctly and it should also be recursive as I have some nested elements as well, so I would prefer to use a library that exists already (if exists) rather than having to write my own.

Any ideas/suggestions?

Thanks

At the end, if someone is interested, I changed the template a bit so that I used only one and show/hide the required/not required parts.

This made it slimmer and easier to edit. I then used ng-style (yes, i'm using angular) to apply the style inline.

basically i created all my style in a scope object and used it this way in the template:

$scope.style = {
   class1: {background:"red"},
   class2: {background:"yellow"}
}

<div ng-style="style.class1">...</div>
<div ng-style="style.class2">...</div>

I don't like this approach, but it works and at least let me keep all the style in one place if i have need to edit/change it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM