161

Is it possible to format numbers with CSS? That is: decimal places, decimal separator, thousands separator, etc.

Mir-Ismaili
  • 10,843
  • 5
  • 65
  • 90
Don
  • 16,223
  • 11
  • 59
  • 96
  • 73
    You can't but you really should be able to. After all, 50,000 or 50000 or 50,000.00 are all the same 'data' they're just presented differently which is what CSS is for. – punkrockbuddyholly Dec 30 '11 at 09:57
  • 4
    @MrMisterMan: There are some ideas being tossed around here: http://wiki.csswg.org/ideas/content-formatting#numbers I'm probably going to be harassed and accused of citing "specifications" and getting everyone's hopes up though. And for me, I'm curious to know how non-numeric text would be handled here. – BoltClock Dec 30 '11 at 10:52
  • 3
    While I do agree that this would be nice to have, the number is embedded inside an otherwise localized page. I.e., the rest of the page is English, Chinese or whatever other language, and the numbers should IMO conform to that localization. Why should they be localized separately from the rest of the page...? – deceze Feb 07 '12 at 09:33
  • @deceze: You are right. It should be possible to have "localization CSS"s – Don Feb 07 '12 at 10:54
  • 1
    adding JS option using Intl.NumberFormat [mdn-ref:](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat) – Joshua Baboo May 31 '17 at 07:25
  • 1
    @punkrockbuddyholly; Also localizations are needed. For example, `۵۰٬۰۰۰` (Persian) and `٥٠٬٠٠٠` (Arabic) are the same data (`50,000`). – Mir-Ismaili May 05 '22 at 14:00

14 Answers14

32

The CSS working group has publish a Draft on Content Formatting in 2008. But nothing new right now.

Yoann
  • 4,817
  • 1
  • 27
  • 47
30

Unfortunately, it's not possible with CSS currently, but you can use Number.prototype.toLocaleString(). It can also format for other number formats, e.g. latin, arabic, etc.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString

CascadiaJS
  • 2,111
  • 2
  • 25
  • 45
  • 2
    The most modern and elegant approach, and since it is still impossible to achieve with CSS as of now, should be the number 1 answer! – FMA Jan 12 '19 at 12:40
  • It is being broken on RTL layouts. I format numbers serverside and put them to markup, so they get delivered to browser as (for example, two thousands five hundreds) `2 500`. And at Arabic versions (with `body.rtl_ { direction: rtl; }`) this example all of a sudden turns to `500 2`. – Alex Naidovich Dec 15 '21 at 12:55
  • @AlexNaidovich Thanks for the info. This seems like a bug. You should report it. If you're using Chrome, it is based on the Chromium project and you can [report bugs here](https://www.chromium.org/for-testers/bug-reporting-guidelines) – CascadiaJS Jan 06 '22 at 20:23
  • @CascadiaJS Thanks for reply, but I found out that this is actually not a bug. RTL layout by nature changes word order, so it treats whitespaces respectively. So there are minor cases (like my example above) when I need to explicitly set `direction: ltr;`. To conclude - the answer we are commenting on is totally OK. – Alex Naidovich Jan 18 '22 at 15:22
24

Well, for any numbers in Javascript I use next one:

var a = "1222333444555666777888999";
a = a.replace(new RegExp("^(\\d{" + (a.length%3?a.length%3:0) + "})(\\d{3})", "g"), "$1 $2").replace(/(\d{3})+?/gi, "$1 ").trim();

and if you need to use any other separator as comma for example:

var sep = ",";
a = a.replace(/\s/g, sep);

or as a function:

function numberFormat(_number, _sep) {
    _number = typeof _number != "undefined" && _number > 0 ? _number : "";
    _number = _number.replace(new RegExp("^(\\d{" + (_number.length%3? _number.length%3:0) + "})(\\d{3})", "g"), "$1 $2").replace(/(\d{3})+?/gi, "$1 ").trim();
    if(typeof _sep != "undefined" && _sep != " ") {
        _number = _number.replace(/\s/g, _sep);
    }
    return _number;
}
  • 1
    Thanks. Not a pure CSS solution, but does the task! – Don Feb 25 '15 at 04:13
  • 1
    I like it. But I needed to also convert the number to a string before the replace. You can not do a replace on a number. – Mardok May 27 '16 at 18:47
  • before calling `_number.replace` we have to make sure it is a string like this `_number = typeof _number != "undefined" && _number > 0 ? String(_number) : "";` or else you will get an error `_number.replace` is not defined or not a function – Shalkam Jul 01 '17 at 15:28
  • 6
    why not simply use: (123456789).toLocaleString('en-GB') or the like? – Joehannes Nov 22 '17 at 22:50
15

Probably the best way to do so is combo of setting a span with a class denoting your formatting then use Jquery .each to do formatting on the spans when the DOM is loaded...

Ross
  • 1,625
  • 1
  • 17
  • 22
9

No, you have to use javascript once it's in the DOM or format it via your language server-side (PHP/ruby/python etc.)

mreq
  • 6,204
  • 4
  • 33
  • 56
  • 7
    The format of numbers is a content matter, like the text of the content or other notational issues (e.g., date notations, which are language-dependent). So formatting numbers is localization and should be handled when content is generated. Doing it in JavaScript makes sense for the part of content that is JavaScript-generated. – Jukka K. Korpela Dec 30 '11 at 10:01
  • I fully agree with that. That's why I wrote it in my answer. Should've probably put more stress on it. – mreq Dec 30 '11 at 20:28
  • It can be either content or presentation. Take CSS `rtl`, that shows the same content in a different way: should it also be treated server-side? – Don Feb 01 '18 at 08:29
8

Not an answer, but perhpas of interest. I did send a proposal to the CSS WG a few years ago. However, nothing has happened. If indeed they (and browser vendors) would see this as a genuine developer concern, perhaps the ball could start rolling?

itpastorn
  • 2,897
  • 1
  • 20
  • 23
7

If it helps...

I use the PHP function number_format() and the Narrow No-break Space ( ). It is often used as an unambiguous thousands separator.

echo number_format(200000, 0, "", " ");

Because IE8 has some problems to render the Narrow No-break Space, I changed it for a SPAN

echo "<span class='number'>".number_format(200000, 0, "", "<span></span>")."</span>";
.number SPAN{
    padding: 0 1px; 
}
DanielBlazquez
  • 1,007
  • 1
  • 12
  • 21
  • Unfortunately this is server side, there is a slight CPU hit, we need an html/css edit mask ability. Dressing and rendering should be client side unless we are serving a pdf ? – mckenzm Dec 30 '16 at 02:09
3

I don't think you can. You could use number_format() if you're coding in PHP. And other programing languages have a function for formatting numbers too.

Florin Frătică
  • 577
  • 4
  • 7
  • 13
  • BAD practice to alter data for display purposes in the "backend". – Buffalo Jan 28 '19 at 05:35
  • What is the problem with serving a page in Spanish (or another language) with the numbers formatted in that language? I don't think it's a bad practice at all. – DanielBlazquez May 07 '21 at 18:59
2

Another solution with pure CSS+HTML and the pseudo-class :lang().

Use some HTML to mark up the number with the classes thousands-separator and decimal-separator:

<html lang="es">
  Spanish: 1<span class="thousands-separator">200</span><span class="thousands-separator">000</span><span class="decimal-separator">.</span>50
</html>

Use the lang pseudo-class to format the number.

/* Spanish */
.thousands-separator:lang(es):before{
  content: ".";
}
.decimal-separator:lang(es){
  visibility: hidden;
  position: relative;
}
.decimal-separator:lang(es):before{
  position: absolute;
  visibility: visible;
  content: ",";
}

/* English and Mexican Spanish */
.thousands-separator:lang(en):before, .thousands-separator:lang(es-MX):before{
  content: ",";
}

Codepen: https://codepen.io/danielblazquez/pen/qBqVjGy

DanielBlazquez
  • 1,007
  • 1
  • 12
  • 21
2

You cannot use CSS for this purpose. I recommend using JavaScript if it's applicable. Take a look at this for more information: JavaScript equivalent to printf/string.format

Also As Petr mentioned you can handle it on server-side but it's totally depends on your scenario.

Community
  • 1
  • 1
Qorbani
  • 5,622
  • 2
  • 37
  • 46
1

You could use Jstl tag Library for formatting for JSP Pages

JSP Page
//import the jstl lib
<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt" %>

<c:set var="balance" value="120000.2309" />
<p>Formatted Number (1): <fmt:formatNumber value="${balance}" 
        type="currency"/></p>
<p>Formatted Number (2): <fmt:formatNumber type="number" 
        maxIntegerDigits="3" value="${balance}" /></p>
<p>Formatted Number (3): <fmt:formatNumber type="number" 
        maxFractionDigits="3" value="${balance}" /></p>
<p>Formatted Number (4): <fmt:formatNumber type="number" 
        groupingUsed="false" value="${balance}" /></p>
<p>Formatted Number (5): <fmt:formatNumber type="percent" 
        maxIntegerDigits="3" value="${balance}" /></p>
<p>Formatted Number (6): <fmt:formatNumber type="percent" 
        minFractionDigits="10" value="${balance}" /></p>
<p>Formatted Number (7): <fmt:formatNumber type="percent" 
        maxIntegerDigits="3" value="${balance}" /></p>
<p>Formatted Number (8): <fmt:formatNumber type="number" 
        pattern="###.###E0" value="${balance}" /></p>

Result

Formatted Number (1): £120,000.23

Formatted Number (2): 000.231

Formatted Number (3): 120,000.231

Formatted Number (4): 120000.231

Formatted Number (5): 023%

Formatted Number (6): 12,000,023.0900000000%

Formatted Number (7): 023%

Formatted Number (8): 120E3

Mohammad Javed
  • 188
  • 1
  • 12
1

…A few years later…

I use this to format a number with a small space as thousands separator:

theNumber.toString().replaceAll(/(\d)(?=(?:\d\d\d)+$)/g, '$1\u202f')

It will insert a small space after each digit which is followed by a number of digits, where the digit count is a multiple of 3.

  • (\d) => A digit. In brackets to remember the digit

  • (?=) => Positiv look-ahead

  • (?:\d\d\d) => Three digits. Just grouped.

  • + => At least one group of three digits have to be present

  • $ => End of string/number

  • $1 => replaced by the remembered digit

  • \u202f => Unicode notation for a small blank

As pointed out: That's Javascript, not CSS.
Skeeve
  • 5,400
  • 2
  • 14
  • 21
0

Another js solution to improve the work of Skeeve:

<input type="text" onkeyup="this.value=this.value.toString().replaceAll(/[^\d]/g, '').replaceAll(/(\d)(?=(?:\d\d\d)+$)/g, '$1\u202f')" pattern="[0-9\s]*">
vacsati
  • 458
  • 6
  • 7
0

The closest thing I could find is the <input type="number" /> tag, which does do formatting in plain HTML but is also an input field. To make it look like plain text, you could use a bit of CSS.

Unfortunately I don't know how to fix the right margin without JavaScript or using a monospace font and set the width attribute server side.

HTML:

<p>In <input type="number" value="1.223" readonly="readonly" size="1" /> line</p>

CSS:

p {font-family: verdana;}
input {
  font-family: verdana;
  font-size: 16px;
}
input[readonly] {
  border: 0;
  padding: 0;
  margin: 0;
  min-width: 3em;
  font-size: 16px; 
}
/* Chrome, Safari, Edge, Opera */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
/* Firefox */
input[type=number] {
  -moz-appearance: textfield;
}
Code4R7
  • 2,306
  • 1
  • 16
  • 39