21

What is a good way to apply styling dynamically (i.e. the value of styles are created at runtime) to HTML elements with JavaScript?

I'm looking for a way to package a JavaScript widget (JS, CSS and markup) in a single component (basically, an object). The idea would be for the component to encapsulate styling (so users have a nice API to modify it instead of a more tightly coupled approach of modifying the CSS directly and having changes applied indirectly). The problem is that a single API call might imply changes to several styling elements.

The way I would do it is to construct the CSS and set thestyle atrribute to the proper elements (most likely using the ID to avoid applying changes to other areas of the markup). Is this a good solution? Is there a better way to do it?

AtheistP3ace
  • 9,611
  • 12
  • 43
  • 43
Juan Carlos Coto
  • 11,900
  • 22
  • 62
  • 102
  • 1
    I would create css rules with JS, the inline style solution imply that you have to change all styles attributes when you need to make a change for a set of elements. – Hacketo Feb 25 '16 at 15:05

6 Answers6

26

Using Jquery

Use the css() function to apply style to existing elements where you pass an object containing styles :

var styles = {
  backgroundColor : "#ddd",
  fontWeight: ""
};
$("#myId").css(styles);

You can also apply one style at the time with :

$("#myId").css("border-color", "#FFFFFF");

Vanilla JS :

var myDiv = document.getElementById("#myId");
myDiv.setAttribute("style", "border-color:#FFFFFF;");

With Css :

You can also use a separate css file containing the different styles needed inside classes, and depending on the context you add or remove those classes to your elements.

in your css file you can have classes like

.myClass {
    background-color: red;
}

.myOtherClass {
    background-color: blue;
}

Again using jquery, to add or remove a class to an element, you can use

$("#myDiv").addClass('myClass');

or

$("#myDiv").removeClass('myClass');

Again, you can also do the same with vanilla JS:

document.getElementById("#myId").classList.add('myClass') 

or

document.getElementById("#myId").classList.remove('myClass') 

I think this is a cleaner way as it separates your style from your logic. But if the values of your css depends from what is returned by the server, this solution might be difficult to apply.

kerwan
  • 699
  • 10
  • 21
7

The way I would do it is to construct the CSS and set the style attribute to the proper elements. For example:

var div = document.createElement('div');
div.setAttribute("style", "color: blue, margin-top:5px");
document.body.appendChild(div);

This code will create a new div element with the style color: blue, margin-top:5px and append it to the page.

Dean Meehan
  • 2,511
  • 22
  • 36
  • 1
    "The way I would do it is to construct the CSS and set the style atrribute to the proper elements " – Hacketo Feb 25 '16 at 15:00
  • 1
    I would rather use the `style` property of the DOM Element instead of the `setAttribute()`, something like: `div.style = 'color: blue, margin-top:5px'` – Roberto Linares Feb 25 '16 at 15:07
  • Aren't these all the same? – Juan Carlos Coto Feb 25 '16 at 15:19
  • OP is about "Is this a good solution? Is there a better way to do it?" not how to add inline style. – Hacketo Feb 25 '16 at 15:24
  • This is the best way to do it, you can of course write CSS and place it into your head dynamically `http://stackoverflow.com/questions/3922139/add-css-to-head-with-javascript` then add classes to the element but there is no point in over complicating what is a simple problem. Easy to read and easy to change. – Dean Meehan Feb 25 '16 at 15:58
  • Yeah, like I said in the question, this sounds like the best. However, I don't understand the distinction of setting the DOM element's `style` property vs atrribute. How does that impact the solution? If it merits asking a new question, let me know and I'll get to it. – Juan Carlos Coto Feb 25 '16 at 21:00
  • 4
    Mozilla states "Setting style Note that styles should NOT be set by assigning a string directly to the style property (as in elt.style = "color: blue;" ), since it is considered read-only because the style attribute returns a CSSStyleDeclaration object which is also read-only." -https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style – Dean Meehan Feb 26 '16 at 11:29
  • No answer or comment so far mentions how to add a style in plain JS without modifying existing styles of the element. Though the question asks only about setting, useful for those who end up here looking for how to add. @DeanMeehan has quoted the doc mentioning how not to do it. Next line says how to do it: **Instead, styles can be set by assigning values to the properties of `style`. For adding specific styles to an element without altering other style values, it is preferred to use the individual properties of `style` (as in `elt.style.color = '...'`) as using `elt.style.cssText = '...'`** – trss Feb 13 '20 at 15:44
7

Using Vanilla JS you could do something like this.

If you want to add a CSS class named animate to an element with Id circle, do it like this.

var circle = document.getElementById("circle");
circle.classList.add('animate');

You can remove the class like this.

circle.classList.remove('animate');
1

Since you have also asked if there is a better way and you building a component, a better way i would recommend is for you to build such a component with frontend javascript framework because they make dynamically styles very easy out of the box take an example of Vuejs, Reactjs

`      
import React, {Component} from 'react'
import styled from 'styled-jss'
const Circle = styled('div')({
  position: 'absolute',
  width: 50,
  height: 50,
  borderRadius: '50%',
  background: (props) => (
    /* Generates a random or based on props color */
  ),
  transform: (props) => (
    /* Generates a random or based on props transform for  positioning */
  )
})
class Demo extends Component {
  componentDidMount() {
    this.tick()
  }
  tick = () => {
    requestAnimationFrame(() => {
      this.setState({/* Some new state */}, this.tick)
    })
  }
  render() {
    return (
      <div>
        {[...Array(amount)].map(() => <Circle />)}
      </div>
    )
  }
}
`
Matovu Ronald
  • 782
  • 11
  • 13
0

I could be misinterpreting your question, but it sounds like you are asking for a simple architectural pattern. You want something that makes it easier for someone who is using your widget to change it to their specifications?

If this is the case, then I do not know of any special pattern to do this without using CSS.

I can tell you that the "widgets" that I have found easiest to use do have separate CSS files. I have found it fairly straightforward to modify them to my needs. I think this is because the structure of using CSS with HTML and Javascript is already a nice, simple pattern. I don't know of there is anything better, especially considering that people are already very familiar with the HTML/CSS relationship.

Chris Dutrow
  • 48,402
  • 65
  • 188
  • 258
  • The question goes along the lines of creating components with JS that can be independent of each other. While what you say about HTML and CSS being standard is absolutely true, this is more about packaging things in a way that enhances cohesion and reduces coupling. Packaged like this, users of the widget need not know what styling is done in order to construct the widget, which has the added benefit of not requiring them to know more than a single API to interact with it. – Juan Carlos Coto Feb 25 '16 at 21:07
  • I think you want to use .attr('style', '...') or .css('width, etc', '0px,etc..") then. – Chris Dutrow Feb 25 '16 at 21:11
0
window.onscroll = function(){workOnScroll()};
function workOnScroll() {
  if (document.body.scrollTop > 50 || document.documentElement.scrollTop > 50) {
      var ul = document.getElementById("ulID");
      ul.setAttribute("style", "position: sticky;top: 150px;");
  } else {
      var ul = document.getElementById("ulID");
      ul.setAttribute("style", "position: relative;top: 0px;");
  }
}
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Sep 02 '22 at 22:43