53

Just wondering if anyone knows whether it is possible to format the content of an element as currency using only CSS. It would be nice to have how the value is presented in CSS if possible, can't find anything though so I'm not holding my breath :)

<!DOCTYPE html>
<html>
<head>
    <style type="text/css">
        .dollars:before { content:'$'; }
    </style>
</head>
<body>
    Pure CSS: <span class="dollars">25153.3</span>
    <br />
    Ideal format: <span>$25,153.30</span>
</body>
</html>

That example comes out as:

Pure CSS: $25153.3

Ideal format: $25,153.30

Also I'm aware that it's fairly trivial using javascript - http://css-tricks.com/snippets/javascript/format-currency/.

Daniel Imms
  • 47,944
  • 19
  • 150
  • 166

4 Answers4

36

The currency format can be achieved with CSS and a bit of Javascript which is needed for the parsing of the number to add the commas. A CSS class adds the additional styling like negative (red) or currency sign (i.e. $ Dollar sign). The approach is a follows:

1) Convert the value to number (adds the commas based on the locale)

Number(value).toLocaleString('en');

2) Add a class to determine if it is negative or positive value (i.e. red color)

.enMoney::before {
    content:"$";
}
.negMoney {
    color:red;
}

See more detail here with the sample code and css:

http://www.ozkary.com/2014/04/format-currency-with-javascript-and-css.html

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
ozkary
  • 2,436
  • 1
  • 21
  • 20
  • Can't affect the middle thousand sepparators, but before and after a number is enough for the goal... – DavidTaubmann Dec 17 '16 at 23:37
  • document.querySelectorAll(".currency").forEach(e => { n = Number(e.innerHTML).toFixed(2); if (!isNaN(n)) e.innerHTML = n.toLocaleString(); }); – user3270784 Apr 14 '20 at 20:08
18

var number = 25153.3; console.log(number.toLocaleString()); /------

var number = 25153.3;
result="$ " + number.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2})
console.log(result);

console.log();
//---------------------------------------------------

// request a currency format
console.log(number.toLocaleString('us-US', { style: 'currency', currency: 'USD' }));
// → $ 251,52.30 

console.log(number.toLocaleString('de-DE', { style: 'currency', currency: 'EUR' }));
// → 25.152,30 €

// the Japanese yen doesn't use a minor unit
console.log(number.toLocaleString('ja-JP', { style: 'currency', currency: 'JPY' }))
// → ¥251,53
Timothy Nwanwene
  • 995
  • 11
  • 18
4

If you're asking about number formatting in CSS (that is, parsing a number from a string and then formatting it with thousands separator, decimal separator, fixed decimal digits number etc), then no, it is impossible in CSS, and this is not what CSS was designed for.

If you want to do any formatting, then you'd better to use XSLT. For example:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="span[@class='dollars']">
        <span>
            <xsl:text>$</xsl:text>
            <xsl:value-of select="format-number(current(), '###,###.00')"/>
        </span>
    </xsl:template>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>
penartur
  • 9,792
  • 5
  • 39
  • 50
  • 81
    "and this is not what CSS was designed for"... I would reserve judgement about what CSS was designed for. Pushing common functionality into the browser is exactly what technologies like CSS were designed for. There was a time when "responding to screen sizes" was "not something CSS was designed for" Also: http://wiki.csswg.org/ideas/content-formatting – umassthrower Mar 19 '13 at 22:41
  • 8
    aha - so *that's* what XSLT was designed for ;-) – Simon_Weaver Feb 10 '15 at 09:21
  • 41
    "Formatting a number" is a function of presentation, and that's *exactly* what CSS was designed for. – Aaron Cicali Feb 12 '16 at 17:37
-2

Well, this doesn't fit your own use case unfortunately, and it's fairly obvious, but you could do this for integer numbers from -999 to 999.

.currency:before{ content:'$'; }
.currency:after{ content: '.00'; }
<span class="currency">789</span>

Then, a possible, annoying, solution if you're working server side, is to convert your number to a reversed string and loop over each character. If you really wanted you could place the characters into li's and css could then do the formatting you wanted as follows. However this is incredibly pointless as you may as well simply author the string at that point.

.currency li:before{ content: ' ,';}
.currency li:first-child:before{ content:'$' !important; }
.currency *{ display: inline-block; }
.currency, .currency > *{ display: inline-block; }
.currency:after{ content: '.00'; }
<ul class="currency"><li>123</li><li>456</li><li>789</li></ul> 
<ul class="currency"><li>456</li><li>789</li></ul> 
<ul class="currency"><li>789</li></ul> 

For an even deeper dive into pointless effort, you could prepend a

<style> .currency:after{ content: '.00'; } </style>

above the <ul>, allowing your script to change the decimal value in CSS, lol

Still, if you were to cave and use JavaScript, then the CSS may actually be somewhat useful. You can output a plain int or double (any precision) and just have JS break it into <li>s.

  • Good idea. But not the right solution. Because if your integer increases say to 100,000 you won't have the comma – 13garth Feb 25 '20 at 08:46
  • @GarthBaker hmmm, I'm confused why that would be the case since it works with 6 and 9 digit numbers in the second code snippet. Am I misunderstanding you? While I can easily understand people disliking this solution, as I hate it and would not use it, logically grouping the groups of digits for formatting is rather semantic to the goal – That Realty Programmer Guy Feb 25 '20 at 19:55
  • I'm not exactly sure what you saying. making a number like this
    • 123
    • 456
    • 789
    is ridiculous no one is going to go through such a ridiculous process. And because the decimals are been set with css there is room for error. this solution is a dismal hack. CSS is not the correct solution for this problem.
    – 13garth Feb 27 '20 at 20:30
  • mmmm, not the correct solution for every instance of the problem, but it IS the ideal solution in some scenarios. as per room for error, you are skipping some step in logic. it is trivial to transform a `1234567890` to this with 0 chance of error. Though it's fascinating how much more aggressive you became rather than correcting your mistake about 100,000 – That Realty Programmer Guy Feb 29 '20 at 18:55