9

For explanation imagine a simple address. Written in a HTML paragraph with line breaks it would like this:

Street: Example Street 1
City: Vienna
Zip Code: 1010
Country: Austria

Most of the time that's completely okay, but sometimes I have to achieve the following output:

Street:   Example Street 1
City:     Vienna
Zip Code: 1010
Country:  Austria

My thoughts so far:

  1. Should be valid XHTML and work or degrade gracefully in all major browsers
  2. Using tags in a semantically correct way is strongly preferred
  3. Because of point two: I hope there's a better solution than tables
  4. The problem is not limited to addresses - would be useful in other situation too

How do you achieve this output (using HTML and/or CSS)?

Christoph Schiessl
  • 6,818
  • 4
  • 33
  • 45
  • I just don't feel that tables are the correct tool for the job. I don't believe you could call ONE address tabular data? – Christoph Schiessl Oct 12 '08 at 20:30
  • 1
    Tables are a great way to present data. The problem is, they are misused for almost anything and now they have a bad name. – Toon Krijthe Oct 12 '08 at 20:34
  • I don't deny that the problem could be nicely solved with tables. However, tables just don't feel right to me. Maybe I am just to pedantic - I don't know ;) – Christoph Schiessl Oct 12 '08 at 20:39
  • Lol, we all have our quirks ;-). – Toon Krijthe Oct 12 '08 at 20:44
  • 1
    @Christoph Schiessl, the clue is in the word "tab". It's a contraction of "tabulated", ie anything involving tabs is tabulated data and thus the best way to present it to the user is as a table. Anything else is biting off your nose to spite your face. – David Arno Oct 12 '08 at 21:07
  • Christoph has a point actually, multiple address would be data but one address? I suppose it's data whether it's on its own or as a collection. If you really wanted to you could use
     and tabs ;)
    – Ross Oct 12 '08 at 21:07
  • @Ross: That's exactly my point. I think only data consisting of multiple rows (or records) should be represented with HTML tables. I think that's the way tables are supposed to be used. The questions remains: How to represent a single "record" of data in HTML? – Christoph Schiessl Oct 12 '08 at 21:12
  • @Christoph Well I suppose it could be fine for one row of data if there was only one result - a search for example. Headings could be a good alternative, although this whole thing should be wrapped in an `address` tag anyway. – Ross Oct 12 '08 at 21:15
  • 1
    I decided to go with definition lists - it's probably the cleanest solution so far. Good explanation: http://www.maxdesign.com.au/presentation/definition – Christoph Schiessl Oct 12 '08 at 21:25
  • @David - his tabbing of the data is purely presentational. if there were different headings, say, one for each client, then that would be a table. when you're look at one set of data, it's not a table. DLs are the answer here. – nickf Oct 13 '08 at 12:56

7 Answers7

17

I think you've taken "tables are bad" concept to the extreme.

  • Tables used purely for layout (when other element would be more semantic) are bad.
  • Tables for tabular data are good. They were intended for that purpose!

What you've got fits very nicely into concept of rows and columns, with headers (<th>) and data (<td>) – based on semantics, not only layout.

If you want to make it more explicit that it's an address, then use adr Microformat or add a <caption>.

Wrong approaches:

  • <dl>: "1010" is not a definition of "Zip Code". The other way round it makes a bit more sense, but the relationship is just as clear with <th><td>, it doesn't rely on CSS, and will look perfect regearless of user's font size.
    If you use <th> will be perfectly rendered even in lynx! Address in <dl> without CSS trick will look weird.
  • HTML's <address> element may not be appropriate for this, because it is intended only for page author's/maintainer's contact information. It also allows inline content only, so you would lose structure of the address.
Kornel
  • 97,764
  • 37
  • 219
  • 309
  • Tables are bad when you *don't* use them for tabular layout ;-) – Chris Noe Oct 12 '08 at 20:34
  • @Chris, I 100% agree. It drives me mad that anti-table fever is so bad these days, people go to ridiculous lengths to avoid using tables for tabular data. – David Arno Oct 12 '08 at 20:56
  • I once wrote a tableless spreadsheet to respond to a post claiming tables should "never" be used. Never again... – Ross Oct 12 '08 at 21:05
  • 1
    Tables can be bad simply because the markup is ridiculously verbose. I hate the "tables are bad" extremists, but sometimes they can be write, even for tabular data, if that tabular data can be created more simply with alternative markup. – Dan Herbert Oct 12 '08 at 21:38
  • @porneL: that link you've added (the one right above this comment) supports the view that dl is the right tool for this job. Just sayin'. From TFA: "Definition lists can be used to tie together any items that have a direct relationship with each other (name/value sets)" – nickf Oct 13 '08 at 13:01
9

I find that definition lists make much more sense than tables here. Float the dt to the left with a specific width and have it clear on the left. If either the label or the data are going to wrap, you'll have to do some post-element-float-clearing trickery to make this work, but it doesn't sound like you'll need that. (I think it's worth it, anyway; plus, do it once and you'll never have to do it again.)

You can even use :after to add the colons automatically, if you don't mind brushing off IE6.

Eevee
  • 47,412
  • 11
  • 95
  • 127
  • I haven't thought about that yet ;) I like the idea very much! – Christoph Schiessl Oct 12 '08 at 20:43
  • I have changed my mind on this one. Initially I down-voted it as it seemed a misuse of dt/dd's. Upon reflection though, the data in the question is a classic case of data that fits the dt/dd model perfectly, so it's now upvoted :) – David Arno Oct 12 '08 at 21:15
  • If you like it Christoph, then you ought to mark it as the "right" answer. – David Arno Oct 12 '08 at 21:16
  • @David Arno: I know that. Just waiting a little longer - maybe someone has a even better solution ;) Besides: The exchange in the comments is quite interesting... – Christoph Schiessl Oct 12 '08 at 21:19
  • This makes sense to me - wrap it in an address block as well for extra semanticity =) – Ross Oct 12 '08 at 21:24
  • This is a valid solution, but I have to agree with others that this is no better than a tables solution. Even a UL would be incorrect. The data isn't a list at all, its just data. – willasaywhat Oct 13 '08 at 19:07
  • 1
    Problem with DL: DT "column" doesn't autosize to longest item, so you have to use known names of fields (IE, lines could break if users are able to add field with long name). On the other side, table with TH for headers and TD for content are OK, semantically more suitable, and will autosize. – Tomáš Kafka Jun 22 '09 at 20:04
4

Don't listen to the people saying that this is tabular data. Just because something has been presented in rows, it doesn't make it a table!

This is a great situation to use the dl, dt and dd tags. It's a bit of a stretch from what they're originally intended for, but it's still much more meaningful than a table, spans or divs.

<dl>
    <dt>Street</dt>
    <dd>Example Street 1</dd>
    <dt>City</dt>
    <dd>Vienna</dd>
    <dt>Zip Code</dt>
    <dd>1010</dd>
    <dt>Country</dt>
    <dd>Austria</dd>
</dl>

And the CSS:

dt {
    width: 150px;
    float: left;
    clear: left
}
dd {
    float: left;
}

That's fairly basic CSS - it probably won't hold up to a lot of situations (eg: two dd's in a row, a really long dt), but it's a start. Look at the inline-block property for the dt, and perhaps instead of using floating, you could set a left-margin of 150px on the dd.

nickf
  • 537,072
  • 198
  • 649
  • 721
  • 2
    If you look up "Zip Code" in dictionary, you won't find "1010" as a definition (unless it's a Big Bender's Binary Dictionary). You've got term/definition backwards. – Kornel Oct 13 '08 at 19:20
  • 4
    This is fine, but I just don't agree that dl/dt/dd is more semantically appropriate here than the alternatives. These aren't definitions: They're label/value pairs. Since there's no corresponding entity in HTML, the alternative approaches suggested here (divs, tables, definitions) are equally fine. – Herb Caudill Oct 17 '08 at 01:25
  • The problem with this approach is that you have to define a with for the labels. I would rater set a margin that insures a minimum space between the labels and the two columns of text, but I think that this is only possible using tables. – Jan Aagaard Feb 04 '10 at 09:50
  • 1
    “it's still much more meaningful than a table” — I disagree it’s more meaningful than a table. A properly marked up table would be slightly more meaningful than the `
    ` version if you had column headers. Of course, the definition list is fine too.
    – Paul D. Waite Apr 06 '10 at 22:23
2

Tables are the way to go.

Henrik Paul
  • 66,919
  • 31
  • 85
  • 96
0

As others have mentioned, floated elements are the way to go here.

This would be my solution:

<p class="details">
    <span class="label">Street:</span>
    Some Street or other.
    <br />

    <span class="label">City:</span>
    A City.
    <br />
</p>

With CSS that looks like this:

p.details {
    padding-left: 200px;
}

p.details span.label {
    float: left;
    clear: left;
    width: 200px;
    margin-left: -200px;
}

Because the main text isn't floating, this avoid any issues where that text is long and needs to wrap; it stops the floating element becoming to wide and then floating below the label. This means that no special cases are needed for when this text is multi-line either, say, if you wanted to have a multi-line address.

Similarly, this method also works if the label data needs to wrap over multiple lines, since the next label clears the previous float.

Having the line breaks in there means it also degrades nicely and looks like you would expect when not using CSS.

This method works very well for laying out forms, where <label> elements are used instead of the spans, and the paragraphs can be selected in the CSS as any paragraph that is the child of a <form>.

SpoonMeiser
  • 19,918
  • 8
  • 50
  • 68
-1

No need for tables (not that tables would be really inappropriate in this setting). I do this kind of thing all the time.

<div class=DetailsRow>
  <div class=DetailsLabel>Street</div>
  <div class=DetailsContent>123 Main Street</div>
</div>
<div class=DetailsRow>
  <div class=DetailsLabel>City</div>
  <div class=DetailsContent>Vienna</div>
</div>
  ...etc

and

div.DetailsRow
{
clear:both;
}

div.DetailsLabel
{
float:left;
width:100px;
color:gray;
}

div.DetailsContent
{
float:left;
width:400px;
}
Herb Caudill
  • 50,043
  • 39
  • 124
  • 173
  • 2
    so you regularly write reams of code to bodge div's into behaving like a poor implementation of tables. Why? You are even using fixed pixel-based widths, so your solution is crap in accessibility terms... – David Arno Oct 12 '08 at 21:03
  • fixed width divs != bad accessibility. – nickf Oct 13 '08 at 13:02
  • 1
    With divs being block level elements, I don't think this degrades particularly nicely. – SpoonMeiser Oct 13 '08 at 19:26
  • 1. Fixed widths are not "crap in accessibility terms." If the text is too big for the horizontal width, it wraps. No harm done. – Herb Caudill Oct 14 '08 at 00:29
  • 2. The situation given here isn't a table. It's not a definition list either. Since there's not an HTML element that matches the situation precisely, I think divs are no better or worse than the alternatives. – Herb Caudill Oct 14 '08 at 00:30
  • 3. This degrades fine. If CSS is turned off, this is perfectly readable. – Herb Caudill Oct 14 '08 at 00:31
  • What I meant was that your labels and data appear on separate lines and don't necessarily appear related. I think getting down voted is a bit harsh though. – SpoonMeiser Oct 15 '08 at 19:45
-2

Or you can throw away all sanity (and semantics) and recreate tables using CSS (tested in Firefox and Chrome):

<html>
<head>
<title>abusing divs</title>
<style type="text/css">
div.details {
    display: table;
}
div.details > div {
    display: table-row;
}
div.details > div > div {
    display: table-cell;
    padding-left: 0.25em;
    padding-right: 0.25em;
}
</style>
</head>
<body>
<div class="details">
    <div>
        <div>Street</div>
        <div>123 Main Street</div>
    </div>
    <div>
        <div>City</div>
        <div>Vienna</div>
    </div>
    <div>
        <div>This is a very very loooong label</div>
        <div>...</div>
    </div>
</div>
</body>
</html>

Just kidding.

panzi
  • 7,517
  • 5
  • 42
  • 54