kofifus
kofifus

Reputation: 19275

Break CSS into rules

I have the content of a CSS file as a string I got with an AJAX request.

I need to break it into rules that I can feed into styleSheet.insertRule

What is the best way to achieve this correctly and efficiently ? I do not want to include/write a full CSS parser just for that if possible ...

I considered simply splitting on '}' but this will not work if there are @media clauses which created nested curly brackets, and I am not sure it is correct otherwise ...

Thanks!

Upvotes: 0

Views: 135

Answers (2)

Brett DeWoody
Brett DeWoody

Reputation: 62743

The solution from Nisarg Shah probably does the job, but here's an alternative. It uses the css.js library to parse the CSS string into a JS array, which can then be inserted using stylesheet.insertRule().

The two advantages this method has:

  1. It breaks the CSS into rules as stated in the question
  2. It would allow styles to be filtered or altered before insertion

Also, this is a simplified solution that will not work with more complicated CSS containing media queries or similar rules. For a more robust solution, the function would need to handle those types of style rules, and more info on how to do that can be found in the MDN docs.

Here's the approach:

  1. Get the CSS from your API
  2. Parse the CSS into a JS array of objects
  3. Loop through the CSS rules and create the CSS style string
  4. Add the style string to the stylesheet with insertRule()

var cssString = `
div {
  color: green;
  font-size: 24px;
}`;

setTimeout(function() {
  var parsedStyles = addStylesAndReturnParsedStyles(cssString);
  console.log(parsedStyles)
}, 1000);

var addStylesAndReturnParsedStyles = function(cssString) {
  var parser = new cssjs();
  var parsed = parser.parseCSS(cssString);
  var styleEl = document.createElement('style'),
      styleSheet;

  // Append style element to head
  document.head.appendChild(styleEl);

  // Grab style sheet
  styleSheet = styleEl.sheet;

  parsed.forEach(style => {
    var selector = style.selector;
    var rules = style.rules;
    var propStr = '';

    for (var i = 0; i < rules.length; i++) {
      var prop = rules[i];
      propStr += prop.directive + ':' + prop.value + ';\n';
    }

    // Insert CSS Rules
    styleSheet.insertRule(selector + '{' + propStr + '}', styleSheet.cssRules.length); 
  });
  
  return parsed;
};
<script src="https://cdn.rawgit.com/jotform/css.js/master/css.min.js"></script>
<div>Here's some content</div>

Upvotes: 1

Nisarg Shah
Nisarg Shah

Reputation: 14531

You can simply create a new <style> element using the stylesheet text you have and insert it into the <head> element.

var style = `
div {
  color: blue;
}`;

setTimeout(function() {
  var elem = document.createElement("style");
  elem.innerHTML = style;
  document.head.appendChild(elem);
}, 1000);
<div>
  Some text
</div>

Upvotes: 1

Related Questions