5

If I create a vanilla JS component like this:

class TestComponent {
  constructor(el) {
    this.render(el);
  }

  render(el) {
    var html = `
      <div>
        <p>Some dummy content</p>
      </div>
    `;
    document.getElementById(el).innerHTML = html;
  }
}

Can I add CSS in JS for it? I mean something like:

const styles = {
  backgroundColor: 'palevioletred',
  color: 'papayawhip',
};

so the above render method will look like this:

render(el) {
  var html = `
    <div style={styles}>
      <p>Some dummy content</p>
    </div>
  `;
  document.getElementById(el).innerHTML = html;
}

is that possible to do outside of frameworks like Angular / React ?

3
  • 3
    ANYTHING a JavaScript framework or library can do, vanilla JavaScript can do, because all those frameworks and libraries are written in vanilla JavaScript or eventually output vanilla JavaScript.. People tend to forget or not know this. Commented Sep 2, 2018 at 14:49
  • Why do you not want to use classes ? Commented Sep 2, 2018 at 14:54
  • 2
    @rach8garg, because I want it to be something like a stand alone component, that includes it's own html and css, and in my opinion inline css is not a good solution, and I like the css-in-js approach (like what we get when using Radium and other tools). Commented Sep 2, 2018 at 15:02

3 Answers 3

5

You are using a JS object into HTML (a String). So you have to convert your object into a valid HTML String:

const styles = {
  // CSS key is `background-color` instead of `backgroundColor`
  'background-color': 'palevioletred', 
  color: 'papayawhip',
}


render(el) {
  // Loop every keys, and create an array contain every
  // key:value
  // join every items on array to create a single String.
  var string_styles = Object.keys(styles).map(s => { 
    return s + ":" + styles[s]
  }).join(';')

  // Or
  string_styles = JsToCss(styles)  


  var html = '<div style="' + string_styles + '">' +
      '<p>Some dummy content</p>' +
    '</div>';
  document.getElementById(el).innerHTML = html;
}

// Decomposed function:
let JsToCss = (styles) => {
  let keys = Object.keys(styles) 
  // keys = [ 'background-color', 'color']

  let css_values = keys.map(key => {
    return key + ":" + styles
  })
  // css_values = [
  //     'background-color:palevioletred', 
  //     'color:papayawhip'
  // ]

  return css_values.join(';') 
  // return "background-color:palevioletred;color:papayawhip;" 
}

Code not tested but this is the idea

Sign up to request clarification or add additional context in comments.

6 Comments

Concise answer. I believe it should be style="${string_styles}"
And, you haven't addressed the conversion from camel case to hyphenated syntax.
@KhauriMcClain thank you, I updated my answer. Also add a comment for the conversion
@Arthur I think you still have to wrap it in quotes. A suggestion for converting from camel case to hyphenated case: s.replace(/([A-Z])/g, "-$1").toLowerCase()
@KhauriMcClain, Okay, I didn't use new ES6 syntax for concat, so I redo it with old way (to be sure it's working good). It's not the idea of the reply so i'ts not important (more info about es6 template strings: developers.google.com/web/updates/2015/01/ES6-Template-Strings)
|
1

You would need to convert the object to valid CSS.

<div style={styles}> won't work because you are asking for an object to be converted to a string here and the conversion won't yield the result you want.

const styles = {
  backgroundColor: 'palevioletred',
  color: 'papayawhip',
};

console.log(styles.toString());

You could use JSON.stringify(), but even then, you'd need to remove the braces, convert commas to semi-colons, remove the excess quotes, and convert camel cased names to hyphenated names.

I've done all this below and broken it up into individual steps to show what has to be done, but it could be condensed into a single statement and even made more compact with a regular expression. But, this should give you the idea.

FYI: You need a $ in front of your template literal to identify it as such.

const styles = {
  backgroundColor: 'palevioletred',
  color: 'papayawhip',
};

let cssString = JSON.stringify(styles);
console.log(cssString);

// Remove the braces
cssString = cssString.replace("{","").replace("}","");
console.log(cssString);

// Remove the quotes
cssString = cssString.replace(/"/g, "")
console.log(cssString);

// Change comma to semi-colon and add trailing semi-colon
cssString = cssString.replace("," ,";") + ";";
console.log(cssString);

// Convert camel case to hyphen
cssString = cssString.replace("backgroundColor", "background-color");
console.log(cssString);

class TestComponent {
  constructor(el) {
    this.render(el);
  }

  render(el) {
    var html = `
      <div style=${cssString}>
        <p>Some dummy content</p>
      </div>
    `;
    document.getElementById(el).innerHTML = html;
  }
}

let tc = new TestComponent("test");
<div id="test"></div>

8 Comments

Care to explain the down vote for a working answer with explanation?
@H.Pauwelyn My answer clearly states that hyphenation is an issue and my answer also clearly states that my solution is only an example.
@ScottMarcus Why did you create a wrong string and updating it, instead of building the good string first ?
@Arthur I'll ask you the same question brk did when you made the same comment to him - - what are you talking about? The string my code creates is correct.
It's correct after some transformations, but the first one isn't after: let cssString = JSON.stringify(styles). It's a lots of update to do after a stringify, and you can just build yourself the valid string
|
0

I made a simple genCSS function which takes CSS in the javascript object and converts into CSS string and generated CSS applied to style tag.

const genCSS = (style) => {
  let result = '';
  for (props in style) {
     let keyValuePair = `${props}:${style[props]};`;
     result += keyValuePair;
   }
   return result;
};

const styles = {
  background: '#2196f3',
  color: 'white',
  padding: '5px 10px'
};

class TestComponent {
  constructor(el) {
    this.render(el);
  }

  render(el) {
    const genStyle = genCSS(styles);

    var html = `
      <div style="${genStyle}">
        <p>Some dummy content</p>
      </div>
    `;
    document.getElementById(el).innerHTML = html;
  }
}

const test = new TestComponent('root');

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.