169

I have very basic and known scenario of form where I need to align labels next to inputs correctly. However I don't know how to do it.

My goal would be that labels are aligned next to inputs to the right side. Here is picture example of desired result.

enter image description here

I have made a fiddle for your convenience and to clarify what I have now - http://jsfiddle.net/WX58z/

Snippet:

<div class="block">
    <label>Simple label</label>
    <input type="text" />
</div>
<div class="block">
    <label>Label with more text</label>
    <input type="text" />
</div>
<div class="block">
    <label>Short</label>
    <input type="text" />
</div>
Michał Perłakowski
  • 88,409
  • 26
  • 156
  • 177
Stan
  • 25,744
  • 53
  • 164
  • 242

8 Answers8

220

WARNING: OUTDATED ANSWER

Nowadays you should definitely avoid using fixed widths. You could use flexbox or CSS grid to come up with a responsive solution. See the other answers.


One possible solution:

  • Determine a reasonable fixed width for label elements and set it using width
  • Give them display: inline-block
  • Align text to the right

That is:

label {
  display: inline-block;
  width: 140px;
  text-align: right;
}​
<div class="block">
    <label>Simple label</label>
    <input type="text" />
</div>
<div class="block">
    <label>Label with more text</label>
    <input type="text" />
</div>
<div class="block">
    <label>Short</label>
    <input type="text" />
</div>

JSFiddle

bfavaretto
  • 71,580
  • 16
  • 111
  • 150
  • 4
    How do I make this work if some of the labels are check-boxes or radio buttons? The labels for these elements end up with the same fixed width as the textbox labels which is not desired. Is there a way to do this without a fixed width on the label? – Rebecca Meritz Jan 14 '14 at 12:15
  • @RebeccaMeritz You mean when the markup has the checkbox first, and the label afterwards? You could add a class to both, and style them separately. Perhaps you should [ask a new question](http://stackoverflow.com/questions/ask) about it. – bfavaretto Jan 14 '14 at 14:34
  • 2
    How to make this responsive? And how to cope with i18n? I mean that text labels have different length in different languages, thus I fear that that setting fixed width fill not work if the text is long. – Azimuth Apr 06 '18 at 12:16
  • @Azimuth Nowadays, you might want to use CSS grid instead. – bfavaretto Apr 06 '18 at 14:04
  • 2
    this is marking fixed width, it should be dynamic, based on max label width. – Samyak Jain May 23 '19 at 17:21
  • I agree with the people here above, that using a fixed width is a bad solution when it comes down to scaling of the labels and the usage of dynamic width's based on content. – Barrosy Oct 09 '20 at 18:28
  • @Barrosy I totally agree, you could use flexbox or grid nowadays. That was not the case when this answer was written 8 yrs ago... – bfavaretto Oct 09 '20 at 18:33
  • @bfavaretto Even so, I belive better solutions existed back then as well, but you might be right. – Barrosy Oct 11 '20 at 14:32
  • CSS flexbox is merely a candidate recommendation, while CSS grid is not even at that stage yet (draft CR). Unfortunately, the warning is misleading; this answer remains current. – Philippe Cloutier Apr 27 '23 at 20:27
  • Regardless of the formal status of flexbox and grid, I'd avoid fixed widths whenever possible today. That's the spirit of the warning. Also, both technologies are widely supported nowadays. @PhilippeCloutier – bfavaretto Apr 28 '23 at 01:00
80

While the solutions here are workable, more recent technology has made for what I think is a better solution. CSS Grid Layout allows us to structure a more elegant solution.

The CSS below provides a 2-column "settings" structure, where the first column is expected to be a right-aligned label, followed by some content in the second column. More complicated content can be presented in the second column by wrapping it in a <div>.

[As a side-note: I use CSS to add the ':' that trails each label, as this is a stylistic element - my preference.]

/* CSS */

div.settings {
    display:grid;
    grid-template-columns: max-content max-content;
    grid-gap:5px;
}
div.settings label       { text-align:right; }
div.settings label:after { content: ":"; }
<!-- HTML -->

<div class="settings">
    <label>Label #1</label>
    <input type="text" />

    <label>Long Label #2</label>
    <span>Display content</span>

    <label>Label #3</label>
    <input type="text" />
</div>
14

Answered a question such as this before, you can take a look at the results here:

Creating form to have fields and text next to each other - what is the semantic way to do it?

So to apply the same rules to your fiddle you can use display:inline-block to display your label and input groups side by side, like so:

CSS

input {
    margin-top: 5px;
    margin-bottom: 5px;
    display:inline-block;
    *display: inline;     /* for IE7*/
    zoom:1;              /* for IE7*/
    vertical-align:middle;
    margin-left:20px
}

label {
    display:inline-block;
    *display: inline;     /* for IE7*/
    zoom:1;              /* for IE7*/
    float: left;
    padding-top: 5px;
    text-align: right;
    width: 140px;
}

updated fiddle

Community
  • 1
  • 1
Andres I Perez
  • 75,075
  • 21
  • 157
  • 138
  • 2
    This is a very nice solution, except for the fact that you must hard-code the width of the labels. If a new label is too long - the layout breaks. Seems like there should be a more robust solution? – mattstuehler Feb 05 '19 at 01:03
10

I use something similar to this:

<div class="form-element">
  <label for="foo">Long Label</label>
  <input type="text" name="foo" id="foo" />
</div>

Style:

.form-element label {
    display: inline-block;
    width: 150px;
}
Mike G
  • 758
  • 6
  • 18
6

I know this is an old thread but an easier solution would be to embed an input within the label like so:

<label>Label one: <input id="input1" type="text"></label>
Robert
  • 229
  • 3
  • 9
5

You can also try using flex-box

<head><style>
body {
    color:white;
    font-family:arial;
    font-size:1.2em;
}
form {
    margin:0 auto;
    padding:20px;
    background:#444;
}
.input-group {
    margin-top:10px;
    width:60%;
    display:flex;
    justify-content:space-between;
    flex-wrap:wrap;
}
label, input {
    flex-basis:100px;
}
</style></head>
<body>

<form>
    <div class="wrapper">
        <div class="input-group">
            <label for="user_name">name:</label>
            <input type="text" id="user_name">
        </div>
        <div class="input-group">
            <label for="user_pass">Password:</label>
            <input type="password" id="user_pass">
        </div>
    </div>
</form>

</body>
</html>
Cromax
  • 1,822
  • 1
  • 23
  • 35
user6797117
  • 51
  • 1
  • 1
2

You can do something like this:

HTML:

<div class='div'>
<label>Something</label>
<input type='text' class='input'/>
<div>

CSS:

.div{
      margin-bottom: 10px;
      display: grid;
      grid-template-columns: 1fr 4fr;
}

.input{
       width: 50%;
}

Hope this helps ! :)

Rakonjac
  • 87
  • 9
0

Here is generic labels width for all form labels. Nothing fix width.

call setLabelWidth calculator with all the labels. This function will load all labels on UI and find out maximum label width. Apply return value of below function to all the labels.

     this.setLabelWidth = function (labels) {
            var d = labels.join('<br>'),
                dummyelm = jQuery("#lblWidthCalcHolder"),
                width;
            dummyelm.empty().html(d);
            width = Math.ceil(dummyelm[0].getBoundingClientRect().width);
            width = width > 0 ? width + 5: width;
            //this.resetLabels(); //to reset labels.
            var element = angular.element("#lblWidthCalcHolder")[0];
            element.style.visibility = "hidden";
            //Removing all the lables from the element as width is calculated and the element is hidden
            element.innerHTML = "";
            return {
                width: width,
                validWidth: width !== 0
            };

        };
Samyak Jain
  • 856
  • 1
  • 9
  • 12