1

I have some dynamically created html whole css properties are in an object. So they need to be given using Javascript. So I have used the method below for appending to styles to the dynamically created dom element. I believe it's costly as each time a I'm doing a dom manipulation for appending styles. In the below code itself 10 lines are doing css dom manipulation.

function createNavbar() {
  let nav;
  nav = '<div class="navbar" id="nav"></div>';
  this.body.insertAdjacentHTML("beforeend", nav);
  let navBar = document.getElementById("nav");
  navBar.style.display = "block"; // style appending begins
  navBar.style.background = this.navColors.notice.bg;
  navBar.style.color = this.navColors.notice.textColor;
  navBar.style.borderWidth = "1px";
  navBar.style.borderStyle = "solid";
  navBar.style.borderColor = this.navColors.notice.borderColor;
  navBar.style.top = this.navPositionValue[this.position].top;
  navBar.style.right = this.navPositionValue[this.position].right;
  navBar.style.bottom = this.navPositionValue[this.position].bottom;
  navBar.style.left = this.navPositionValue[this.position].left; // style appending ends
}

Found a better way from this SO Question, so I used the below line to replace the 10 line code ( used the cssText property )

navBar.style.cssText = `display: block; color: ${this.navColors.notice.textColor}; background: ${this.navColors.notice.bg}; border: 1px solid ${this.navColors.notice.borderColor}; top: ${this.navPositionValue[this.position].top}; right: ${this.navPositionValue[this.position].right}; bottom: ${this.navPositionValue[this.position].bottom}; left: ${this.navPositionValue[this.position].left};`

By using this method I hope the Dom manipulation is reduced to 1 instead of 10, but the line is pretty long and hard to read. I would like to know if there is any better way than this to append long lines or many css in js

theFrontEndDev
  • 890
  • 1
  • 17
  • 41
  • 1
    Since you're using [template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) you can just add line breaks (enters) for more readable code. Or just create a class and add that class to the element – Reyno Aug 19 '20 at 14:14
  • @Reyno Oh! That's great! I will do that. Is the method I have used an optimized one? – theFrontEndDev Aug 19 '20 at 14:17
  • 2
    Using 10 instructions to change as many style properties will not cause 10 separate CSS repaints, because you are doing all the changes without yielding to the JavaScript event loop in-between. – Touffy Aug 19 '20 at 14:23
  • 1
    @theFrontEndDev yes, this is pretty good, their is not really a big difference with the first option though. I also created an answer to show you how to remove the big variables you have for the colors and position. It helps to increase the readability. – Reyno Aug 19 '20 at 14:25
  • 1
    there is no need for optimization. the browser will update your css only once. see my answer below – k1ngjulien Aug 19 '20 at 14:34

4 Answers4

2

just add a class with common styles then add the class to the dom. isn't that the easiest way?

1

Your code above will only cause one update of the page because of how the Browser works. You do not have to worry about optimizing it.

Basically, all your changes will be applied at once after your function has ended, meaning that even if you change element.style multiple times inside one function, it is still just one operation.

For more information as to why and how this works I recommend this talk by Jake Archibald about how the Event Loop works.

k1ngjulien
  • 411
  • 6
  • 12
  • "browsers are smart" may be a slight overstatement and an unnecessarily complex reason in this case, but the conclusion is correct. – Touffy Aug 19 '20 at 14:25
  • @K1ngjulien_ Thanks for the update. I thought its similar to the append method. I believe I have read somewhere that appending constantly to DOM is costly and they explained the concept called document fragment to reduce that. I saw this too as a similar case. Anyway the second one looks cleaner than 10 lines of code. With few line breaks I guess it would be fine – theFrontEndDev Aug 19 '20 at 14:33
  • @theFrontEndDev looks like your're just appending one element to the dom so I wouldn't worry about any performance issues. – k1ngjulien Aug 19 '20 at 14:37
  • @theFrontEndDev also I'd use document.createElement() to create new dom nodes and just append them where you need them, so you don't have to query for the node you just inserted with insertAdjacentHTML – k1ngjulien Aug 19 '20 at 14:37
1

You can add linebreaks inside template literals to increase readability.

Another option is to destructure some of the objects so we don't have really long variable names that we have to repeat.

const navBar = document.querySelector(".navBar");

const navColors = {
  notice: {
    textColor: "red",
    bg: "green",
    borderColor: "blue",
  }
};

const navPositionValue = {
  top: "5px",
  right: "10px",
  bottom: "15px",
  left: "20px",
};

// destructering so we dont have to repeat "navColors.notice" or "navPositionValue" for each value
const {textColor, bg, borderColor} = navColors.notice;
const {ttop, right, bottom, left} = navPositionValue;

navBar.style.cssText = `
  display: block;
  color: ${textColor};
  background: ${bg};
  border: 1px solid ${borderColor};
  top: ${ttop};
  right: ${right};
  bottom: ${bottom};
  left: ${left};
`;
.navBar {
  padding: 20px;
}
<div class="navBar">
  I'm a navBar
</div>
Reyno
  • 6,119
  • 18
  • 27
0

You can use template literals

And you can marge css border

function createNavbar() {
  let nav = `
        <div class="navbar" id="nav" style = "
          display: block;
          background: ${this.navColors.notice.bg};
          color: ${this.navColors.notice.textColor};
          border: 1px solid ${this.navColors.notice.borderColor};
          top: ${this.navPositionValue[this.position].top};
          right: ${this.navPositionValue[this.position].right};
          bottom: ${this.navPositionValue[this.position].bottom};
          left: ${this.navPositionValue[this.position].left};
        ">
        </div>
  `
  document.body.insertAdjacentHTML("beforeend", nav);
}
Nekiy2
  • 81
  • 6