get CSS rule's percentage value in jQuery

Viewed 83633

Let's say the rule is as follows:

.largeField {
    width: 65%;
}

Is there a way to get '65%' back somehow, and not the pixel value?

Thanks.

EDIT: Unfortunately using DOM methods is unreliable in my case, as I have a stylesheet which imports other stylesheets, and as a result the cssRules parameter ends up with either null or undefined value.

This approach, however, would work in most straightforward cases (one stylesheet, multiple separate stylesheet declarations inside the head tag of the document).

13 Answers

This is most definitely possible!

You must first hide() the parent element. This will prevent JavaScript from calculating pixels for the child element.

$('.parent').hide();
var width = $('.child').width();
$('.parent').show();
alert(width);

See my example.

Now... I wonder if I'm first to discover this hack:)

Update:

One-liner

element.clone().appendTo('body').wrap('<div style="display: none"></div>').css('width');

It will leave behind a hidden element before the </body> tag, which you may want to .remove().

See an example of one-liner.

I'm open to better ideas!

There's no built-in way, I'm afraid. You can do something like this:

var width = ( 100 * parseFloat($('.largeField').css('width')) / parseFloat($('.largeField').parent().css('width')) ) + '%';

You could access the document.styleSheets object:

<style type="text/css">
    .largeField {
        width: 65%;
    }
</style>
<script type="text/javascript">
    var rules = document.styleSheets[0].rules || document.styleSheets[0].cssRules;
    for (var i=0; i < rules.length; i++) {
        var rule = rules[i];
        if (rule.selectorText.toLowerCase() == ".largefield") {
            alert(rule.style.getPropertyValue("width"));
        }
    }
</script>

A late response but wanted to add on for anyone 2020+ who stumbles across this. Might be more for niche cases but I wanted to share a couple options.

If you know what the initial % value is you can also assign these values to variables in the :root of the style sheet. i.e

:root {
    --large-field-width: 65%;
}

.largeField {
  width: var(--large-field-width);
}

When you want to access this variable in JS you then simply do the following:

let fieldWidth = getComputedStyle(document.documentElement).getPropertyValue('--large-field-width');
// returns 65% rather than the px value. This is because the % has no relative
// size to the root or rather it's parent.

The other option would be to assign the default styling at the start of your script with:

element.style.width = '65%'

It can then be accessed with:

let width = element.style.width;

I personally prefer the first option but it really does depend on your use case. These are both technically inline styling but I like how you can update variable values directly with JS.

You could put styles you need to access with jQuery in either:

  1. the head of the document directly
  2. in an include, which server side script then puts in the head

Then it should be possible (though not necessarily easy) to write a js function to parse everything within the style tags in the document head and return the value you need.

There's nothing in jQuery, and nothing straightforward even in javascript. Taking timofey's answer and running with it, I created this function that works to get any properties you want:

// gets the style property as rendered via any means (style sheets, inline, etc) but does *not* compute values
// domNode - the node to get properties for 
// properties - Can be a single property to fetch or an array of properties to fetch
function getFinalStyle(domNode, properties) {
    if(!(properties instanceof Array)) properties = [properties]

    var parent = domNode.parentNode
    if(parent) {
        var originalDisplay = parent.style.display
        parent.style.display = 'none'
    }
    var computedStyles = getComputedStyle(domNode)

    var result = {}
    properties.forEach(function(prop) {
        result[prop] = computedStyles[prop]
    })

    if(parent) {
        parent.style.display = originalDisplay
    }

    return result
}
Related