Based off of https://gist.github.com/PaulKinlan/6284142 , but with support for media queries and dumps css to a textarea in a panel stuck to the top of the page. Only tested in Chrome, uses height of window to determine "critical path".
(function(){ | |
if(document.querySelector("#_CRIT_CSS")){return;} | |
var container = document.createElement("div"); | |
container.id = "_CRIT_CSS"; | |
container.innerHTML = '<textarea cols=80 rows=20></textarea><button id="CRIT_FIND">Find Critical CSS</button><button id="CRIT_CLOSE">Exit</button>'; | |
container.style.position = "fixed"; | |
container.style.top = 0; | |
container.style.left = 0; | |
container.style.right = 0; | |
container.style.backgroundColor = "#FFF"; | |
container.style.zIndex = 99999999999999; | |
document.body.appendChild(container); | |
container.querySelector("#CRIT_FIND").addEventListener("click",function(){ | |
container.querySelector("textarea").value = findCriticalCSS(window,document); | |
}); | |
container.querySelector("#CRIT_CLOSE").addEventListener("click",function(){ | |
container.remove(); | |
container = null; | |
}); | |
function findCriticalCSS(w, d){ | |
//Setup our Pseudo selector killer, view height and critical nodes | |
var removePseudo = /([^\s,\:\(])\:\:?(?!not)[a-zA-Z\-]{1,}(?:\(.*?\))?/g; | |
var height = w.innerHeight; | |
var criticalNodes = []; | |
//Go find all the critical nodes | |
var walker = d.createTreeWalker(d, NodeFilter.SHOW_ELEMENT, function(node) { if(node === container){console.error("FOUND IT", node)};return node === container ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT; }, true); | |
while(walker.nextNode()) { | |
var node = walker.currentNode; | |
var rect = node.getBoundingClientRect(); | |
if(rect.top < height) { | |
criticalNodes.push(node); | |
} | |
} | |
console.log("Found " + criticalNodes.length + " critical nodes"); | |
//Grab loaded stylesheets | |
var sheets = document.styleSheets; | |
var outCss = Array.prototype.map.call(sheets,function(sheet){ | |
var rules = sheet.rules || sheet.cssRules; | |
//If there are rules | |
if(rules){ | |
return { | |
sheet: sheet, | |
rules: Array.prototype.map.call(rules, function(rule){ //Convert each CSSRule into a | |
try{ | |
if(rule instanceof CSSMediaRule){ | |
var subRules = rule.rules || rule.cssRules; | |
var css = Array.prototype.filter.call(subRules, function(rule){ | |
return criticalNodes.filter(function(e){ return e.matches(rule.selectorText.replace(removePseudo,"$1"))}).length > 0; | |
}).map(function(rule){return rule.cssText}).reduce(function(ruleCss,init){return init + "\n" + ruleCss;},""); | |
return css ? ("@media " + rule.media.mediaText + " { " + css + "}") : null; | |
}else if(rule instanceof CSSStyleRule){ | |
return criticalNodes.filter(function(e){ return e.matches(rule.selectorText.replace(removePseudo,"$1"))}).length > 0 ? rule.cssText : null; | |
}else{ | |
console.warn("allowing", rule); | |
return rule.cssText; | |
} | |
}catch(e){ | |
console.error("Bad CSS rule", rule.selectorText); | |
throw e; | |
} | |
}).filter(function(e){return e;}) | |
} | |
}else{ | |
return null; | |
} | |
}).filter(function(cssEntry){return cssEntry && cssEntry.rules.length > 0}) | |
//Enable only this for debug dump | |
//.map(function(e){return {href: e.sheet.href, oldsize: e.sheet.cssRules.length, rules: e.rules, css: e.rules.join("\n")} }) | |
//Enable this for CSS | |
.map(function(cssEntry){ return cssEntry.rules.join(""); }) | |
.reduce(function(css,out){return out + css},"") | |
return outCss.replace(/\n/g,"").replace(/content\: \"(.)\"/g,function(a,e){ | |
return "content: \"\\" + escape(e).substr(2) + "\""; | |
}); | |
} | |
})() |
This comment has been minimized.
This comment has been minimized.
I have the same issue. When I hit the button, noting happens. |
This comment has been minimized.
This comment has been minimized.
Nothing happening here either... |
This comment has been minimized.
This comment has been minimized.
This is what i found in the console after try
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
Hi :)
on chrome (51.0.2704.106 (64-bit)) I keep getting the error in the line 31
It create the textarea, but when I click the button "Find Critical CSS" nothing appears.
In the console doesn't appear anything and outCss appears to be empty.