Skip to content

Instantly share code, notes, and snippets.

@PaulKinlan
Last active March 29, 2026 12:20
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);
})();
@lewisje
Copy link
Copy Markdown

lewisje commented Aug 6, 2020

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
Copy link
Copy Markdown

lewisje commented Sep 23, 2021

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.

@lewisje
Copy link
Copy Markdown

lewisje commented Jan 25, 2024

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