(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); | |
})(); |
This comment has been minimized.
This comment has been minimized.
Fixing merge of styles. |
This comment has been minimized.
This comment has been minimized.
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); |
This comment has been minimized.
This comment has been minimized.
@GlynnPhillips funny, I had this on my list :) great spot. not sure about head elements but let's give it ago. |
This comment has been minimized.
This comment has been minimized.
Fixed, head makes thinks look great. noticed a couple of other issues, working on them too. |
This comment has been minimized.
This comment has been minimized.
Awesome, looking better now :) |
This comment has been minimized.
This comment has been minimized.
@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. |
This comment has been minimized.
This comment has been minimized.
I see cross-browser issues... |
This comment has been minimized.
This comment has been minimized.
@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? |
This comment has been minimized.
This comment has been minimized.
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?? |
This comment has been minimized.
This comment has been minimized.
What about this error message: "Uncaught SyntaxError: Unexpected end of input"? I'm using Chrome :) |
This comment has been minimized.
This comment has been minimized.
great work! just got pagespeed insights of 99 / 100 after moving the styles output to inline css! wow |
This comment has been minimized.
This comment has been minimized.
@cforge79 - awesome!! |
This comment has been minimized.
This comment has been minimized.
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. |
This comment has been minimized.
This comment has been minimized.
Patrick from feed the bot told me about this this is a fantastic set of code you have there. Thank you so much |
This comment has been minimized.
This comment has been minimized.
@marcis you have to convert it to a bookmarklet (URLencoded, etc) code .. try http://chriszarate.github.io/bookmarkleter/ |
This comment has been minimized.
This comment has been minimized.
@PaulKinlan Is it possible to pick up styles with media queries? |
This comment has been minimized.
This comment has been minimized.
Sorry, possibly unrelated. But I want to test this. |
This comment has been minimized.
This comment has been minimized.
@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) |
This comment has been minimized.
This comment has been minimized.
Hey @PaulKinlan It should also return the pseudo-elements like ::after, ::before, hover, focus and active as well, check http://ali.shahab.pk/ |
This comment has been minimized.
This comment has been minimized.
A little bit of a resurrection, but I couldn't find anything on this problem: Do you have any solution for the same-origin problem? It seems that if you deliver your static resources via a CDN, this code will not work, because of the above problem.. I guess we can always temporarily move that CSS to be inline or so for testing, but I was hoping for something without many manual steps. :) Awesome little tool by the way! |
This comment has been minimized.
This comment has been minimized.
I built my own CriticalCSS Generator to solve these issues, something I can use for production. You can check it out here if you're interested: https://github.com/pocketjoso/penthouse Thanks for the inspiration! |
This comment has been minimized.
This comment has been minimized.
Is there any solution available for CDN served css files ? |
This comment has been minimized.
This comment has been minimized.
I put this script inside a CLI tool (Node) running on top of PhantomJS. https://github.com/cleberdantas/atf It's good for some automations. Thanks for de original idea @PaulKinlan |
This comment has been minimized.
This comment has been minimized.
Doesn't work for me in Chrome. I made it into a Bookmarklet using http://chriszarate.github.io/bookmarkleter/ Edit: Ok this gives it away console.log(css); - i can see it now :) |
This comment has been minimized.
This comment has been minimized.
Doesn't grab ALL the critical CSS for us... leaves out our header menu, so we get a flash of unstyled content, mainly the header menu |
This comment has been minimized.
This comment has been minimized.
Just found this gem, works really well :) When executing, I get this warning however:
@amityweb I suspect it has it has something to do with the positioning of the elements, as it works fine for me on my current project (with a fixed header nav) |
This comment has been minimized.
This comment has been minimized.
Not working for me :( http://neu.contur-online.de/de/index.php . After fill in only the 'critical path css', your tool gives me, the page is showing up wrong |
This comment has been minimized.
This comment has been minimized.
It seems the getMatchCSSRules function is expecting 2 arguments. Calling it with an empty string kills the deprecated message and still works as expected.
|
This comment has been minimized.
This comment has been minimized.
It doesn't work for media query and responsive websites. I tried with Bootstrap (http://getbootstrap.com/examples/theme/). Is there any way to make it work with Bootstrap? |
This comment has been minimized.
This comment has been minimized.
@vuquangchien, this might be of use (I based it off Paul's code when we also hit the media queries issue) https://gist.github.com/james-Ballyhoo/04761ed2a5778c505527 |
This comment has been minimized.
This comment has been minimized.
@james-Ballyhoo I tested it, It didn't work well on default brower on Android. It works well on chrome |
This comment has been minimized.
This comment has been minimized.
non-techie reporting: this doesn't work with chromium-browser in Ubuntu 16.10 -- but running under google's chrome download worked. thanks for the work you've done. |
This comment has been minimized.
This comment has been minimized.
The function getMatchedCSSRules does not work anymore. Long time it was deprecated and now it is removed. Does someone knows a replacement? |
This comment has been minimized.
This comment has been minimized.
Hello, Someone wrote a plugin as per your code: but that plugin is out to update, would like to update it? As per suggestion from google page speed insight, we need generate critical css, some plugins (https://wordpress.org/plugins/above-the-fold-optimization/) only handle optimize, but not handle generate those css. Anyone would like to update those wordpress' plugin? Alex |
This comment has been minimized.
This comment has been minimized.
Hi! Thanks a lot for this snippet!
We have created an improved snippet based on this concept that includes a polyfill for getMatchedCSSRules to support more browsers, including Firefox. |
This comment has been minimized.
This comment has been minimized.
Hi! i modidyed the snippet for the latest Chrome, and testet it a lot of Times! |
This comment has been minimized.
This comment has been minimized.
hi DirkPersky , I wasn't able to get your https://github.com/DirkPersky/criticalcss bookmarklet working in Chrome 72 Mac... should it be working? I tried it on several URLs, nothing happens (e.g. https://www.nytimes.com/ ). Thanks for your work on this. |
This comment has been minimized.
This comment has been minimized.
@CameronKnowlton I just tried https://github.com/DirkPersky/criticalcss on the NY Times site and it worked for me in Chrome Canary Version 75.0.3740.0 macOS 10.13.6. The generated critical CSS is displayed in the console in DevTools. |
This comment has been minimized.
This comment has been minimized.
Just tried DirkPersky's bookmarklet. It works. Thanks! |
This comment has been minimized.
This comment has been minimized.
Hello, Paul Kilan's code pops an error and DirkPerky's code does nothing. Anyone knows a working script to run on Chrome console to extract the critical css? |
This comment has been minimized.
This comment has been minimized.
Same issue here. Nothing happens. |
This comment has been minimized.
This comment has been minimized.
On Windows 10 with Crome 83.0.... the Bookmarklet works. |
This comment has been minimized.
This comment has been minimized.
Hi, I was sent here via the Autoptimize plugin FAQ. I have no clue how to use this to generate critical/above the fold CSS for the inline and defer css field of AO. Using another critical css generator I am getting the flash of unoptimized code (something like that). Could somebody please point me in the right direction of how to use this tool to extract (*the FAQ link points to this page) |
This comment has been minimized.
This comment has been minimized.
@gatehealing you create a new bookmark, and copy all javascript code from my https://github.com/DirkPersky/criticalcss/blob/master/bookmark.js into that field like the screenshot =) using it: |
This comment has been minimized.
This comment has been minimized.
Thanks DirkPersky! Please forgive my ignorance . . . what page am I bookmarking? This one (the one I am commenting on?) |
This comment has been minimized.
This comment has been minimized.
@gatehealing Non of both! Only create a new bookmark, but instead of adding a url to it, copy the content of my javascript and paste it to the url =) |
This comment has been minimized.
This comment has been minimized.
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.... |
This comment has been minimized.
This comment has been minimized.
FWIW I also made a version of the bookmarklet, and I even accounted for some cases where the |
This comment has been minimized.
Just added merging of styles.