First, there are many duplicates for this question but those answers don't give deeper insights.
Q1. Why this results in 200,0 ?
Consider this snippet:
var el = document.querySelector('#r');
console.log('First:: ' + el.offsetHeight);
el.style = {
height: el.offsetHeight + 500 + 'px'
}
console.log('Second:: ' + el.offsetHeight);
<div id="r" style="height:200px;width:800px;overflow:auto;border:1px solid;margin:20px;box-sizing:border-box"></div>
First, there are many duplicates for this question but those answers don't give deeper insights.
Q1. Why this results in 200,0 ?
Consider this snippet:
var el = document.querySelector('#r');
console.log('First:: ' + el.offsetHeight);
el.style = {
height: el.offsetHeight + 500 + 'px'
}
console.log('Second:: ' + el.offsetHeight);
<div id="r" style="height:200px;width:800px;overflow:auto;border:1px solid;margin:20px;box-sizing:border-box"></div>
I suspect el.style
to be read-only , so I expect setting an object should silently fail and therefore I expect the output to be
First:: 200,Second:: 200
but it is:
First:: 200,Second:: 0
Why ?
Q2. Why setting el.style using Object.assign works ?
Object.assign(el.style,{
height : el.offsetHeight + 500
})
Can someone please explain me with some deeper insights?
Share Improve this question edited Jan 9, 2017 at 23:24 halfer 20.4k19 gold badges108 silver badges201 bronze badges asked Nov 4, 2016 at 15:50 Annamalai SaravananAnnamalai Saravanan 1311 gold badge1 silver badge10 bronze badges 4 |4 Answers
Reset to default 6For your first question:
MDN says that although the style
object is read-only, FF, Chrome and Opera do allow assignments to it (https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style). Now, the offsetHeight
property is read-only (https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetHeight), so it appears that attempting to set the style
is causing that property to be reset to zero since offsetHeight
is calculated value, not one that is set explicitly, and your browser is actually allowing the setting of the style property (albeit incorrectly).
For your second question:
The reason why Object.assign
works is written right into the documentation for Object.assign. It doesn't replace the object, it replaces the enumerable own properties of the object. From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
"Properties in the target object will be overwritten by properties in the sources if they have the same key. Later sources' properties will similarly overwrite earlier ones.
The Object.assign() method only copies enumerable and own properties from a source object to a target object."
So, in your first attempt:
el.style = {
height: el.offsetHeight + 500 + 'px'
}
You are attempting to replace the entire object, which fails, but Object.assign just copies properties, which succeeds.
Based on Chrome https://chromium.googlesource.com/chromium/src/+/d1a7b0cbd0a511459f0f6202dfe61e27aa47df46.,
When we set any property it forwards it to el.style.cssText
(see the spec https://drafts.csswg.org/cssom/#the-cssstylerule-interface)
It says [PutForwards=cssText]
so when assigning a string.,
el.style = 'some valid css string';
// it takes the string and assigns to cssText
el.style.cssText = 'some valid css string';
// So when assigning an object
el.style = {...};
// it takes the object and converts to string toString()
el.style.cssText = '[object Object]';
// Since it is not valid , it unsets everything
I looked this up because I had a series of style properties that I wanted to change and wondered if I could do it using an object so it would look cleaner. If anybody wonders and will stumble upon this subject, here's what I've come up with:
var setStyle = {
zIndex: 10000,
position: "absolute",
top: somey,
left: somex,
opacity: 1,
height: someh + "px",
width: somew + "px"
}
for(let prop of Object.keys(setStyle)){
elem.style[prop.toString()] = setStyle[prop.toString()];
}
Take care
The issue is with this statement:
el.style = {
height: el.offsetHeight + 500 + 'px'
};
Not only does this not work (as in, the element’s CSS height
is not set to 700px
), but it also removes all inline styles that were previously set on the element (the style
attribute):
And since your <div>
is completely empty, its height will be zero. This is why el.offsetHeight
returns 0
at the end.
el.style
is not read-only. You use it to get or set inline styles on an element. Accessing the.style
property returns an object. That object has all the CSS properties. i.e.el.style.height = '500px'
– Scott Marcus Commented Nov 4, 2016 at 15:54el.style.[property]
should work but it fails when assigning an object toel.style
– Annamalai Saravanan Commented Nov 4, 2016 at 16:04