69

I have an HTML table with a large number of rows, and I need to right align one column.

I know the following ways,

<tr><td>..</td><td>..</td><td align='right'>10.00</td><tr>

and

<tr><td>..</td><td>..</td><td class='right-align-class'>10.00</td><tr>

In both the methods, I have to repeat the align or class parameter on every <tr> tag. (If there are 1000 rows, I have to put align='right' or class='right-align-class' 1000 times.)

Is there an efficient way to do this? *Is there a direct way to say, align the third column in all rows to the right?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Palani
  • 8,962
  • 11
  • 53
  • 62
  • 3
    I suggest whatever is generating the HTML should be adding the right alignment to the output so that you don't have to type it 1000 times. If you have a thousand rows in a table it should be generated programmatically to begin with. This means you only have to change the alignment in the template or the code that generates the html, and you only do this once. This isn't exactly an answer to your question. But I know I often find I am doing something not quite like others that leads me to ask questions I wouldn't even have if one layer deeper I was doing things differently. Look one layer deepr – Jason Jan 22 '19 at 18:55

13 Answers13

79

Updated (after 10+ years!): Yes! It's possible to do this more efficiently now, with widespread practical browser support, using the nth-child selector.

HTML:

<table>
<tr>
<td>foo 1</td>
<td>bar 1</td>
<td>baz 1</td>
<td>bap 1</td>
</tr>
<tr>
<td>foo 2</td>
<td>bar 2</td>
<td>baz 2</td>
<td>bap 2</td>
</tr>
</table>

CSS:

table td { width: 20em; border: 1px solid black; }
table td:nth-child(3) { text-align: end; }

https://jsfiddle.net/mv83qszL/

Previously, it was not possible to do this, because browser support used to be inconsistent and hit-or-miss, especially with regard to newer CSS features. This made it impossible to use more elegant, efficient solutions -- and required lots of repetitive markup and class definitions in order to get consistent results across the audience's browser space.

See the edit history for the previous version of this answer.

Matt Howell
  • 15,750
  • 7
  • 49
  • 56
  • Why is this getting upvoted? He just repeated the same method the OP already knew about. – cdmckay Aug 26 '09 at 18:44
  • But it's not more efficient. Having to add a class to each `td` is the most compatible way, but not the most efficient. The most efficient way would be to use the `nth-child(3)` selector. – cdmckay Aug 27 '09 at 03:11
  • There's also the sibling selector solution, which only requires you add a class to the table and is supported by all browsers other than IE6. That is also a more efficient solution (especially if the code is maintained by hand). – cdmckay Aug 27 '09 at 15:32
  • Where are all these 10% of the population who uses IE6? I don't think I ever met one of them. –  Jan 16 '14 at 23:37
  • "IE6 is still 10% of the browsing population -- and you still have to contend with that" No.... I don't. People on IE6 deserve to be miserable. – nathanchere Sep 10 '15 at 10:30
  • 5
    @MattHowell: This awesome answer looks time-sensitive and outdated (your links disprove your text, the 40% figure which is a key point in your argument), could you refresh it ? – Nikana Reklawyks Dec 21 '15 at 12:19
  • This is still relevant, in fact it is no more or less efficient than decrying .css altogether and just using "align". OP does not disambiguate what is meant by efficient. I find it hard to imagine all these rows are not written by a preprocessor (php say). Align should be supported in perpetuity across the board for backwards compatibility. After a while the .css bloat can mean it is more efficient to serve an image ! – mckenzm Dec 26 '16 at 22:06
17

You could use the nth-child pseudo-selector. For example:

table.align-right-3rd-column td:nth-child(3)
{
  text-align: right;
}

Then in your table do:

<table class="align-right-3rd-column">
  <tr>
    <td></td><td></td><td></td>
    ...
  </tr>
</table>

Unfortunately, this only works in Firefox 3.5. However, if your table only has three columns, you could use the sibling selector, which has much better browser support. Here's what the style sheet would look like:

table.align-right-3rd-column td + td + td
{
  text-align: right;
}

This will match any column preceded by two other columns.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
cdmckay
  • 31,832
  • 25
  • 83
  • 114
9

If it's always the third column, you can use this (assuming table class of "products"). It's kind of hacky though, and not robust if you add a new column.

table.products td+td+td {
  text-align: right;
}
table.products td,
table.products td+td+td+td {
  text-align: left;
}

But honestly, the best idea is to use a class on each cell. You can use the col element to set the width, border, background or visibility of a column, but not any other properties. Reasons are discussed here.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
DisgruntledGoat
  • 70,219
  • 68
  • 205
  • 290
4

Looking through your exact question to your implied problem:

Step 1: Use the class as you described (or, if you must, use inline styles).

Step 2: Turn on GZIP compression.

It works wonders ;)

This way, GZIP removes the redundancy for you (over the wire, anyway) and your source remains standards compliant.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
John Gietzen
  • 48,783
  • 32
  • 145
  • 190
  • 2
    +1 for turning on GZIP. Seriously, this answer does not warrant 3 downvotes. Other less compatible answer should be voted down instead. – Adrian Godong Aug 26 '09 at 10:10
  • I wasn't advocating inline styles as the best way by any means. It was just one possibility on how to solve the problem. – John Gietzen Aug 26 '09 at 11:55
  • 1
    +1, downvoters explain? This is not any different than the top answer at the moment, and on top of that it is the only sensible solution. – Jan Zich Aug 26 '09 at 14:58
  • Whether it's "sensible" depends on the goal: the original question sounded like it was about semantic repetition, not bandwidth, so GZIP sounds irrelevant to me. The FAQ says downvotes on SO are for "off topic or incorrect" answers. IMHO, simply being "less compatible" should not be grounds for downvoting, but GZIP is borderline offtopic. (FWIW, I did not downvote anything on this page.) (Goodbye, karma! I barely knew ye.) –  Aug 26 '09 at 15:53
  • @John: Maybe you should *bold* the "or" word on your #1. @Ken: GZIPing will make it more efficient than *not* GZIPing (which is the one of the question asked). – Adrian Godong Aug 26 '09 at 21:53
2

A number of years ago (in the IE only days) I was using the <col align="right"> tag, but I just tested it and and it seems to be an IE only feature:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <title>Test</title>
</head>
<body>
    <table width="100%" border="1">
        <col align="left" />
        <col align="left" />
        <col align="right" />
        <tr>
            <th>ISBN</th>
            <th>Title</th>
            <th>Price</th>
        </tr>
        <tr>
            <td>3476896</td>
            <td>My first HTML</td>
            <td>$53</td>
        </tr>
    </table>
</body>
</html>

The snippet is taken from www.w3schools.com. Of course, it should not be used (unless for some reason you really target the IE rendering engine only), but I thought it would be interesting to mention it.

Edit:

Overall, I don't understand the reasoning behing abandoning this tag. It would appear to be very useful (at least for manual HTML publishing).

Jan Zich
  • 14,993
  • 18
  • 61
  • 73
  • 1
    Is anybody actually reading my answer? I did not say it should be used in real life for real website. It was a historical remark, and I suggested using this only if targeting IE rendering engine (not necessarily for webpages). – Jan Zich Aug 26 '09 at 15:03
  • 1
    Firefox didn't drop support in 3.5; it never had support for this. –  Aug 26 '09 at 15:47
  • 2
    I am reading this 12 years after :-) are you still alive? I find your historical note very important as nowadays standards lack support of table columns semantics, forcing web designers to bastardize design, so I added more notes about the past (and hopefully the future) in my answer. – Jan Turoň Mar 02 '21 at 22:48
  • Jan Turoň: [Probably not](https://stackoverflow.com/users/15716/jan-zich): *"Last seen more than 7 years ago"*. That usually means an abandoned or lost account. – Peter Mortensen Mar 12 '23 at 17:52
1

HTML5 messed up the col attribute functionality...

It is really uncool that HTML5 deprecated most of the col attributes and did not add the support for the style and class attributes. Modern browsers still holds support for its width attribute, but not for others. The width support will probably hold as it is used in table layout render algorithm.

...which can be fixed by defining CSS class series...

To achieve similar functionality without the need of editing every row, it can be achieved by defining

.right-1 td:nth-child(1),
.right-2 td:nth-child(2),
.right-3 td:nth-child(3),
.right-4 td:nth-child(4),
.right-5 td:nth-child(5), ...
  { text-align: right; }

which can be a single line with help of some CSS preprocessor / generator, but still acceptable without it as most web tables has reasonable number of columns. Then to right-align the third column, you can just

<table class="right-3">
...
</table>

...but it is just a poor hack :-(

CSS classes should hold the semantics. If they imply particular styles (like in the example above), it is semantically just legalized inline style attribute, merging the HTML with the design (CSS should separate it). This is what Bootstrap styles do, and this is what you should avoid if possible.

Jan Turoň
  • 31,451
  • 23
  • 125
  • 169
0

This doesn't work in Internet Explorer 6, which may be an issue, but it'll work in Internet Explorer 7 (or later), Firefox, Safari, etc. It'll align the third column right and all of the subsequent columns left.

td + td + td { text-align: right; }
td + td + td + td { text-align: left; }
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Eifion
  • 5,403
  • 2
  • 27
  • 27
0

If you have only two "kinds" of column styles - use one as TD and one as TH. Then, declare a class for the table and a sub-class for that table's THs and TDs. Then your HTML can be super efficient.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
John Marno
  • 11
  • 3
0

The current draft of CSS Selectors Level 4 specifies structural selectors for grids. If implemented, we will be able to do things like:

th.price,
th.price || td {
    text-align: right;
}

Of course, that doesn't help us today -- the other answers here offer enough practical advice for that.

Chris
  • 9,994
  • 3
  • 29
  • 31
0

Following up on this excellent description, here's a complete solution for 12 columns, and includes both <th> and <td>:


/* table column text alignment */
.col-r-1 td:nth-child(1),
.col-r-1 th:nth-child(1),
.col-r-2 td:nth-child(2),
.col-r-2 th:nth-child(2),
.col-r-3 td:nth-child(3),
.col-r-3 th:nth-child(3),
.col-r-4 td:nth-child(4),
.col-r-4 th:nth-child(4),
.col-r-5 td:nth-child(5),
.col-r-5 th:nth-child(5),
.col-r-6 td:nth-child(6),
.col-r-6 th:nth-child(6),
.col-r-7 td:nth-child(7),
.col-r-7 th:nth-child(7),
.col-r-8 td:nth-child(8),
.col-r-8 th:nth-child(8),
.col-r-9 td:nth-child(9),
.col-r-9 th:nth-child(9),
.col-r-10 td:nth-child(10),
.col-r-10 th:nth-child(10),
.col-r-11 td:nth-child(11),
.col-r-11 th:nth-child(11),
.col-r-12 td:nth-child(12),
.col-r-12 th:nth-child(12) {
  text-align: right;
}

.col-l-1 td:nth-child(1),
.col-l-1 th:nth-child(1),
.col-l-2 td:nth-child(2),
.col-l-2 th:nth-child(2),
.col-l-3 td:nth-child(3),
.col-l-3 th:nth-child(3),
.col-l-4 td:nth-child(4),
.col-l-4 th:nth-child(4),
.col-l-5 td:nth-child(5),
.col-l-5 th:nth-child(5),
.col-l-6 td:nth-child(6),
.col-l-6 th:nth-child(6),
.col-l-7 td:nth-child(7),
.col-l-7 th:nth-child(7),
.col-l-8 td:nth-child(8),
.col-l-8 th:nth-child(8),
.col-l-9 td:nth-child(9),
.col-l-9 th:nth-child(9),
.col-l-10 td:nth-child(10),
.col-l-10 th:nth-child(10),
.col-l-11 td:nth-child(11),
.col-l-11 th:nth-child(11),
.col-l-12 td:nth-child(12),
.col-l-12 th:nth-child(12) {
  text-align: left;
}

To use (this would right-align the 2nd and 3rd columns):

<table className="table text-left col-r-2 col-r-3">
    <thead>
        <tr>
            <th>Widget</th>
            <th>Quantity</th>
            <th>Price</th>
            <th>Comments</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th>Sprocket</th>
            <th>100</th>
            <th>$4.57</th>
            <th>Works well</th>
        </tr>
        <tr>
            <th>Rocket fuel</th>
            <th>7</th>
            <th>$114.57</th>
            <th>Spicy</th>
        </tr>
    </tbody>
</table>

Using Bootstrap, you can globally align the table with text-right or text-left, and then tweak which columns don't match the whole table; I'd imagine other CSS frameworks would have something similar.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
shapiromatron
  • 569
  • 6
  • 11
-1

You really want:

<col align="right"/>

But it looks like Gecko doesn't support this yet: it's been an open bug for over a decade.

(Geez, why can't Firefox have decent standards support like Internet Explorer 6?)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • 2
    Align is a deprecated attribute so Firefox has no reason to support it. –  Aug 26 '09 at 06:55
  • 1
    Hmm yes, but what was the reason for its deprecation? It seems to be useful. If not the align attribute, it would be useful to style it using CSS. I know that it could possibly lead to some precedence issues (because nowhere else an element can transfer styles to other element), but still ... – Jan Zich Aug 26 '09 at 10:09
  • 1
    There are only 4 properties allowed on columns, see http://stackoverflow.com/questions/1119106/why-is-styling-table-columns-not-allowed – DisgruntledGoat Aug 26 '09 at 12:07
  • Those 4 are the only *CSS* properties. HTML4.01 allows more document attributes on the col tag. For example, "span" (which would be a little silly to put in CSS). And "align" is deprecated in 'table' and 'caption', but I don't see anywhere that says it's deprecated for 'col'. –  Aug 26 '09 at 15:37
  • 2
    "Geez, why can't Firefox have decent standards support like IE6?)" HAHA! fantastic comment! So untrue but indeed funny! – Jesper Rønn-Jensen Sep 08 '09 at 08:10
-2

Use jQuery to apply class to all 'tr's unobtrusively:

$(”table td”).addClass(”right-align-class″);

Use enhanced filters on td in case you want to select a particular td.

See jQuery

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nrj
  • 6,723
  • 7
  • 46
  • 58
-2

The <colgroup> and <col> tags that lives inside tables are designed for this purpose. If you have three columns in your table and want to align the third, add this after your opening <table> tag:

 <colgroup>
     <col />
     <col />
     <col class="your-right-align-class" />
 </colgroup>

along with the requisite CSS:

.your-right-align-class { text-align: right; }

From the W3C:

Definition and Usage

  • The <col> tag defines attribute values for one or more columns in a table.

  • The <col> tag is useful for applying styles to entire columns, instead of repeating the styles for each cell, for each row.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
supertrue
  • 2,049
  • 5
  • 30
  • 49
  • For some reason this doesn't seem to work for HTML email in GMail. – jpierson Mar 08 '12 at 00:48
  • Email clients have limited support for many kinds of styling, including and especially non-inline styles—e.g., styling based on classes. To work in all email clients, the individual TDs may need `style="text-align: right;"` or `align="right"`. – supertrue Aug 15 '12 at 15:24
  • 2
    This solution doesn't work. Please refer to http://stackoverflow.com/questions/1238115/using-text-align-center-in-colgroup for better explanation. – Custodio Oct 09 '13 at 15:41
  • 1
    Agreed... this solution doesn't work even when not associated with email clients. Did you actually test it before you posted it? – Jeff Moden Jul 20 '14 at 04:43
  • 1
    `colgroup` would be ideal, but in HTML5 it got less useful. – Maxim Egorushkin Sep 12 '16 at 15:35