public

CriticalCSS Bookmarklet and Devtool Snippet.js

  • Download Gist
criticalcss-bookmarklet-devtool-snippet.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
(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);
})();

Just added merging of styles.

Fixing merge of styles.

Hey @PaulKinlan

Not sure if there is a reason why you have chosen to use d.body but I found that using the body as the start node missed body and html styles which could be very important on the critical css. Mind you my understanding of walkers is limited.

var walker = d.createTreeWalker(d, NodeFilter.SHOW_ELEMENT, function(node) { return NodeFilter.FILTER_ACCEPT; }, true);

instead of

var walker = d.createTreeWalker(d.body, NodeFilter.SHOW_ELEMENT, function(node) { return NodeFilter.FILTER_ACCEPT; }, true);

@GlynnPhillips funny, I had this on my list :) great spot. not sure about head elements but let's give it ago.

Fixed, head makes thinks look great. noticed a couple of other issues, working on them too.

Awesome, looking better now :)

@GlynnPhillips I just relaised that it doesn't pull in scripts that are external to your domain (i.e cross-origin), whilst a little inconvienient I think this makes sense.

I see cross-browser issues...

@PaulKinlan in what way? I can see script tags from external domains being 'walked' through. Is it just that it wouldn't pick up any styles which are set by these?

Looks great when I tested on some websites, but it failed miserably on facebook.com AND youtube.com, it just returned bunch of selectors with css of { display: none !important; orphans: 4321 !important; }

So what is the issue here??

What about this error message: "Uncaught SyntaxError: Unexpected end of input"?

I'm using Chrome :)

great work! just got pagespeed insights of 99 / 100 after moving the styles output to inline css! wow

@cforge79 - awesome!!

Are there any workarounds for the cross origin thing? I serve all my static content from a different domain to prevent users from sending cookies to it.

Patrick from feed the bot told me about this this is a fantastic set of code you have there. Thank you so much

@marcis you have to convert it to a bookmarklet (URLencoded, etc) code .. try http://chriszarate.github.io/bookmarkleter/

@PaulKinlan Is it possible to pick up styles with media queries?

Sorry, possibly unrelated. But I want to test this.
How to use it as bookmark? I even minified it to put in bookmark in chrome but it is not taking. Possibly size!

@satya61229 it should work fine minified... but don't forget you'll need to prefix it with "javascript:" ;-) (oh, and make sure you delete the comments... or the // will terminate your bookmarklet code early)

Hey @PaulKinlan

It should also return the pseudo-elements like ::after, ::before, hover, focus and active as well, check http://ali.shahab.pk/

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.