This question already has answers here:
Best practice for making web forms
(6 answers)
Closed 9 years ago.
A classical piece of web development mantra is: "Only use tables for tabular data". This has its roots in the elder days, when tables were abused for every possible layout task imaginable.
While I too hold to this rule whenever possible, there are now and then layout tasks which I just cannot solve without a table - or tasks that straddle on the boundary between "tabular data" and "non-tabular data". This is one of them.
The situation is a totally classical one:
Name: […]
Surname: […]
Age: […]
Job: […]
The […] are meant to be textboxes. Is this tabular data? Should I use a table for arranging these labels and textboxes or some unholy mashup of <div>s and <span>s? The table would make it easier to provide the proper vertical alignments and help lining up labels of unknown widths. But would it be "proper", or just another "hack that floats my boat"?
And what if we look at it like this?
Field | Value
---------------
Name: […]
Surname: […]
Age: […]
Job: […]
First of all, thanks for a good question!
This is obviously a form, not a table. The layout of it doesn't really matter, the point of a table is to designate that you are displaying data that lends itself to tabulate (think of it as a composite of simple lists.) Your use case here is to gather input, it doesn't matter whether its layout kind'a sort'a looks like a form.
Of course, none of this matters if you don't really care about semantics; in which case I say use whatever you want. In any event there are plenty of examples and frameworks out there that'll do what you want, but it's not particularly difficult to do by yourself either. And in fact, it can be very much like laying out a table, if you so wish. I'll walk you through it.
(tl;dr)
First, some markup:
<form>
<label><span>Name:</span><input name="name" type="text"></label>
<label><span>Surname:</span><input name="surname" type="text"></label>
<label><span>Age:</span><input name="age" type="text"></label>
<label><span>Job:</span><input name="job" type="text"></label>
</form>
This is not particularly tricky markup. I've not added any classes as you can see, and I'll get to that in a second. But first, I wanted to show you, without any extra markup, how to turn this into a layout like that you requested:
form {
display: table;
}
label {
display: table-row;
}
label > * {
display: table-cell;
}
label > :first-child {
text-align: right;
padding-right: 10px;
}
That's it really. By using css and the table, table-row and table-cell headers for the display values, it's dead simple to create a table like layout without having to sacrifice semantic markup. This css doesn't change the semantics or accessibility of your form, it just provides clues to the browser how it should lay things out. Now, you also asked about adding a header to this. Changing the markup to the following, will unfortunately not really work:
<form>
<div>
<span>Field</span><span>Value</span>
</div>
<label><span>Name:</span><input name="name" type="text"></label>
<label><span>Surname:</span><input name="surname" type="text"></label>
<label><span>Age:</span><input name="age" type="text"></label>
<label><span>Job:</span><input name="job" type="text"></label>
</form>
This is because our styling rules doesn't include any selectors for the div. Now, there are a number of ways this could be fixed, with various different pros and cons. You'll probably run into people that have one thing or another to say about best practices in this area, but honestly it mostly comes down to what works for you. I'd say so long as you keep the markup accessible for humans and robots alike – this does mean trying to stay semantic and make use of microformats, amongst other things – then adding whatever extra cherries on top to get the job done is A-OK!
Anyway, here's one way of doing it, to get your creative juices flowing. First, the markup:
<form>
<div class="form-row">
<span>Field</span><span>Value</span>
</div>
<label class="form-row"><span>Name:</span><input name="name" type="text"></label>
<label class="form-row"><span>Surname:</span><input name="surname" type="text"></label>
<label class="form-row"><span>Age:</span><input name="age" type="text"></label>
<label class="form-row"><span>Job:</span><input name="job" type="text"></label>
</form>
And then the css:
form {
display: table;
}
.form-row {
display: table-row;
}
.form-row > * {
display: table-cell;
}
.form-row > :first-child {
text-align: right;
padding-right: 1em;
}
As you can see all that had to change was that we introduced the class form-row to classify our content such, and replaced the label selectors in the css with .form-row. Now there are plenty of ways to go with this and I hope you take some time to play around with it, because there's plenty to learn (semantics, microformats, css practices etc.)
Hope this helps!
Tabular-data describes a collective form of definite information. A form is not "tabular-data", it is interactive and not even really information for the visitor of the website, rather, it is information that (usually) gets sent, therefore it's fair to consider it incorrect to view changeable forms as "tabular-data." (Then again, it really depends on the usage, but I'm assuming you mean forms as in the practical and semantic purpose).
As far as a practice for styling forms, I usually tend to use divs and ul li combinations, as a form element is in fact a list of information. It even comes with (very limited, but still) some formatting options such as fieldset, legend, etc. I would consider looking into those as well.
Then there's the other side of the force (not necessarily the dark side, just, the alternative side) where semantics, while they matter, shouldn't be turned into a religious discipline. If tables work for forms, then so be it. You cannot apply a single set of semantic rules to every single situation. I've found myself saying this a lot, lately, but I'll say it again, every situation is different.
Well, using table or not depends, but if you are going to design a form, using table element is not the only thing which can design it perfectly, if you want, simply use an ul element with label and see how flawlessly you design the same thing without table or div
Demo
ul {
margin: 50px;
}
ul li {
margin-bottom: 10px;
font-family: Arial;
}
ul li label {
display: inline-block;
width: 100px;
}
Infact you can use float on the li by assigning a fixed width to your ul element, this will result in a two column form, increase the width and make it three, so you don't need table here.
The example you provided does not require a table... And not does resort into an "unholy mashup" of divs.
<div>
<label for="x"></label>
<div class="value">
<input id="x" type="text">
</div>
</div>
<!-- rinse, repeat -->
CSS:
label {
min-width: 8em; /* or whatever makes sense */
display: inline-block;
text-align: right;
}
.value {
display: inline-block;
}
While I too hold to this rule whenever possible, there are now and
then layout tasks which I just cannot solve without a table
Table elements have some pretty cool layout properties, and yes, there are times that those properties are needed. In these cases, CSS has the ability to set elements to display like various table elements, while keeping your code semantically correct as you would not actually using tables elements.
This includes properties such as display: table; display: table-cell;, display: table-row;
In terms of your example.. Tabular data is used to display information to a user.. placing inputs or textareas inside of a table would not be semantically correct. However, if you were to have that same format, with pre-existing data just being displayed, I would say that a table would be acceptable.
That format layout can be made with css fairly easily, using anything from floats, display: inline-block; or the table display properties mentioned above.
Related
Are there characters that are "smaller" (e.g. half the size) than ?
I am laying out my contact details on my website like so:
I'm trying to align my phone number with the email address above it:
Email: email address here
Tel telephone number here
If I was to add yet another non-breaking space the number would move too far right.
I agree with the other answerers, you are definitely using the wrong tool. If you are a beginner and CSS is over your head, use a table, it's really simple:
<table>
<tr> <td>Email</td> <td>whatever</td> </tr>
<tr> <td>Tel.</td> <td>012345</td> </tr>
</table>
However for anybody who is really in need of unusual spaces, Wikipedia has an overwhelming selection. Notably there is thin space ( , breaking) and Narrow No-Break Space (#x202F;, non-breaking).
You're barking up the wrong tree. Markup your data properly and align it using CSS, not using spaces or tabs. That's fundamentally a futile approach. E.g.:
<dl>
<dt>Telephone</dt>
<dd>012 3456 6789</dd>
<dt>Email</dt>
<dd>foo#example.com</dd>
</dl>
dl {
overflow: hidden;
}
dt {
float: left;
clear: left;
width: 150px;
}
dd {
margin-left: 170px;
}
The method you have chosen to align email and telephone is frankly straight out of the dark ages. There are modern ways to do this that will do the job in a much saner and more maintainable manner, i.e. using appropriate HTML and CSS:
<label>Email:</label> email address here
<label>Tel:</label> telephone here
Apply a uniform width to the labels with CSS and you are good to go:
label { width: 5em; display: inline-block }
Even something as basic as the above gives you bonuses like the ability to modify the width of all labels at once and choose left or right justification "for free" on top of justifying the content.
Live example.
You need to use css attribute 'margin-left' by creating span tags for email and phone no.
In css you can able to assign margin in pixel
Space was looking too big so I added padding instead. Margin can also be used as it makes no difference here.
-xLTx- means to put the less than < character in there.
You can use:
-xLTx-h1>Save/Retreive-xGTx-span style="padding-left:5px;">Data-LTx-/span>-xLTx-/h1>
You could also use:
-xLTx-h1>Save/Retreive-xLTx-span style="margin-left:5px;">Data-xLTx-/span>-xLTx-/h1>
Adjust the padding or margin to your liking.
I want to do a simple form layout, labels and inputs, without tables. It works fine like this:
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
form {
display: table;
}
form>div {
display: table-row;
}
form>div>* {
display: table-cell;
}
</style>
</head>
<body>
<form>
<div>
<label>Hello</label>
<input type="text"/>
</div>
<div>
<label>World</label>
<input type="text"/>
</div>
</form>
</body>
</html>
However, it doesn't work in IE7. What is the cleanest way to make table layouts that display correctly in IE7, IE8, Firefox, Chrome and Safari?
Edit:
I've added a mock up of the layout I want to achieve:
How about absolute positioning?
HTML:
<form>
<h3> LOGIN </h3>
<p> <label> Username: <input type="text"> </label> </p>
<p> <label> Password: <input type="text"> </label> </p>
</form>
CSS:
p { position:relative; }
input { position:absolute; top:0; right:0; }
Live demo: http://jsfiddle.net/GCWWv/1/
Or this CSS:
p { position:relative; }
input { position:absolute; left:100px; }
Live demo: http://jsfiddle.net/GCWWv/9/
Use <table>. Most likely, you've heard it is bad practice to use tables in HTML. It is true that you should avoid using tables for layout. But, if you are actually displaying tabular data, then you should use a table. If you are displaying rows and columns of data, that sounds like a table to me. It would be inappropriate to try and spoof it with css.
A little bit on why. An HTML tag should describe its content, not its appearance. Eg, <p> represents a paragraph, not a block element with top and bottom margins, and not something to use when you need more white space. Some people like this because it feels right. It's clean and tidy and provides a nice separation between content and style. Done well, it can make it easier to re-skin a website.
But more importantly, it makes a HUGE difference for accessibility. Consider screen readers for the blind. When the screen reader encounters a <table>, it expects it to contain data. It allows the user to navigate the table by columns, rows, and headings. Using a table at the wrong time can be very confusing. Using it properly, can make it much easier for the user. Creating a table out of divs and fancy CSS tricks forces the user to navigate each element individually, instead of being able to skip to the row and column that is pertinent. To use your example, if a user was filling out a form, and certain fields were unnecessary, he could easily navigate by <th> to find the fields he needed to fill out.
There are other similar reasons to follow the "tags describe content" convention. Mostly, it is when anything other than a standard browser is consuming your page. Think search engines, feeds, etc. There are
many
lengthy
discussions
about
this
online.
HTML5 takes this concept further with the introduction of some new semantic tags.
I would do something whereby you don't use display: table
I would:
form div {
float: left;
width: 200px /* change this to whatever */
}
If you need help could you please outline what visual layout you're trying to achieve? Good luck.
I looked online for examples of implementation of the form using DIVs and all I see is pretty simple one column forms. I have some pretty complicated forms, here is a picture of one:
http://img835.imageshack.us/img835/8292/formn.jpg
It is easy to make it work with table (which I do), the only problem I have is that sometimes I need to not display some of the choices and move the values up one row to avoid gaps.
I started making some forms using divs, but they fall apart when I change the browser window size and it is not easy to align things.
This topic is helpful:
Is it bad design to use table tags when displaying forms in html?
but it doesn't address some of the concerns I have.
What would you propose as a solution? I can dynamically delete/insert values in the table or try to do the DIVs.
I would go the div route. As long as you're careful of your widths when you apply floats, it's actually pretty straightforward to get the layouts to work properly in different screen resolutions.
Here are a few rules:
Set a max width on your form or your form's wrapper element. If you want to float elements on one row make sure their width's added together does not exceed this width.
If you are adding horizontal padding/margins to your floated elements remember that these add to the total width of the element.
Avoid mixing percentage widths with pixel padding and margins. Apply the percentage width to a parent element and the pixel padding/margins to a child element.
Use clearing elements between your rows of elements to keep everything in line.
As to the markup, you can use the form elements along with CSS to create a semantic structure:
<fieldset>
<legend>Fieldset Title</legend>
<label for="input1">Input 1:</label>
<span><input type="text" id="input1" name="input1"/></span>
<label for="input2">Input 2:</label>
<span><input type="text" id="input2" name="input2"/></span>
<br/>
<label for="input3">Input 3:</label>
<span><input type="text" id="input3" name="input3"/></span>
<label for="input4">Input 4:</label>
<span><input type="text" id="input4" name="input4"/></span>
</fieldset>
And the CSS:
fieldset {
padding: 20px 0;
width: 600px;
margin: 0;
border: 0;
}
legend {
display: block;
width: 100%;
background: black;
color: white;
}
label, span{
float: left;
width: 150px;
}
input {
width: 120px;
}
br {
clear: both;
}
You can see the result here.
If it is a fixed-width table, it's trivial to lay out with divs and floats. Just set each width to exactly what you want.
For a liquid-layout table—and liquid layout is in general highly desirable—it is much harder to arrange a form without table-style-display, because float and position do not readily allow for calculations like “this cell is half the remaining width of the parent, after the fixed-width labels have been allocated”.
So in cases like this, which certainly includes the kind of two-column form you posted, the table-* CSS display values are your only possibility. If you are aiming only at IE8 and the other modern browsers, you can use divs and set display: table-row et al in the stylesheet. However for compatibility with IE6-7 and other older/mobile/niche browsers, you will have to use actual <table>/<tr>/<td> elements, as only the modern browsers support table-CSS independently of the table-elements.
There is no shame in this. A form is kind-of semi-tabular anyway and there is no practical accessibility disadvantage because the page content remains ordered appropriately.
Note: for liquid-layout forms you also have the issue of sizing input fields to match the parent element. input { width: 100%; } almost does it, but not quite, because the width is not including the border or padding that inputs get by default. You can use CSS3 box-sizing and the browser-specific versions of it to get around that for modern browsers, but if you want it to line up exactly to the pixel on IE6-7 too you would have to use padding on the parent elements equal to the border/padding on the child input field.
General information is some kind of list, key > value list to be exact - <dl /> would be probably the best structure for it
Issues values is a table,
Ratings is a table,
Both Redemption and Indicators are lists - unordered lists <ul />
I want to display:
Name [Textbox]
Age: [Textbox]
BlahBlahCatfish: [Textbox]
but if I simply plonk the code in, it gets lined up exactly as its lined up above.
What I want is for it to be lined up like this:
Name: [Textbox]
Age: [Textbox]
BlahBlahCatfish: [Textbox]
Ordinarly I would use a Table but I am trying to get out of that habit and use lovely CSS. Ideas of how to do this without billions of divs and stuff?
Here is a site I did that does that.
http://acm.cs.kent.edu/contact/form.php
Basically its like this
<p>
<label for="someTextBox" >Text</label>
<input type="text" id="someTextBox" />
</p>
p label {
display: inline-block;
width: x;
}
p input {
width: y;
}
I use the 960 Grid System to handle form based layout, in particular I found the Fluid 960 Grid System most useful.
It's a simple and structured approach to layout, worth investing a little time to learn this as it will save you so much time in the future.
Another handy tool is the Gridder bookmarklet to aide layout.
There are other CSS frameworks such as Blueprint which are equally as good.
use a "left" and a "right" class, and make them float:left and float:right, respectively. The text would then go in a <div class="right">, and the attribute name in a <div class="left">.
I have long wanted to be able to include one style class within another. For example
med-font {
font-size:12px;
}
#message a {
style: med-font;
color: blue;
...
}
/* lots of other styles, some of which use med-font */
Obviously this is a stripped down example, but the key point is that all those anchor tags within #message shouldn't need explicit classes or ids. For now I either duplicate the font-size in each class that needs it or add classes to things that wouldn't otherwise require it. And since I want to easily control the font-size from one place, I usually start adding classes.
Another solution is to split up the definition of "#message a" in this example (below). This works ok for small projects, but for larger projects this is actually my least favoured solution. It makes site maintenance very difficult if you have many classes split apart and scattered around large style files.
med-font, #message a {
font-size:12px;
}
#message a {
color: blue;
...
}
So my question is two parts: 1. Does this annoy other people? 2. Does anyone know if this feature is/was being considered for CSS3?
Edit: Adding example of html body and more details...
The main point is that adding a class attribute to the 20 anchors below to set their font size is tedious.
<div id="username" class="med-font">schickb</div>
<div id="message">
<div id="part1">
text
<!--lots more tags and say 6 anchors -->
</div>
<div id="part2">
text
<!--lots more tags and say 8 anchors -->
</div>
</div>
<div id="footer"> <!-- footer anchors should be a smaller font-size -->
lala
<p class="med-font">Company Name</p>
<!-- other tags and 3 more anchors -->
</div>
Remember, an important goal is to have one place where "med-font" is declared so that it is easy to adjust. In my actual project, there are small, medium, and large font styles. I only want one declaration for each so that I don't have to search through the css to say change 12px to 11px.
The best solution currently is to add the "med-font" class to all the anchors in the body, and the "small-font" class to all the anchors in the footer. But I'd much rather do what I showed originally, and simply include the desired font in the styles for "#message a" and "#footer a".
Summary: I want CSS to be more DRY
No, it does not annoy me, because you can use multiple classes for an element and BOTH will match:
.idiot {
color:pink;
text-decoration:underline;
}
.annoying {
font-weight:bold;
}
/* and if you want to get REALLY specific... */
.annoying.idiot {
background-image('ann.jpg');
}
...
<div class="annoying idiot">
Ann Coulter
</div>
Personally, I find this a much more versatile solution to the problem. For example, in jQuery (or in another framework), you can add and remove these classes -- most commonly, you'll add a "selected" class or something that might do something like highlight a table cell, and when someone clicks to toggle it off, you just remove the "selected" class. Uber-elegant IMO.
In response to your edits, all you would have to do to remove the CSS from all of your A links would be to do something like this:
#message > div > a {
font-size:12px;
}
#footer > a {
font-size:10px;
}
Where the > symbol means "is a child of"
or, more generally (but this would also match an A directly inside #message and anything deeper -- the space means "is any descendant of")
#message a {
font-size:12px;
}
#footer a {
font-size:10px;
}
This is exactly what the Compass framework is good at. Sass allows variables, which makes coding/maintaining stylesheets very easy and a pleasant experience.
Have a look at SASS, which might do what you want. It allows for nested CSS structures, which can then be converted to CSS. I think.
In my opinion, the fact that you can't do this is perfectly OK because your CSS should remain as straightfoward as possible. On of the greatest advantage of CSS, as mention in Micheal Kay's XSLT reference (yeah xstl... I know), is that CSS is very simple and incredibly easy to understand.
I don't have to look at multiple places to know the styling effects of putting a class on a tag (well maybe but still).
So for me it would be a no for number 1. And as for 2, it has been discussed and I don't think it will be part of the standard.
css is not a programming language, it was never meant to be and (at this stage) never will be. what you're talking about has been discussed plenty of times before in W3C and WHATWG
oh and to answer 1) it doesn't annoy me
No, It doesnt annoy me, IE6 annoys me :)
It would be a useful feature to have, especially in a css framework, however, are we not being encouraged to lump all our css into one file now for "optimisation". I havent heard any rumours about such a feature in css3, but there is still a way to go on that spec yet, so who knows, it could make it in if you make enough noise now!