Search code examples
javascriptresponsive-designmedia-queriesstylesheettext-analysis

Determine element styles at all screen sizes


In Javascript we can use something like window.getComputedStyle(element,null).getPropertyValue(property) to retrieve a given element's style property. That being said, any property can change with responsive web design at any screen size.

I'm wondering if it's possible to analyze the element's related stylesheet to determine the styles that will be applied to it at a all window sizes/breakpoints.

For example, a <p> has font-size: 16px on desktop, and font-size: 18px on mobile (set by @media (max-width: 768px) { ... }. I'd like to know that the font size will be 18px on mobile without having to resize down to mobile size and sample the font size again.

I suppose with some clever text processing in JS I could sort through a stylesheet for @media and see if it reflects on the element, but for larger or multiple stylesheets, inline styles, and injected styles that method would likely be impossible to get 100% accurate.

Any ideas?

Thought...

Is it possible to wrap an element in a simulated (hidden) window element and then use JS to resize it so it triggers the media queries?

Another approach...

I started playing around with document.styleSheets but even that seems like a pretty impossible task to get perfect. In my example below I have wrapped some selected text in an element and then passed it to the method below (written in coffeescript).

analyzeSelectiontyles: (selectionElement) ->
    selectionParents = []
    while selectionElement
        selectionParents.unshift selectionElement
        selectionElement = selectionElement.parentNode

    pageStylesheets = document.styleSheets

    for stylesheet in pageStylesheets
        rules = stylesheet.cssRules
        for rule of rules
            if rules[rule]["type"] is 1
                console.log 'standard style'
            if rules[rule]["type"] is 4
                console.log 'media query'
            # If it's a standard style rule or a media query containing
            # style rules we have to check to see if the style rule applies
            # to any one of our selectionParents defined above, and in
            # Which order so as to simulate "cascading"

Solution

  • Something like the following might work iff all of the styles are hosted on the same origin. I tested it here and it couldn't get the all.css file; I assume because it is hosted on a different cdn domain.

    function css(element) {
        var sheets = document.styleSheets,
        standard = [],
        mediaStyles = {};
        element.matches = element.matches || element.webkitMatchesSelector || element.mozMatchesSelector || element.msMatchesSelector || element.oMatchesSelector;
    
        for (var i in sheets) {
            var rules = sheets[i].rules || sheets[i].cssRules;
            for (var r in rules) {
                if (element.matches(rules[r].selectorText)) {
                    if (rules[r]["type"] === 4) {
                        mediaStyles[rules[r].media] = (mediaStyles[rules[r].media] || []).push(rules[r].cssText);
                    } else {
                        standard.push(rules[r].cssText);
                    }
                }
            }
        }
    
        return { 'standard': standard, 'media': mediaStyles };
    }