physicsboy
physicsboy

Reputation: 6348

Change CSS with properties defined in an object

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

Answers (3)

H K
H K

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

abdelhedi hlel
abdelhedi hlel

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

Mamun
Mamun

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

Related Questions