101

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).

montrealist
  • 5,593
  • 12
  • 46
  • 68
  • 1
    It would be best to seed this data on the element itself and then track how it changes in the future. – Travis J Nov 08 '17 at 22:14

13 Answers13

119

Most easy way

$('.largeField')[0].style.width

// >>> "65%"
redexp
  • 4,765
  • 7
  • 25
  • 37
84

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!

Timofey Drozhzhin
  • 4,416
  • 3
  • 28
  • 31
  • 1
    This should be the accepted solution. I can also confirm it works for me where the other answers don't get the originally assigned percentage value. – EricP Nov 12 '13 at 04:14
  • 1
    To avoid flickering, clone the child, hide the parent, then retrieve the width. var clone = $('.child').clone(); – user1491819 Aug 08 '14 at 04:57
  • Update: var childWidth = jQuery('.parent').clone().hide().find('.child').width(); However, this only returns a number. You couldn't use it to find whether the width was 50px or 50%. – user1491819 Aug 08 '14 at 05:20
  • 3
    Update: function getCssWidth(childSelector){ return jQuery(childSelector).parent().clone().hide().find(childSelector).width(); } console.log('child width:' + getCssWidth('.child'));; – user1491819 Aug 08 '14 at 05:28
  • 1
    Awesome solution! Here's a pure-js equivalent of the script http://jsfiddle.net/Sjeiti/2qkftdjd/ – Sjeiti Jul 01 '15 at 11:49
  • 1
    If the $(...)[0].style.width answer works, then shouldn't that be the accepted solution? This solution, while elegant, does suffer from some performance shortcomings. – Mihai Danila Jan 23 '16 at 21:36
  • @MihaiDanila `$(...)[0].style.width` won't work for most people, since it only works when you apply width through a style, not a class. – Timofey Drozhzhin Jul 28 '16 at 16:24
  • @MihaiDanila That information is already there. See http://stackoverflow.com/questions/744319#answer-10432934 and the highest rated reply to it. – Timofey Drozhzhin Jul 29 '16 at 21:08
  • I'm sure that the same information is also in many other places around the internet, but that's not helpful. There are plenty of folks like me who won't read the comments when looking for an answer, but will read through the various answers. – Mihai Danila Jul 31 '16 at 00:33
  • That is one AWESOME trick. I published a package on NPM using this trick. any contributions are welcome :) https://github.com/idanen/getSizePercent – idan Jul 24 '17 at 06:13
52

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')) ) + '%';
Adam Lassek
  • 35,156
  • 14
  • 91
  • 107
45

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>
maxgalbu
  • 432
  • 3
  • 16
Gumbo
  • 643,351
  • 109
  • 780
  • 844
  • 8
    +1 proper usage of DOM methods (sometimes jQuery is not the answer) – bobince Apr 13 '09 at 18:52
  • 1
    +1 I'm with you here for accuracy. I'm curious about how each browser suppports this, but this is the right answer. – cgp Apr 14 '09 at 01:49
  • Works well in simpler cases, both FF and IE7, but not for me (see EDIT above). – montrealist Apr 15 '09 at 19:04
  • 1
    Have you tried running through all stylesheets too? My example just used the first (`styleSheets[0]`). – Gumbo Apr 15 '09 at 20:05
  • Sorry if this is a noob question, but how would `for (var i=0; rules.length; i++)` work? Shouldn't it be `for (var i=0; i – Stas Bichenko Mar 11 '12 at 17:23
  • There is an issue with this method: there may be more specific rules that apply to an element, for example `#somecontainer > .child > .largefield { width: 30% } ` - the proposed method does not take it into account and thus is not a reliable way to determine the final css rule that is being used for width calculation. There is a function in webkit that does the work for you - called `window.getMatchedCSSRules`, but it's only in Webkit... – ragulka Aug 31 '13 at 11:29
  • If you're fetching an external stylesheet from a different domain, then you won't be able to read the rules (at least on Chrome). Same-origin policy at work, it seems. – danronmoon Sep 24 '13 at 20:56
  • `styleSheets[0]` is just the first stylesheet, not realiable and easy to get the correct file – brauliobo Nov 10 '16 at 10:25
19

Late, but for newer users, try this if the css style contains a percentage:

$element.prop('style')['width'];
ddanone
  • 464
  • 4
  • 8
10

A jQuery plugin based on Adams answer:

(function ($) {

    $.fn.getWidthInPercent = function () {
        var width = parseFloat($(this).css('width'))/parseFloat($(this).parent().css('width'));
        return Math.round(100*width)+'%';
    };

})(jQuery);

$('body').html($('.largeField').getWidthInPercent());​​​​​

Will return '65%'. Only returns rounded numbers to work better if you do like if (width=='65%'). If you would have used Adams answer directly, that hadn't worked (I got something like 64.93288590604027). :)

Leonard Pauli
  • 2,662
  • 1
  • 23
  • 23
5

Building on timofey's excellent and surprising solution, here is a pure Javascript implementation:

function cssDimensions(element) {
  var cn = element.cloneNode();
  var div = document.createElement('div');
  div.appendChild(cn);
  div.style.display = 'none';
  document.body.appendChild(div);
  var cs = window.getComputedStyle
    ? getComputedStyle(cn, null)
    : cn.currentStyle;
  var ret = { width: cs.width, height: cs.height };
  document.body.removeChild(div);
  return ret;
}

Hope it's helpful to someone.

Gregory Magarshak
  • 1,883
  • 2
  • 25
  • 35
1

Convert from pixels to percentage using cross multiplication.

Formula Setup:

1.) (element_width_pixels/parent_width_pixels) = (element_width_percentage / 100)

2.) element_width_percentage = (100 * element_width_pixels) / parent_width_pixels

The actual code:

<script>

   var $width_percentage = (100 * $("#child").width()) / $("#parent").width();

</script>
1

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.

1

I have a similar issue in Getting values of global stylesheet in jQuery, eventually I came up with the same solution as above.

Just wanted to crosslink the two questions so others can benefit from later findings.

Community
  • 1
  • 1
Horst Walter
  • 13,663
  • 32
  • 126
  • 228
  • 2
    Your question and this one are already linked (see the “Linked” sidebar on the right) by virtue of shesek’s comment on your question. – Chris Johnsen Aug 20 '11 at 12:03
0

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
}
B T
  • 57,525
  • 34
  • 189
  • 207
0

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.

wheresrhys
  • 22,558
  • 19
  • 94
  • 162
-1

You can use the css(width) function to return the current width of the element.

ie.

var myWidth = $("#myElement").css("width");

See also: http://api.jquery.com/width/ http://api.jquery.com/css/

user267867
  • 63
  • 1
  • why is this marked down? there is a bug open on this http://bugs.jquery.com/ticket/4772, looks like there is some inconsistency in calling this depending on whether you put your style inline or in a style sheet http://jsfiddle.net/boushley/MSyqR/2/ – Anthony Johnston Feb 04 '11 at 13:01
  • 1
    i cant get % with this – someoneuseless Aug 22 '19 at 03:23