How to right align numbers in the center of a table cell?

Viewed 8372

Given a table with a column that contains numbers, I'd like to position them in the center.

But, I'd like to right-align the numbers as well!

table {
  border: 1px solid black;
}

th {
  width: 200px;
}

td {
  text-align: center;
}
<table>
  <thead>
    <tr>
      <th>Amount</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>45</td>
    </tr>
    <tr>
      <td>2</td>
    </tr>
    <tr>
      <td>18923538273</td>
    </tr>
    <tr>
      <td>9823</td>
    </tr>
  </tbody>
</table>

Outputs:

enter image description here

Desired output:

enter image description here

Note: The table cell width should be constant (200px), regardless of the numbers. For example, if all numbers are 0, they all should be in the center of the table:

enter image description here

Also:

  • You are allowed to modify the content of the <td>s, but there should be one number per <tr>.
  • CSS only, please.
8 Answers

TL;DR:

table {
  border: 1px solid black;
  width: 200px;
}
td {
  text-align: right;
  min-width: 10px;
}
td:first-child, td:last-child {
  width: 50%;
}

... and adding an extra column before and after the existing one. jsFiddle here.


Initial answer:

Considering your markup,

td {
  text-align: right;
  border-left:7rem solid transparent;
  border-right:7rem solid transparent;
}

... should do it.

table {
  border: 1px solid black;
}

th {
  width: 200px;
}

td {
  text-align: right;
  border-left:7rem solid transparent;
  border-right:7rem solid transparent;
}
<table>
  <thead>
    <tr>
      <th>Amount</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>45</td>
    </tr>
    <tr>
      <td>2</td>
    </tr>
    <tr>
      <td>18923538273</td>
    </tr>
    <tr>
      <td>9823</td>
    </tr>
  </tbody>
</table>

Any other solution involves changing the markup (you need to add inner elements inside <td>s, give them smaller width than the <td>, and right align their text). You can do it by modifying the HTML source or on the fly, using JavaScript.


After a good number of tries, the only reliable solution I found (implying markup modification and no JavaScript), was to add additional columns in the table, relying on the table's ability to line up all the cells in a column.

I updated the snippet below so that the column occupies the minimum necessary width, based on most wide number and right-aligns all cells based on resulting width width. This means that when all values are 0, the entire row of values are centered. Here it is:

table {
  border: 1px solid black;
  width: 200px;
}
td {
  text-align: right;
  min-width: 10px;
}
td:first-child, td:last-child {
  width: 50%;
}


/* just stacking tables side by side, not part of solution */
table {      
  float: left;
  width: 200px;
  margin-right: 7px;
}
body { overflow-y: hidden;}
<table>
  <thead>
    <tr>
      <th colspan="3">Amount</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td></td>
      <td>45</td>
      <td></td>
    </tr>
    <tr>
      <td></td><td>2</td><td></td>
    </tr>
    <tr>
      <td></td><td>0</td><td></td>
    </tr>
    <tr>
      <td></td><td>1234</td><td></td>
    </tr>
  </tbody>
</table>
<table>
  <thead>
    <tr>
      <th colspan="3">Amount</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td></td>
      <td>0</td>
      <td></td>
    </tr>
    <tr>
      <td></td><td>2</td><td></td>
    </tr>
    <tr>
      <td></td><td>1</td><td></td>
    </tr>
    <tr>
      <td></td><td>4</td><td></td>
    </tr>
  </tbody>
</table>
<table>
  <thead>
    <tr>
      <th colspan="3">Amount</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td></td>
      <td>44</td>
      <td></td>
    </tr>
    <tr>
      <td></td><td>0</td><td></td>
    </tr>
    <tr>
      <td></td><td>1155</td><td></td>
    </tr>
    <tr>
      <td></td><td>1234548775564</td><td></td>
    </tr>
  </tbody>
</table>

Updated based on an edit of the question and a few comments

In a comment you wrote "In the desired outcome, the cell width stays the same (200px) as numbers change".

In another comment you wrote "...my numbers are links and I want them to occupy the full cell width".

Given those requirements, the only CSS based solution I can find is, where one use CSS Table instead of <table> elements, an anchor a element displayed as table-row, making the full width clickable without adding an event handler, and for the centering, using pseudo elements to puch the numbers to the middle.

Stack snippet

.table {
  display: table;
  border: 1px solid black;
}
.tr {
  display: table-row;
  text-decoration: none;
  color: black;
}
.tr span {
  display: table-cell;
  width: 200px;
}
a.tr {
  text-align: right;
}
.tr::before, .tr::after {
  content: '';
  display: table-cell;
  width: 50%;
}
<div class="table">
  <div class="thead">
    <span class="tr">
      <span>Amount</span>
    </span>
  </div>
  <div class="tbody">
    <a href="#1" class="tr">
      <span>45</span>
    </a>
    <a href="#2" class="tr">
      <span>2</span>
    </a>
    <a href="#3" class="tr">
      <span>18923538273</span>
    </a>
    <a href="#4" class="tr">
      <span>9823</span>
    </a>
  </div>
</div>

<div class="table">
  <div class="thead">
    <span class="tr">
      <span>Amount</span>
    </span>
  </div>
  <div class="tbody">
    <a href="#1" class="tr">
      <span>0</span>
    </a>
    <a href="#2" class="tr">
      <span>0</span>
    </a>
    <a href="#3" class="tr">
      <span>0</span>
    </a>
    <a href="#4" class="tr">
      <span>0</span>
    </a>
  </div>
</div>

_____________________________________________________________________________

This is my first answer, which I will leave, as there might be someone that can make use of it as is.

One simple way to accomplish that is to simply nest a table for the values, center it using auto margin and right align its td's content.

This way you will get pretty much the exact same behavior as with your original markup, but get a better control of the values alignment.

Stack snippet

table {
  border: 1px solid black;
}

th {
  width: 200px;
}

table table {
  border: none;
  margin: 0 auto;
}

table table td {
  text-align: right;
}
<table>
  <thead>
    <tr>
      <th>Amount</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>
        <table>
          <tr>
            <td>45</td>
          </tr>
          <tr>
            <td>2</td>
          </tr>
          <tr>
            <td>18923538273</td>
          </tr>
          <tr>
            <td>9823</td>
          </tr>
        </table>
      </td>
    </tr>
  </tbody>
</table>

<table>
  <thead>
    <tr>
      <th>Amount</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>
        <table>
          <tr>
            <td>0</td>
          </tr>
          <tr>
            <td>0</td>
          </tr>
          <tr>
            <td>0</td>
          </tr>
          <tr>
            <td>0</td>
          </tr>
        </table>
      </td>
    </tr>
  </tbody>
</table>


You can of course use div's instead of a table, displayed as inline block or inline flex column.

Inline block

table {
  border: 1px solid black;
}

th {
  width: 200px;
}

td {
  text-align: center;
}

td > div {
  display: inline-block;
}

td > div > div {
  text-align: right;
}
<table>
  <thead>
    <tr>
      <th>Amount</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>
        <div>
          <div>45</div>
          <div>2</div>
          <div>18923538273</div>
          <div>9823</div>
        </div>
      </td>
    </tr>
  </tbody>
</table>

<table>
  <thead>
    <tr>
      <th>Amount</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>
        <div>
          <div>0</div>
          <div>0</div>
          <div>0</div>
          <div>0</div>
        </div>
      </td>
    </tr>
  </tbody>
</table>

Inline flex column

table {
  border: 1px solid black;
}

th {
  width: 200px;
}

td {
  text-align: center;
}

td > div {
  display: inline-flex;
  flex-direction: column;
}

td > div > div {
  text-align: right;
}
<table>
  <thead>
    <tr>
      <th>Amount</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>
        <div>
          <div>45</div>
          <div>2</div>
          <div>18923538273</div>
          <div>9823</div>
        </div>
      </td>
    </tr>
  </tbody>
</table>

<table>
  <thead>
    <tr>
      <th>Amount</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>
        <div>
          <div>0</div>
          <div>0</div>
          <div>0</div>
          <div>0</div>
        </div>
      </td>
    </tr>
  </tbody>
</table>

make text-align:right and padding-right:5emin td css selector

table {
  border: 1px solid black;
}

th {
  width: 200px;
}

td {
  text-align: right;
  padding-right: 4em;
}
<table>
  <thead>
    <tr>
      <th>Amount</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>45</td>
    </tr>
    <tr>
      <td>2</td>
    </tr>
    <tr>
      <td>18923538273</td>
    </tr>
    <tr>
      <td>9823</td>
    </tr>
  </tbody>
</table>

<style>
table {
border: 1px solid black;
}

th {
width: 200px;
}
td {
text-align: center;
float:right; <!--added this-->
margin-right:50px; <!-- and this-->
}
</style>

I added float:right in td adjust the margin-right value to your desired value;

One option is to change the display property for td elements to block

You can then set a max-width to bring td elements to the center of tr elements.

Once that's done you set the text-align property to right for td elements to make the numbers start from the right hand side.

table {
  border: 1px solid black;
}

th {
  width: 200px;
}

td {
  display: block;
  max-width: 70%;
  text-align: right;
}
<table>
  <thead>
    <tr>
      <th>Amount</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>45</td>
    </tr>
    <tr>
      <td>2</td>
    </tr>
    <tr>
      <td>18923538273</td>
    </tr>
    <tr>
      <td>9823</td>
    </tr>
  </tbody>
</table>

Wrap your numbers with element(span) inside the td and add the text align right styles on it.

table {
  border: 1px solid black;
}

th {
  width: 200px;
}

td {
  text-align: center;
}

td span {
  width: 150px;
  text-align: right;
  background: beige;
  display: inline-block;
}
<table>
  <thead>
    <tr>
      <th>Amount</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><span>45</span></td>
    </tr>
    <tr>
      <td><span>2</span></td>
    </tr>
    <tr>
      <td><span>18923538273</span></td>
    </tr>
    <tr>
      <td><span>9823</span></td>
    </tr>
  </tbody>
</table>

        .table {
            display: flex;
            align-items: center;
            justify-content: center;
            width: 300px;
            background-color: red;
            flex-direction: column;
        }
        div {
            text-align: right;
        }
<body>
    <div class='table'>
        <div>
            <div>1</div>
            <div>1111111</div>
            <div>1111111111111</div>
        </div>
    </div>
</body>

text-align :right ----> pulls the text into right end

padding-right: 50% or padding-left : 50% ----> add space from the right or left to center

use 45 - 49 percentage in padding to make a crisp center alignment depends on your requirement

table {
  border: 1px solid black;
}

th {
  width: 200px;
}

td {
  text-align: right;
  padding-right: 50%;
}
<table>
  <thead>
    <tr>
      <th>Amount</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>45</td>
    </tr>
    <tr>
      <td>2</td>
    </tr>
    <tr>
      <td>18923538273</td>
    </tr>
    <tr>
      <td>9823</td>
    </tr>
  </tbody>
</table>

Related