2

I need to find out the width which is defined via CSS of an element on the page; I do not need the actual width which was calculated by the browser!

It's no problem to get the width value from an inline style attribute, but how do I get the width-definition when it is inside a CSS file?

Here's a short sample with 3 div-elements:

  • The first div uses an inline CSS width, which I can find.
  • The second div has a relative width defined via CSS → How can I find the "50%" value?
  • The third div has no width definition → How can I find out that this div has no width?

var box1 = document.getElementById('item1');
var box2 = document.getElementById('item2');
var box3 = document.getElementById('item3');

console.log('Box 1 width:', box1.style.width); // all good!
console.log('Box 2 width:', box2.style.width); // required result: "50%"
console.log('Box 3 width:', box3.style.width); // required result: "", "initial" or undefined
#item1 { width: 200px; }
#item2 { width: 50%; }

#item1, #item2, #item3 { background: #ccc; margin: 2px; padding: 5px }
<div id="item1" style="width: auto">Box 1</div>
<div id="item2">Box 2</div>
<div id="item3">Box 3</div>
Philipp
  • 10,240
  • 8
  • 59
  • 71
  • 1
    https://stackoverflow.com/questions/2558062/use-javascript-to-get-the-style-of-an-element-from-an-external-css-file – s.kuznetsov Aug 29 '20 at 16:58
  • https://stackoverflow.com/questions/47024065/getting-style-of-an-element-from-css-file-with-javascript – s.kuznetsov Aug 29 '20 at 17:01
  • 1
    Those solutions all work. I do not know how I could miss them... Thanks!! – Philipp Aug 29 '20 at 17:02
  • @sergeykuznetsov I would argue that the solutions you provided give the actual current style of the div, not the original value provided in the stylesheet once its overwritten by the inline style, and as such does not really answer the question – chiliNUT Aug 29 '20 at 17:28
  • 1
    @Philipp as I understand your question, the posted solutions here do not work as they show the actual value of the width of the element, not the original value specified in the stylesheet before it was overwritten with an inline or inherited style – chiliNUT Aug 29 '20 at 17:29
  • 1
    @chiliNUT, the solution links I provided are just a hint for a solution. – s.kuznetsov Aug 29 '20 at 17:32
  • 1
    @chiliNUT you are right. I tested the `getComputedStyle` method in jsbin - the results did look good there, but in the actual JS file the results are not _definitions_ but _resolved values_. – Philipp Aug 29 '20 at 17:37

1 Answers1

2

EDIT

One point my original answer missed is: If the element has an inline style being applied, use that, then look to the stylesheet if there is no inline style.

getComputedStyle will give you the actual width of the div, not the width specified in the style sheet.

If you need to find out the rules defined in a stylesheet, not the actual style values of an element, you can do so by iterating over the stylesheet.

let cssRules = Array.from(document.styleSheets[0].rules); //the 3 styles youve set
function getStylesheetPropertyForElement(id, property) {
    let element = document.getElementById(id), appliedStyle ="";
    if (!element) return false;
    // prefer inline style if available!
    if (element.style[property]) return element.style[property];//
    // reverse the order of the rules. 
    // naively assumes the most recent rule is the one thats applied
    // makes no attempt to handle priority and !important
    cssRules.reverse().some(rule => {
        // does the selector for this rule match?
        if (element.matches(rule.selectorText)) {
            //yes. is there a rule for the required property?
            if (Array.from(rule.style).some(el=>el === property)) {
                // great
                appliedStyle = rule.style[property];
                return true;
            }
        }
    });
    return appliedStyle;
}
console.log(getStylesheetPropertyForElement('item1', 'width')); //auto
console.log(getStylesheetPropertyForElement('item2', 'width')); //50%
console.log(getStylesheetPropertyForElement('item3', 'width')); //""
#item1 { width: 200px; }
#item2 { width: 50%; }

#item1, #item2, #item3 { background: #ccc; margin: 2px; padding: 5px }
<div id="item1" style="width: auto">Box 1</div>
<div id="item2">Box 2</div>
<div id="item3">Box 3</div>
chiliNUT
  • 18,989
  • 14
  • 66
  • 106
  • 1
    width for box 1 should say "auto" per question... – iAmOren Aug 29 '20 at 17:39
  • 1
    I've made a jsbin to compare the results of this answer with the `getComputedStyle` approach. This answer is the correct one! → https://jsbin.com/poqudug/edit?js,console,output (note: when "output" is disabled, both methods give the right results) – Philipp Aug 29 '20 at 17:39
  • 1
    Perfect solution. I'll take your code for myself for the future `:)` – s.kuznetsov Aug 29 '20 at 17:42
  • @iAmOren that's a great point! I answered the question of "what style is being applied by the sheet" and missed that nuance – chiliNUT Aug 29 '20 at 18:35
  • @Philipp please see the update as my original answer was neglecting the inline style if present – chiliNUT Aug 29 '20 at 18:41
  • @sergeykuznetsov honestly in my day to day coding I rarely need to use something like this, but it has come up once in the past so I can see this kind of thing being useful for certain situations like debugging purposes – chiliNUT Aug 29 '20 at 18:42
  • @chiliNUT, yes, this is really rarely needed, and for debugging. I agree with you. – s.kuznetsov Aug 29 '20 at 18:43
  • @Philipp glad this worked for you! Curious what your use case is? – chiliNUT Aug 29 '20 at 18:48
  • 1
    @chiliNUT I need to know whether users defined a custom width for a section or not. The width can be assigned in a visual builder or via a CSS file (or not at all). When the width is undefined or set to "auto" my script needs to apply a default value. That's why I cannot use the computed width, as it does not differentiate between custom width and auto-width – Philipp Aug 29 '20 at 23:33
  • @Philipp oh cool, its a situation where end users can modify styles. gotcha – chiliNUT Aug 30 '20 at 01:01