Reputation: 6348
Is it at all possible to dynamically style elements using CSS properties that are stored within a JS object?
For example, changing both the width
and background
of a simple <div>
element:
<div id="box"></div>
<button id="btn">click me</button>
The box is initally styled with:
div {
background: grey;
width: 100px;
height: 100px;
}
The box will be restyled when clicking the button element as so:
btn.addEventListener('click', () => {
// Code to change box style here...
}
I have seen the use of setAttribute('style', 'some style stuff here');
, however I have come to understand that this will simply replace ALL of the style attribute associated with the element, rather than appending/changing the properties defined within :-(
My goal here is to do hold CSS properties in a JS object such as:
const myStyle = {
'background': 'green',
'width': '20px'
}
and apply this to the element.
I know this can be done by holding the properties in another CSS class named something like '.box-transform' and then adding that to the classList of the element... But I am wanting to do this through JS.
My initial attempt was something along the lines of:
btn.addEventListener('click', () => {
for (let [key, val] of Object.entries(myStyle)) {
console.log(`${key}: ${val}`)
box.setAttribute('style', `${key}: ${val}`)
}
});
However I was running into the issue of the overriding nature of setAttribute
...
const btn = document.getElementById('btn');
const box = document.getElementById('b');
const myobj = {
'width': '20px',
'background': 'yellow'
};
btn.addEventListener('click', () => {
for (let [key, val] of Object.entries(myobj)) {
console.log(`${key}: ${val}`)
box.setAttribute('style', `${key}: ${val}`)
}
});
.box {
width: 300px;
height: 300px;
background: grey;
}
<div class="box" id="b"></div>
<button id="btn">click</button>
Upvotes: 5
Views: 2038
Reputation: 1232
Here are a number of ways of we can apply styles from a JavaScript object to an element's style attribute.
For the most concise syntax where ES6 is acceptable we can use Object.assign
:
Object.assign(elem.style, stylesObject);
We can also convert the styles object to an array with Object.entries
then use map
to convert each key-value to an appropriate string and finally, join the strings together using join
:
elem.style = Object.entries(stylesObject).map(x => `${x[0]}:${x[1]}`).join(';');
We can also concatenate a string using various for
loops.
We can use for in
:
let str = '';
for (let style in stylesObject) {
str += `${style}:${stylesObject[style]};`;
}
elem.style = str;
or we can use forEach
:
let str = '';
Object.entries(stylesObject).forEach(style => {
str += `${style[0]}:${style[1]};`;
})
elem.style = str;
or we can use for of
:
let str = '';
for (let style of Object.entries(stylesObject)) {
str += `${style[0]}:${style[1]};`;
}
elem.style = str;
and finally, we can also use a regular good ol' for
loop:
const stylesArray = Object.entries(stylesObject);
let str = '';
for (let x = 0; x < stylesArray.length; x++) {
str += `${stylesArray[x][0]}:${stylesArray[x][1]};`;
}
elem.style = str;
You can check out this benchmark tests I put together to see how these options affect performance.
[For the curious, you can see version 2 of the benchmark tests, where I added more variations (most of the additions is just changing Object.entries
to Object.keys
).]
I left out the option of applying the style in each loop iteration instead of concatenating to a string, because, as you can see in the benchmarks, that is significantly more expensive.
Upvotes: 1
Reputation: 3749
const btn = document.getElementById('btn');
const box = document.getElementById('b');
const myobj = {
'width': '200px',
'background': 'yellow'
};
btn.addEventListener('click', () => {
for (let [key, val] of Object.entries(myobj)) {
box.style[key] = val;
}
});
.box {
width: 300px;
height: 300px;
background: grey;
}
<div class="box" id="b"></div>
<button id="btn">click</button>
Upvotes: 4
Reputation: 68933
You can first generate the CSS as string then use cssText
property:
const btn = document.getElementById('btn');
const box = document.getElementById('b');
const myobj = {
'width': '20px',
'background': 'yellow'
};
btn.addEventListener('click', () => {
var cssText ='';
for (let [key, val] of Object.entries(myobj)) {
cssText += `${key}: ${val};`
}
box.style.cssText = cssText;
});
.box {
width: 300px;
height: 300px;
background: grey;
}
<div class="box" id="b"></div>
<button id="btn">click</button>
You can also update the style with the object key and value inside the loop:
const btn = document.getElementById('btn');
const box = document.getElementById('b');
const myobj = {
'width': '20px',
'background': 'yellow'
};
btn.addEventListener('click', () => {
var cssText ='';
for (let [key, val] of Object.entries(myobj)) {
box.style[key] = val;
}
});
.box {
width: 300px;
height: 300px;
background: grey;
}
<div class="box" id="b"></div>
<button id="btn">click</button>
Upvotes: 1