Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save PaulKinlan/6284142 to your computer and use it in GitHub Desktop.

Select an option

Save PaulKinlan/6284142 to your computer and use it in GitHub Desktop.
CriticalCSS Bookmarklet and Devtool Snippet.js
(function() {
var CSSCriticalPath = function(w, d, opts) {
var opt = opts || {};
var css = {};
var pushCSS = function(r) {
if(!!css[r.selectorText] === false) css[r.selectorText] = {};
var styles = r.style.cssText.split(/;(?![A-Za-z0-9])/);
for(var i = 0; i < styles.length; i++) {
if(!!styles[i] === false) continue;
var pair = styles[i].split(": ");
pair[0] = pair[0].trim();
pair[1] = pair[1].trim();
css[r.selectorText][pair[0]] = pair[1];
}
};
var parseTree = function() {
// Get a list of all the elements in the view.
var height = w.innerHeight;
var walker = d.createTreeWalker(d, NodeFilter.SHOW_ELEMENT, function(node) { return NodeFilter.FILTER_ACCEPT; }, true);
while(walker.nextNode()) {
var node = walker.currentNode;
var rect = node.getBoundingClientRect();
if(rect.top < height || opt.scanFullPage) {
var rules = w.getMatchedCSSRules(node);
if(!!rules) {
for(var r = 0; r < rules.length; r++) {
pushCSS(rules[r]);
}
}
}
}
};
this.generateCSS = function() {
var finalCSS = "";
for(var k in css) {
finalCSS += k + " { ";
for(var j in css[k]) {
finalCSS += j + ": " + css[k][j] + "; ";
}
finalCSS += "}\n";
}
return finalCSS;
};
parseTree();
};
var cp = new CSSCriticalPath(window, document);
var css = cp.generateCSS();
console.log(css);
})();
@gatehealing

Copy link
Copy Markdown

got it! Now what I see is not wrapped in <style></style> tags, and I believe I am supposed to put what is wrapped in those style tags in the AO inline and defer css box. I don't want to crash my site (which I have managed to do before on things like this), so I want to be sure I have extracted the correct code to put in that AO field....

@lewisje

lewisje commented Aug 6, 2020

Copy link
Copy Markdown

FWIW I also made a version of the bookmarklet, and I even accounted for some cases where the cssRules or rules property threw an error on access.

@gillespieza

Copy link
Copy Markdown

I get Uncaught TypeError: w.getMatchedCSSRules is not a function , using Chrome

@lewisje

lewisje commented Sep 23, 2021

Copy link
Copy Markdown

I get Uncaught TypeError: w.getMatchedCSSRules is not a function , using Chrome

My re-fashioning used a polyfill for that; getMatchedCSSRules was never standardized, and it was removed from Chrome starting with version 63.

@reedjones

Copy link
Copy Markdown

I was able to get it working by replacing getMatchedCSSRules with the script below. However doesn't work if css is from a different domain.

 var getCSS = function(el) {
    var sheets = document.styleSheets, ret = [];
    el.matches = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector 
        || el.msMatchesSelector || el.oMatchesSelector;
    for (var i in sheets) {
        var rules; 
      try {
        rules = sheets[i].rules; 
      } catch {
        console.log("Error reading rules: "); 
        try{
          rules = sheets[i].cssRules;
         
        } catch {
           console.log("Error reading cssRules: "); 
          
        }
         
      }
     
     ```

@reedjones

Copy link
Copy Markdown

@lewisje

lewisje commented Jan 25, 2024

Copy link
Copy Markdown

Your example script was not complete, but I imagine the rest of the way you'd do it is to test the element against each rule to see whether it matches.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment