39

I am writing an e-mail HTML template, and some e-mail clients do not support <style> for specifying CSS. The only alternative for applying CSS is to use inline styles (style attribute). Is there a tool or library (Node.JS) for applying a stylesheet to some HTML and getting back the HTML with the styles applied?

The tool does not have to support many selectors; id, class, and element name selectors should be sufficient for my needs.

Example of what is needed:

// stylesheet.css
a { color: red; }

// email.html
<p>This is a <a href="http://example.com/">test</a></p>

// Expected result
<p>This is a <a href="http://example.com/" style="color: red;">test</a></p>
RichardTheKiwi
  • 105,798
  • 26
  • 196
  • 262
strager
  • 88,763
  • 26
  • 134
  • 176

5 Answers5

21

I think juice is what you're looking for.

Simply require it, then pass it your html and css and let it do the heavy lifting for you like this:

var juice = require('juice');
var inlinedcss = juice('<p>Test</p>', 'p { color: red; }');

It builds on a number of mature libraries including mootools' slick, and supports a broad range of selectors.

You may also be interested in node-email-templates, which is a nice wrapper for dynamic emails in node.

Jed Watson
  • 20,150
  • 3
  • 33
  • 43
7

Here's the alive javascript projects that does what you want:

  • juice. 1.7Mb with dependencies.
  • juice2. 5.9Mb with dependencies. This is a fork of juice, seems to be containing more options than juice. This one doesn't drop media queries as juice does. Sorts inline css rules alphabetically.
  • styliner. 4.0Mb with dependencies. This one uses promises instead. Have a couple of different options than juice2. Has a compact option that other ones don't have that minifies the html. Doesn't read the html file itself as others do. Also extends margin and padding shorthands. And in case you somehow modify your native objects(like if you are using sugar) I don't suggest using this till this issue is resolved.

So which one to use? Well it depends on the way you write CSS. They each have different support for edge cases. Better check each and do some tests to understand perfectly.

Farid Nouri Neshat
  • 29,438
  • 6
  • 74
  • 115
3

You could use jsdom + jquery to apply $('a').css({color:'red'});

generalhenry
  • 17,227
  • 4
  • 48
  • 63
  • That requires the email client to support javascript. Not a given, unfortunately. – staticsan Feb 04 '11 at 05:25
  • 1
    @staticsan: jsdom is intended as serverside javascript, so I don't think email client support is an issue. – Lèse majesté Feb 04 '11 at 05:35
  • @staticsan, the OP mentioned Node.JS specifically. Great idea generalhenry. +1 – David Tang Feb 04 '11 at 05:54
  • Hmm. Okay, I missed the Node.js reference in the OP. Also, googling jsdom didn't tell me that it is intended as serverside JS. I suspect there has been a collision of assumptions. (Going away now...) – staticsan Feb 04 '11 at 06:18
  • This looks like the solution I'll be going with. Unless I can find a CSS parser, I'll have to manually apply styles (which shouldn't be too much trouble). – strager Feb 04 '11 at 07:58
3

2020 solution https://www.npmjs.com/package/inline-css

var inlineCss = require('inline-css');
var html = "<style>div{color:red;}</style><div/>";

inlineCss(html, options)
    .then(function(html) { console.log(html); });
jmp
  • 2,456
  • 3
  • 30
  • 47
0

Another alternative is to go back to basics. If you want a link to be red, instead of

<a href="" style="color: red">my link</a>

do

<a href=""><font color="red">my link</font></a>

Almost any browser, including the terrible BlackBerry browser can handle that.

Sean
  • 788
  • 3
  • 10
  • 1
    Yes, but I would still need to process all these HTML documents to transform "normal" CSS into using ``. – strager Feb 04 '11 at 07:30