143

I'm new to HTML and I'm trying to learn how to use forms.

The biggest issue I am having so far is aligning the forms. Here is an example of my current HTML file:

<form>
 First Name:<input type="text" name="first"><br />
 Last Name:<input type="text" name="last"><br />
 Email:<input type="text" name="email"><br />
</form>

The problem with this is, the field box after 'Email' is drastically different in terms of spacing compared to first, and last name. What is the 'proper' way to make it so that they 'line-up' essentially?

I am trying to practice good form and syntax...a lot of people might do this with CSS I am not sure, I have only learned the very basics of HTML so far.

yoshyosh
  • 13,956
  • 14
  • 38
  • 46
  • 1
    there is an evergoing fight between when tables (if at all), the answers to your question is not the exeption, the middle point seam to be that is for tabular data, se more here: http://stackoverflow.com/questions/83073/why-not-use-tables-for-layout-in-html – Trufa Nov 30 '10 at 03:06
  • Exactly the same question but the answer suggests using tag with the citation of W3C: http://stackoverflow.com/questions/4707332
    – Bossliaw Mar 07 '13 at 13:03

17 Answers17

174

The accepted answer (setting an explicit width in pixels) makes it hard to make changes, and breaks when your users use a different font size. Using CSS tables, on the other hand, works great:

form  { display: table;      }
p     { display: table-row;  }
label { display: table-cell; }
input { display: table-cell; }
<form>
  <p>
    <label for="a">Short label:</label>
    <input id="a" type="text">
  </p>
  <p>
    <label for="b">Very very very long label:</label>
    <input id="b" type="text">
  </p>
</form>

Here's a JSFiddle: http://jsfiddle.net/DaS39/1/

And if you need the labels right-aligned, just add text-align: right to the labels: http://jsfiddle.net/DaS39/


EDIT: One more quick note: CSS tables also let you play with columns: for example, if you want to make the input fields take as much space as possible, you can add the following in your form

<div style="display: table-column;"></div>
<div style="display: table-column; width:100%;"></div>

you may want to add white-space: nowrap to the labels in that case.

Basj
  • 41,386
  • 99
  • 383
  • 673
Clément
  • 12,299
  • 15
  • 75
  • 115
  • 6
    I like this solution. It means I don't have to worry about my columns inevitably changing width as the page evolves through development. +1 – Tom Lord Jun 01 '14 at 23:11
  • 11
    @MuhammadUmer Because tables will confuse screen readers and many assistive devices, whereas CSS tables separate presentation and content. Thus your form remains easily parsable by a screen reader or reading assistant, and yet displays nicely. – Clément Jun 16 '14 at 14:20
  • @Clément how come? Screen Readers Rely On Structure of document..and the structure of this is exactly the same as table's would be. Just replace `p` with `tr`, `label` & `input` with `td`. I think `td` would have better support then new `label` elements. – Muhammad Umer Jun 16 '14 at 15:10
  • 3
    Well, fitting label in td suggests that it's part of organized, tabular data, like charts; that's not the case here. Plus, using HTML tables makes it harder to change the layout in the future, or to adapt it to various screen sizes (think mobile phones & tablets). – Clément Jun 17 '14 at 04:30
  • 4
    I have been strongly resisting the CSS table structure with the same argument @MuhammadUmer was making, until today! I caved and decided to try it and finally see the value of switching! Plus, its CSS, so makes things easier in the long run – BillyNair Mar 05 '15 at 22:07
  • 3
    How can you span columns with this solution? In order to center align submit button. – eugenekr Mar 21 '19 at 13:05
  • 1
    Any particular reason why you chose to use the p tag for rows instead of, say, a `div` tag or a `fieldset` tag? – Alex Rummel Jun 29 '20 at 19:47
65

Another example, this uses CSS, I simply put the form in a div with the container class. And specified that input elements contained within are to be 100% of the container width and not have any elements on either side.

.container {
  width: 500px;
  clear: both;
}

.container input {
  width: 100%;
  clear: both;
}
<html>

<head>
  <title>Example form</title>
</head>

<body>
  <div class="container">
    <form>
      <label>First Name</label>
      <input type="text" name="first"><br />
      <label>Last Name</label>
      <input type="text" name="last"><br />
      <label>Email</label>
      <input type="text" name="email"><br />
    </form>
  </div>
</body>

</html>
Nisarg Shah
  • 14,151
  • 6
  • 34
  • 55
serialk
  • 926
  • 7
  • 11
49

A simple solution for you if you're new to HTML, is just to use a table to line everything up.

<form>
  <table>
    <tr>
      <td align="right">First Name:</td>
      <td align="left"><input type="text" name="first" /></td>
    </tr>
    <tr>
      <td align="right">Last Name:</td>
      <td align="left"><input type="text" name="last" /></td>
    </tr>
    <tr>
      <td align="right">Email:</td>
      <td align="left"><input type="text" name="email" /></td>
    </tr>
  </table>
</form>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
amonett
  • 714
  • 5
  • 12
  • 50
    Quick and simple solution. Leave the religous CSS debates for the lunch break and get the job done. – Emmanuel Bourg Oct 17 '12 at 22:26
  • 3
    @ClarkeyBoy - who cares as long as its doing the job. – Desolator Apr 26 '13 at 21:41
  • 1
    @ClarkeyBoy - most ignorant comment? lol.. I don't wanna get in an argument with you in here.. if you wanna do it the divs way do it. if you wanna do it the tables way its up to you. but don't assume all of customers or people will care about that. most of them care about getting the job done.. – Desolator May 01 '13 at 00:05
  • 2
    @ClarkeyBoy - Do read this answer, and the post from W3C: http://stackoverflow.com/a/4707368/40411 – J. Polfer Sep 20 '13 at 15:31
  • 7
    @EmmanuelBourg: Isn't this precisely what CSS tables are meant for? Achieving a table-like layout without confusing screen readers? The layout that the OP asks for is actually pretty easy to achieve using CSS tables (see [below](http://stackoverflow.com/a/23741073/695591)) – Clément May 19 '14 at 15:12
  • minimum CSS! great idea. – KawaiKx Jun 19 '17 at 18:16
  • 1
    That's what I use too. To hell with "simpler" tableless + 300 lines of hacky CSS code. – rodrigocfd Nov 30 '17 at 17:57
  • While techincally still part of the standard atributes such as 'align' are deprecated. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table#attr-align. Meaning webpages using this are not future proof. – wheredidthatnamecomefrom Dec 03 '21 at 19:45
22

I find it far easier to change the display of the labels to inline-block and set a width

label {
  display: inline-block;
  width: 100px;
  text-align: right;
}
<form>
  <label>First Name:</label><input type="text" name="first" /><br />
  <label>Last Name:</label><input type="text" name="last" /><br />
  <label>Email:</label><input type="text" name="email" /><br />
</form>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
Byron
  • 283
  • 2
  • 7
9

You should use a table. As a matter of logical structure the data is tabular: this is why you want it to align, because you want to show that the labels are not related solely to their input boxes but also to each other, in a two-dimensional structure.

[consider what you would do if you had string or numeric values to display instead of input boxes.]

Collin Street
  • 107
  • 1
  • 1
2

For this, I prefer to keep a correct HTML semantic, and to use a CSS simple as possible.

Something like this would do the job :

label{
  display: block;
  float: left;
  width : 120px;    
}

One drawback however : you might have to pick the right label width for each form, and this is not easy if your labels can be dynamic (I18N labels for instance).

kleopatra
  • 51,061
  • 28
  • 99
  • 211
Samuel EUSTACHI
  • 3,116
  • 19
  • 24
2

using css

.containerdiv label {
  float:left;
  width:25%;
  text-align:right;
  margin-right:5px; /* optional */
}
.containerdiv input {
  float:left;
  width:65%;
}

this give you something like:

           label1 |input box             |
    another label |another input box     |
Gjaa
  • 1,461
  • 1
  • 19
  • 20
2

I'm a big fan of using definition lists.

They're easy to style using CSS, and they avoid the stigma of using tables for layout.

<dl>
  <dt>Username:</dt>
  <dd><input type="text" name="username" /></dd>
  <dt>Password:</dt>
  <dd><input type="password" name="password" /></dd>
</dl>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
Andrew
  • 1,369
  • 1
  • 17
  • 30
  • This is just as easily accomplished with `div`s (a `dd` just has a ~40px left margin), and avoids any semantic confusion. Besides, neither of these line up the labels/inputs on the same line. – Hollister Sep 25 '12 at 03:07
1

I know this has already been answered, but I found a new way to align them nicely - with an extra benefit - see http://www.gargan.org/en/Web_Development/Form_Layout_with_CSS/

basically you use the label element around the input and align using that and then with css you simply align:

label {
  display: block;
  position: relative;
}

label span {
  font-weight: bold;
  position: absolute;
  left: 3px;
}

label input,
label textarea,
label select {
  margin-left: 120px;
}
<label><span>Name</span> <input /></label>
<label><span>E-Mail</span> <input /></label>
<label><span>Comment</span> <textarea></textarea></label>
  • you do not need any messy br lying around for linebreaks - meaning you can quickly accomplish a multi-column layout dynamically
  • the whole line is click-able. Especially for checkboxes this is a huge help.
  • Dynamically showing/hiding form lines is easy (you just search for the input and hide its parent -> the label)
  • you can assign classes to the whole label making it show error input much clearer (not only around the input field)
mplungjan
  • 169,008
  • 28
  • 173
  • 236
Niko
  • 6,133
  • 2
  • 37
  • 49
1

The traditional method is to use a table.

However, many would argue that tables are restricting and prefer CSS. The benefit of using CSS is that you could use various elements. From divs, ordered and un-ordered list, you could accomplish the same layout.

In the end, you'll want to use what you're most comfortable with.

Hint: Tables are easy to get started with.

Example:

<table>
  <tbody>
    <tr>
      <td>
        First Name:
      </td>
      <td>
        <input type="text" name="first">
      </td>
    </tr>
    <tr>
      <td>
        Last Name:
      </td>
      <td>
        <input type="text" name="last">
      </td>
    </tr>
  </tbody>
</table>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • 1
    +1 for stating that they are easy to get started with... but really developers should only resort to tables for *data* (see my comment on another answer for full rant!) – ClarkeyBoy Nov 30 '10 at 03:44
  • 1
    Using CSS tables is just as easy, and it doesn't have the associated accessibility problems. See [my answer](http://stackoverflow.com/a/23741073/695591) below. – Clément May 19 '14 at 15:08
1

Clément's answer is by far the best. Here's a somewhat improved answer, showing different possible alignments, including left-center-right aligned buttons:

label {
  padding-right: 8px;
}

.FAligned,
.FAlignIn {
  display: table;
}

.FAlignIn {
  width: 100%;
}

.FRLeft,
.FRRight,
.FRCenter {
  display: table-row;
  white-space: nowrap;
}

.FCLeft,
.FCRight,
.FCCenter {
  display: table-cell;
}

.FRLeft,
.FCLeft,
.FILeft {
  text-align: left;
}

.FRRight,
.FCRight,
.FIRight {
  text-align: right;
}

.FRCenter,
.FCCenter,
.FICenter {
  text-align: center;
}
<form class="FAligned">
  <div class="FRLeft">
    <p class="FRLeft">
      <label for="Input0" class="FCLeft">Left:</label>
      <input id="Input0" type="text" size="30" placeholder="Left Left Left" class="FILeft" />
    </p>
    <p class="FRLeft">
      <label for="Input1" class="FCRight">Left Right Left:</label>
      <input id="Input1" type="text" size="30" placeholder="Left Right Left" class="FILeft" />
    </p>
    <p class="FRRight">
      <label for="Input2" class="FCLeft">Right Left Left:</label>
      <input id="Input2" type="text" size="30" placeholder="Right Left Left" class="FILeft" />
    </p>
    <p class="FRRight">
      <label for="Input3" class="FCRight">Right Right Left:</label>
      <input id="Input3" type="text" size="30" placeholder="Right Right Left" class="FILeft" />
    </p>
    <p class="FRLeft">
      <label for="Input4" class="FCLeft">Left Left Right:</label>
      <input id="Input4" type="text" size="30" placeholder="Left Left Right" class="FIRight" />
    </p>
    <p class="FRLeft">
      <label for="Input5" class="FCRight">Left Right Right:</label>
      <input id="Input5" type="text" size="30" placeholder="Left Right Right" class="FIRight" />
    </p>
    <p class="FRRight">
      <label for="Input6" class="FCLeft">Right Left Right:</label>
      <input id="Input6" type="text" size="30" placeholder="Right Left Right" class="FIRight" />
    </p>
    <p class="FRRight">
      <label for="Input7" class="FCRight">Right:</label>
      <input id="Input7" type="text" size="30" placeholder="Right Right Right" class="FIRight" />
    </p>
    <p class="FRCenter">
      <label for="Input8" class="FCCenter">And centralised is also possible:</label>
      <input id="Input8" type="text" size="60" placeholder="Center in the centre" class="FICenter" />
    </p>
  </div>
  <div class="FAlignIn">
    <div class="FRCenter">
      <div class="FCLeft"><button type="button">Button on the Left</button></div>
      <div class="FCCenter"><button type="button">Button on the Centre</button></div>
      <div class="FCRight"><button type="button">Button on the Right</button></div>
    </div>
  </div>
</form>

I added some padding on the right of all labels (padding-right:8px) just to make the example slight less horrible looking, but that should be done more carefully in a real project (adding padding to all other elements would also be a good idea).

mplungjan
  • 169,008
  • 28
  • 173
  • 236
Cyberknight
  • 156
  • 2
  • 6
1

It also can be done using CSS and without tables or floats or fixed lengths by changing the content direction to rtl and then back to ltr, but the labels must go after each input.

To avoid this markup reordering, just set the label's text in a data-* attribute and show it using an ::after pseudo-element. I think it becomes much clearer.

Here is an example setting the label's text in a custom attribute called data-text and showing them using the ::after pseudo-element, so we don't mess with markup while changing direction to rtl and ltr :

form
{
  display: inline-block;
  background-color: gold;
  padding: 6px;
}

label{
  display: block;
  direction: rtl; 
}

input{
  direction: ltr; 
}

label::after{
  content: attr(data-text);
}
<form>
  <label data-text="First Name">
    <input type="text" />
  </label>
  <label data-text="Last Name">
    <input type="text" />
  </label>
  <label data-text="E-mail">
    <input type="text" />
  </label>
</form>
Felypp Oliveira
  • 2,147
  • 1
  • 17
  • 17
0

Well for the very basics you can try aligning them in the table. However the use of table is bad for layout since table is meant for contents.

What you can use is CSS floating techniques.

.styleform label{float:left;}
.styleform input{margin-left:200px;} /* this gives space for the label on the left */
.styleform .clear{clear:both;} /* prevent elements from stacking weirdly */
<div class="styleform">
  <form>
    <label>First Name:</label><input type="text" name="first" />
    <div class="clear"></div>
    <label>Last Name:</label><input type="text" name="first" />
    <div class="clear"></div>
    <label>Email:</label><input type="text" name="first" />
    <div class="clear"></div>
  </form>
</div>

An elaborate article I wrote can be found answering the question of IE7 float problem: IE7 float right problems

mplungjan
  • 169,008
  • 28
  • 173
  • 236
mauris
  • 42,982
  • 15
  • 99
  • 131
  • thanks for the examples, however the HTML form still doesnt solve the issue. If you change 'First Name' in one of them to just 'Name' for example, I end up with the same problem I had the first time – yoshyosh Nov 30 '10 at 02:29
  • I've worked with this from designers and it's a little fragile, IME. For this basic layout, it will be fine 98% of the time. Try to get too complex, e.g. two-column layout, or multi-line labels, and it gets difficult. – staticsan Nov 30 '10 at 02:30
  • 1
    @staticsan - if you understand floats, clears and divs, you will work fine with such layout and in fact they render faster and is more flexible compared to tables on modern browsers. – mauris Nov 30 '10 at 03:02
  • Well, I *thought* I understood floats, clears and divs, but I couldn't extend the form I was given without it breaking. Whether it was a flaw in my understanding or the designer's implementation, the fact remained it was fragile. (Interestingly, the next version is going to more of a hybrid design using `ul` tags.) – staticsan Nov 30 '10 at 04:12
  • 1
    I made a snippet. It does not do what you think it should do - at least not in 2023 Chrome – mplungjan Feb 16 '23 at 18:40
-1

The CSS I used to solve this problem, similar to Gjaa but styled better

It's very simple, and I'm just beginning, but it worked quite nicely

Here is my CSS and HTML, used specifically for a simple registration form with no php code

p {
  text-align: center;
}

.styleform label {
  float: left;
  width: 40%;
  text-align: right;
}

.styleform input {
  float: left;
  width: 30%;
}
<form id="registration">
  <h1>Register</h1>
  <div class="styleform">
    <fieldset id="inputs">
      <p><label>Name:</label>
        <input id="name" type="text" placeholder="Name" autofocus required>
      </p>
      <p><label>Email:</label>
        <input id="email" type="text" placeholder="Email Address" required>
      </p>
      <p><label>Username:</label>
        <input id="username" type="text" placeholder="Username" autofocus required>
      </p>
      <p>
        <label>Password:</label>
        <input id="password" type="password" placeholder="Password" required>
      </p>
    </fieldset>
    <fieldset id="actions">
    </fieldset>
  </div>
  <p>
    <input type="submit" id="submit" value="Register">
  </p>
</form>  
mplungjan
  • 169,008
  • 28
  • 173
  • 236
PA_Commons
  • 269
  • 2
  • 6
  • 14
-1

Insert input tags inside an unordered lists.Make the style-type none. Here's an example.

<ul>
Input1     
<li> <input type="text" />
Input2
<li> <input type="text" />
<ul/>

Worked for me !

Vivek Iyer
  • 154
  • 1
  • 6
  • 16
  • This would never work. `UL` would just indent the content away from the margin, not align anything. Putting the `input`s in `LI` would just add a bullet before them (yes, they would be aligned, as a list, not against the labels). Also, "Input2" would stick to the previous `input` element, because the `LI` are not closed (there are no ``) and there is no starting `
  • ` for that "label", so it will be treated as it should, common text, therefore, concatenated to the previous element. Last, the code has an error, the closing `
      ` should be ``.
    • – Cyberknight May 03 '20 at 23:06