简体   繁体   中英

How would you achieve this table based layout using CSS instead of HTML tables?

I want the following layout to appear on the screen:

FieldName 1             [Field input 1]
FieldName 2 is longer   [Field input 2]
    .                         .
    .                         .
FieldName N             [Field input N]

Requirements:

  • Field names and field inputs must align on the left edges
  • Both columns must dynamically size themselves to their content
  • Must work cross-browsers

I find this layout extremely simple to do using HTML tables, but since I see a lot of CSS purists insisting that tables only be used for tabular data I figured I'd find out if there was a way to do it using CSS.

I wouldn't, I would use a table. This is a classic example of a tabular layout - exactly the sort of thing tables are supposed to be used for.

I think most of the answers are missing the point that the original questioner wanted the columns widths to depend on the width of the content. I believe the only way to do this with pure CSS is by using 'display: table', 'display: table-row' and 'display: table-cell', but that isn't supported by IE. But I'm not sure that this property is desirable, I find that creating a wide columns because there is a single long field name makes the layout less aesthetically pleasing and harder to use. Wrapped lines are fine in my opinion, so I think the answers that I just suggested were incorrect are probably the way to go.

Robertc's example is ideal but if you really must use tables, I think you can make it a little more 'semantic' by using <th> for the field names. I'm not sure about this so please someone correct me if I'm wrong.

<table>
    <tr><th scope="row"><label for="field1">FieldName 1</label></th>
        <td><input id="field1" name="field1"></td></tr>
    <tr><th scope="row"><label for="field2">FieldName 2 is longer</label></th>
        <td><input id="field2" name="field2"></td></tr>
    <!-- ....... -->
</table>

Update: I haven't been following this closely, but IE8 apparently supports CSS tables, so some are suggesting that we should start using them. There's an article on 24 ways which contains a relevant example at the end.

better still use a list

     <fieldset class="classname">
        <ul>
            <li>
                <label>Title:</label>
                <input type="text" name="title" value="" />
            </li>
        </ul>
     </fieldset>

the set the li tags width wide enough for both label and input and float the label to the left.

also to achieve that table like block with the tables you could set the label width to be as big as the largest fieldname forcing all the labels or expand that wide.

[edit] this is some good reading on a list apart

It's not clear that it is tabular data as some others have commented, though it could be. A table would imply a semantic relationship between all the items in the respective columns (other than just "they're all names of database columns"). Anyway, here's how I've done it before:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <title>Form layout</title>
    <style type="text/css">
        fieldset {width: 60%; margin: 0 auto;}
        div.row {clear: both;}
        div.row label {float: left; width: 60%;}
        div.row span {float: right; width: 35%;}
    </style>
</head>
<body>
    <form action="#" method="post">
        <fieldset>
            <legend>Section one</legend>
            <div class="row">
                <label for="first-field">The first field</label>
                <span><input type="text" id="first-field" size="15" /></span>
            </div>
            <div class="row">
                <label for="second-field">The second field with a longer label</label>
                <span><input type="text" id="second-field" size="10" /></span>
            </div>
            <div class="row">
                <label for="third-field">The third field</label>
                <span><input type="text" id="third-field" size="5" /></span>
            </div>
            <div class="row">
                <input type="submit" value="Go" />
            </div>
        </fieldset>
    </form>
</body>
</html>

Edit: Seems that 'by design' I can't reply to comments on my answer, obviously this is somehow less confusing. So, in reply to 17 of 26's comment - the 60% width is entirely optional, by default the fieldset will inherit the width of the containing element. You could also, of course, make use of min-width and max-width, or any of the table layout rules, if only IE supported them, but that's not CSS failing miserably ;)

This markup and CSS roughly achieves your stated goals under the restrictions for this question...

The Proposal

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>My Form</title>
    <style type="text/css">
      #frm1 div {float: left;}
      #frm1 div.go {clear: both; }
      #frm1 label, #frm1 input { float: left; clear: left; }
    </style>
  </head>
  <body>
    <form id="frm1" action="#" method="post">
      <fieldset>
        <legend>Section One</legend>
        <div>
          <label for="field1">Name</label>
          <label for="field2">Address, City, State, Zip</label>
          <label for="field3">Country</label>
        </div>
        <div>
          <input type="text" id="field1" size="15" />
          <input type="text" id="field2" size="20" />
          <input type="text" id="field3" size="10" />
        </div>
        <div class="go">
          <input type="submit" value="Go" />
        </div>
      </fieldset>
    </form>
  </body>
</html>

The Merits

...but I would not recommend its use. The problems with this solution are

  1. the very annoying entire-column wrap at skinny browser widths
  2. it separates the labels from their associated input fields in the markup

The solution above should be (I haven't verified this) accessible-friendly because screen readers, I have read, do a good job of using the for="" attribute in associating labels to input fields. So visually and accessibly-wise this works, but you might not like listing all your labels separately from your input fields.

Conclusion

The question as it is crafted -- specifically the requirement to automatically size the width of an entire column of different-length labels to the largest label length -- biases the markup solution towards tables. Absent that requirement, there are several great semantic solutions to presenting forms, as has been mentioned and suggested by others in this thread.

My point is this: There are several ways to present forms and collect user input in a pleasing, accessible, and intuitive way. If you can find no CSS layout that can meet your minimum requirements but tables can, then use tables.

FieldName objects should be contained in SPANs with style attributes of float: left and a width that is wide enough for your labels.

Inputs should be contained within a span styled to float: left. Place a <div style="clear: both"/> or <br/> after each field input to break the floating.

You may enclose the aforementioned objects into a div with the width style attribute set that is wide enough for both labels and inputs, so that the "table" stays small and contained.

Example:

<span style="float: left; width: 200px">FieldName1</span><span style="float: left"><input/><br/>

<span style="float: left; width: 200px">FieldName2</span><span style="float: left"><input/><br/>

<span style="float: left">FieldName3</span><span style="float: left"><input/><br/>

Each row is to be taken as a 'div' that contains two 'spans' one for fieldname and one for the input. Set 'float:left' on both the spans. However, you need to set some width for the 'fieldname' span.

Also, style the div to include the attribute 'clear:both' for precaution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM