Created
October 26, 2019 22:16
-
-
Save tomhodgins/8decbb628b620f2a33bdb8fadf77aa44 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Run this on a loaded web page in the browser to log a CSS stylesheet to the console that contains all of the CSS rules that presently apply to the elements visible on the screen. This can be used for 'Critical CSS' generation | |
// You can use an import statement like this if it's in a <script type=module> | |
//import {process} from 'https://unpkg.com/cssomtools' | |
// Or a dynamic import() for copy/pasting into the JS console | |
import('https://unpkg.com/cssomtools').then(({process, all}) => { | |
// Log the final output to the console | |
console.log( | |
// Find all tags in document… | |
[...document.querySelectorAll('*')] | |
// …that are above the fold | |
.filter(el => el.offsetTop <= window.innerHeight) | |
// For each tag | |
.reduce( | |
// Stylesheet will be our accumulated CSS as a string | |
// Tag is the current DOM element we're processing | |
(stylesheet, tag) => { | |
// Process CSS rules | |
process( | |
// Find all CSS rules in CSSOM… | |
all(), | |
// …and process them with this function | |
rule => { | |
// Function for processing a style rule | |
function processRule(rule, existing) { | |
// If the rule is a regular style rule | |
// and the tag we're processing matches the selector of this rule | |
// and our output does not already contain this particular rule | |
if ( | |
rule.selectorText | |
&& tag.matches(rule.selectorText) | |
&& existing.includes(rule.cssText) === false | |
) { | |
// return the CSS text of this rule as a string | |
return rule.cssText | |
} else { | |
// In all other cases return nothing | |
return '' | |
} | |
} | |
// For style rules | |
if (rule.selectorText) { | |
// Add the processed text | |
stylesheet += processRule(rule, stylesheet) | |
// Otherwise, if the rule is a media rule | |
} else if (rule.media) { | |
// We'll keep track of the matching child rules | |
let children = '' | |
// Process every rule in the group body rule | |
Array.from(rule.cssRules).forEach(child => | |
// Remember all matching rules | |
children += processRule(child, children) | |
) | |
// If there were any rules with selectors matching the current tag | |
if (children.length) { | |
// Output an equivalent media rule with matching child rules | |
stylesheet += `@media ${rule.media.mediaText} { ${children} }` | |
} | |
} | |
} | |
) | |
return stylesheet | |
}, | |
'' | |
) | |
) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment