Skip to content

Instantly share code, notes, and snippets.

@tomhodgins
Created October 26, 2019 22:16
Show Gist options
  • Save tomhodgins/8decbb628b620f2a33bdb8fadf77aa44 to your computer and use it in GitHub Desktop.
Save tomhodgins/8decbb628b620f2a33bdb8fadf77aa44 to your computer and use it in GitHub Desktop.
// 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