Align form elements in CSS - css

I'm new to CSS and have a simple login form that I'm trying to align correctly. Basically two columns with the labels and the Login button in one column and the text boxes in another column. How do I do this in CSS?
The HTML code is:
<body>
<form action="" method="post">
<label> Username </label>
<input type="text"/>
<label> Password </label>
<input type="password"/>
<input type="submit" value="submit"/>
</form>
</body>

This is one approach that works:
form {
width: 80%;
margin: 0 auto;
}
label,
input {
/* In order to define widths */
display: inline-block;
}
label {
width: 30%;
/* Positions the label text beside the input */
text-align: right;
}
label+input {
width: 30%;
/* Large margin-right to force the next element to the new-line
and margin-left to create a gutter between the label and input */
margin: 0 30% 0 4%;
}
/* Only the submit button is matched by this selector,
but to be sure you could use an id or class for that button */
input+input {
float: right;
}
<form action="#" method="post">
<!-- note that I've added a 'for' attribute to
both of the <label> elements, which is
equal to the 'id' attribute of the relevant
<input> element; this means that clicking
the <label> will focus the <input>: -->
<label for="username">Username</label>
<input id="username" type="text" />
<label for="password">Password</label>
<input id="password" type="password" />
<input type="submit" value="submit" />
</form>
​
JS Fiddle demo.
Adjust dimensions and margins to suit your use-case and aesthetic of course.
Of course, currently, there are other means by which this can work, such as CSS Grid:
*,
::before,
::after {
/* selecting all elements on the page, along with the ::before
and ::after pseudo-elements; resetting their margin and
padding to zero and forcing all elements to calculate their
box-sizing the same way, 'border-box' includes the border-widths,
and padding, in the stated width: */
box-sizing: border-box;
margin: 0;
padding: 0;
}
form {
/* Using CSS Grid to lay out the elements in two-dimensions: */
display: grid;
/* specifying a 0.5em gutter/gap between adjacent elements: */
gap: 0.5em;
/* declaring a number of named grid areas in order to lay out
the child elements; the areas identified with a period (.)
are 'empty' areas, whereas the areas named by strings are
used, later, to place elements according to those names: */
grid-template-areas:
"usernameLabel . usernameInput"
"passwordLabel . passwordInput"
". . submit";
/* declaring the size of each of the three columns; 1fr is
one fractional unit of the available space, and is the
size of the first and last of the columns. The central
column is declared as being 0.5em in width: */
grid-template-columns: 1fr 0.5em 1fr;
margin: 1em auto;
width: 80%;
}
label {
/* placing all <label> elements in the grid column 1 (the first): */
grid-column: 1;
/* aligning text-content to the right in order to position the label
text near to the relevant <input>: */
text-align: right;
}
label::after {
content: ':';
}
input {
grid-column: 3;
}
button {
/* positioning the <button> element in the grid-area identified
by the name of 'submit': */
grid-area: submit;
}
<form action="" method="post">
<label for="username">Username</label>
<input id="username" type="text" />
<label for="password">Password</label>
<input id="password" type="password" />
<input type="submit" value="submit" />
</form>
JS Fiddle demo.
References:
Adjacent-sibling (+) combinator.
box-sizing.
display.
float.
gap.
grid-area.
grid-template-areas.
grid-template-columns.
grid-template-rows.
margin.
width.
Bibliography:
"Basic Concepts of grid layout."

For what you are asking, I'd simply put them in a table.
<form action="" method="post">
<table>
<tr>
<td><label> Username </label></td>
<td><input type="text"/></td>
</tr>
<tr>
<td><label> Password </label></td>
<td> <input type="password"/></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="submit"/></td>
</tr>
</table>
</form>
Here's what it will look like
http://jsfiddle.net/wCSAn/

You can also use the position property in CSS to align your label and input in certain specified way as you want. By this, they get arranged in accordance to the parent element.
form {
position: relative;
width: 70%;
text-align: right;
}
label {
width: 30%;
position: absolute;
left: 10%;
text-align: right;
margin-right: 30px;
}
input[type=submit] {
position: absolute;
left: 25%;
background-color: #9AE5F8;
}
Here is the link to its jsfiddle.

Related

Keeping row of inputs aligned while adding optional label text above

I have a row of 3 inputs. One of them has label text placed above its input. I do not want this label text to interfere with the alignment of the inputs. Right now I'm using flexbox in my example. My hack/approach is to use position: absolute; on my optional label text to remove it from the flex flow so the inputs stay align. However, this creates a bit of spacing inconsistency when wrapping on smaller viewports. I've tried CSS grid as well but had issues where I was stuck writing a media query for every time I needed to wrap, which seemed worse than this. I would also like the solution to have no fixed widths/heights. As the elements and text can be dynamic. What is the best way to achieve this functionality that allows for a cleaner wrapping?
.container {
display: flex;
flex-wrap: wrap;
align-items: center;
}
.optionalContainer {
position: relative;
/*hack to container optional text*/
padding: 20px 0;
}
.optional {
position: absolute;
top: 0;
margin: 0;
}
<form class="container">
<input required type="text"/>
<div class="optionalContainer">
<p class="optional">Optional:</p>
<input type="text"/>
</div>
<input required type="text"/>
</form>
Example of what I'm shooting for at different viewports:
Here is a solution avoid both positioning and the padding hack using flex with row-gap of the input-height:
:root {
--input-height: 21.2px;
}
.container {
display: flex;
align-items: end;
flex-wrap: wrap;
row-gap: var(--input-height);
}
<form class="container">
<input required type="text" />
<div>
<div>Optional:</div>
<input type="text" />
</div>
<input required type="text" />
</form>
Here is a another solution which avoid both positioning and the padding hack using grid and a grid-template-columns hack:
:root {
--input-width: 146.867px;
--input-height: 21.2px;
}
.container {
display: grid;
/* wrapping hack from https://stackoverflow.com/a/43664701/1248177 */
grid-template-columns: repeat(auto-fill, minmax(var(--input-width), 1fr));
row-gap: var(--input-height);
align-items: end;
}
.optionalContainer > input {
box-sizing: border-box;
width: 100%;
}
<form class="container">
<input required type="text" />
<div class="optionalContainer">
<div class="optional">Optional:</div>
<input type="text" />
</div>
<input required type="text" />
</form>

Align two element rows by second element

I have rows consisting of two elements that I'd like to align by the second element (they're input boxes, and it's nice to have them all line up vertically). The solution I behaves exactly how I want when the elements fit onto one line, I don't want to be using the width of the first element to set the horizontal position. This starts to act weird in small windows or on mobile (when the width of the label is more than 45% of the screen it starts wrapping again).
What would be the proper way to achieve the same result?
FIDDLE
HTML:
<label>Test</label>
<input type="number" value="0">
<br />
<label>Test longer</label>
<input type="number" value="0">
<br />
<label>Test longest text</label>
<input type="number" value="0">
<br />
CSS:
label {
display: inline-block;
float: left;
width: 45%;
text-align: right;
padding: 2px;
margin: 2px;
}
input {
display: inline-block;
float: left;
width: 200px;
padding: 2px;
margin: 2px;
}
You can use flex properties to display rows and columns and remove float
<div class="flex">
<label>Test</label>
<input type="number" value="0">
</div>
<div class="flex">
<label>Test longer</label>
<input type="number" value="0">
</div>
<div class="flex">
<label>Test longest text</label>
<input type="number" value="0">
</div>
in css
.flex {
display:flex;
}
label {
width: 45%;
text-align: right;
padding: 2px;
margin: 2px;
}
input {
width: 200px;
padding: 2px;
margin: 2px;
}
#media(max-width:200px){
.flex{
display:block;
}
}
and use media queries for screen below 200px(or your preference) to make the text and input appear vertically

white-space: nowrap and children with 100% width

I have some text inputs (its count may be various), I need to place them in div, stretch on all width but in one line.
<div>
<input type="text" />
<input type="text" />
<input type="text" />
</div>
div {
width: 300px;
white-space: nowrap;
}
input {
width: 100%;
display: inline-block;
}
JSFiddle
But it's not working I expected.
I don't want to set inputs' width manually (in px). Is it possible?
try this. input isnt like a div, you have to give it a display value.
input {
width: 100%;
display: inline-block; clear:both; display:block;
}
Assuming you are trying to have the inputs stretch equally in accordance with the page.
It's a matter of extending the fluid size of their container, the div, then applying the same fluid size to the inputs (assuming they are each equal) by setting their size to 33%. They will in turn stretch with the full width of the div, which will stretch with the full width of the container (or page) it's in.
div {
width: 100%;
white-space: nowrap;
}
input {
width: 33%;
display: inline-block;
}
<div>
<input type="text" />
<input type="text" />
<input type="text" />
</div>

Creating large inline forms

I have been spending the entire day trying to figure out how I can create big forms and at the same time maintain a proper design of the layout.
Currently I'm using formee (style and 960 grid system), which I have tried to turn into an inline form rather than row based (default). Unfortunately it gets really messy and looks horrible.
To give an visual understanding of what I want to archieve I have created a mockup.
How can I solve issue?
Here is such an example: http://jsfiddle.net/PhilippeVay/gaegv/2/
HTML:
<fieldset class="group">
<legend>First logical group of items</legend>
<div class="col">
<p class="text">
<label for="label1">Field label 1</label>
<input type="text" id="label1" />
</p>
<p class="text">
<label for="label2">Field label 2</label>
<input type="text" id="label2" />
</p>
<p class="text">
<label for="label3">Field label 3</label>
<input type="text" id="label3" />
</p>
</div>
<div class="col">
<p class="text">
<label for="label4">Field label 4</label>
<input type="text" id="label4" />
</p>
<p class="text">
<label for="label5">Field label 5</label>
<input type="text" id="label5" />
</p>
<p class="text">
<label for="label6">Field label 6</label>
<input type="text" id="label6" />
</p>
</div>
</fieldset>
<div class="group fieldset-like">
<p class="textarea">
<label for="label7">Field label 7</label>
<textarea id="label7">some text (test font-size)</textarea>
</p>
</div>
<div class="group">
<fieldset class="col">
<legend>Third legend</legend>
<p class="text">
<label for="label8">Field label 8</label>
<input type="text" id="label8" />
</p>
<p class="text">
<label for="label9">Field label 9</label>
<input type="text" id="label9" />
</p>
<p class="text">
<label for="label10">Field label 10</label>
<input type="text" id="label10" />
</p>
</fieldset>
<fieldset class="col">
<legend>Fourth legend</legend>
<p class="text">
<label for="label11">Field label 11</label>
<input type="text" id="label11" />
</p>
<p class="text">
<label for="label12">Field label 12</label>
<input type="text" id="label12" />
</p>
<p class="text">
<label for="label13">Field label 13</label>
<input type="text" id="label13" />
</p>
</fieldset>
</div>
CSS:
.col {
float: left;
width: 36%;
padding: 2%;
background: #EEE;
}
.col + .col {
margin-left: 10%;
}
.col:after {
content: "";
display: block;
clear: both;
}
fieldset,
.fieldset-like {
margin: 0;
padding: 0;
border: 1px solid darkgreen;
}
.group {
margin: 20px 10px; /* must come after .fieldset-like rule */
}
label {
font-weight: bold;
cursor: pointer;
}
.text { /* because .radio and .checkbox are SO different! */
clear: both;
}
.text label,
.textarea label {
display: inline-block;
width: 39%;
margin-right: 1%;
text-align: right;
background-color: lightgreen;
}
.text input,
.textarea textarea {
display: inline-block;
width: 55%;
border: 1px solid darkgreen;
padding: 4px;
}
.textarea {
width: auto;
padding: 2% 4% 2% 4%;
}
/* label and textarea: also see above */
.textarea label {
width: 14.04%; /* 39% of 36% Yeah I know... */
margin-right: 0.36%; /* 1% of 36% */
background-color: lightgreen;
vertical-align: top; /* otherwise label is at the the bottom of a very high neighbor */
}
.textarea textarea {
width: 74%;
}
a class on paragraph allows to style the label according to the nature of the form element (you can't style a preceding sibling - or a parent - according to an element that comes after it in the DOM, in 2012 and in CSS3 at least ;) ).
you can use selector attributes with modern browsers: input[type="text"] but it's longer to write in a Fiddle AND then you must consider text, password and select element in HTML 4.01 and in HTML5 add email, number, tel, etc That'll multiply the length of your selectors. Or you can use a class on a parent to distinguish and group form elements. Former is needed if you're writing a general reset stylesheet for thousands of colleagues, latter is more efficient if you're also the one writing the HTML code.
.group contains 2 .col, it doesn't matter if it's columns in a fieldset or fieldsets in a div.
calculation of a width into an element having a width means multiplication. Draw it on a sheet of paper and write down each width. It'll allow you to not forget about a single one ;)
padding in percentage doesn't seem to work for input. Not sure about that.
widths on select are easier and cross-browser if you add box-sizing:
select {
-moz-box-sizing: content-box; /* Firefox, meet padding ... */
box-sizing: content-box; /* IE8+ */
padding: 4px 6px; /* example */
}
From a UX standpoint form labels that sit to the left of the field have a lower rate of user completion. The reason for this is that users have to read the label, associate the label to the field and then move their eyes back to the left again after completing filling in of the field. This causes minor eye fatigue and mental distraction.
Forms that have the highest rate of completion is when the label is above the field. The second highest is when the label is within the field. This will also give your form a cleaner look and give the impression to the end user that, even though it might be long. It's not a daunting form to complete.

Form layout in CSS

I am trying to create tableless Form using and tags, im stuck.
I want the form look like this:
I should be able to set the width of textbox, text area and select in CSS.
Make each row a <p> containing a <label> and an <input>, both display: inline-block with preset width. (The <label> should be text-align: right)
The buttons can be float: right.
This is a good walk through: http://woork.blogspot.com/2008/06/clean-and-pure-css-form-design.html
check out working example here:
http://jsfiddle.net/bRm3P/2/
<form>
<label>To: <input type="text" /></label>
<label>Subject: <input type="text" /></label>
<label>Message: <textarea></textarea></label>
<div class="submit-container">
<input type="submit" value="submit"/><input type="submit" value="submit"/>
</div>
</form>
<style>
form {
width: 500px;
}
label {
display: block;
text-align: right;
margin-bottom: 4px;
}
label input,label textarea {
border: 1px solid #DEDEDE;
width: 80%;
vertical-align: top;
}
.submit-container {
padding-top: 4px;
text-align: right;
}
</style>
A nice semantic layout would be one of the following:
<ul>
<li><label>To <input></label></li>
...
</ul>
Or with a dl (more common):
<dl>
<dt><label>To</label></dt><dd><input></dd>
...
</dl>
You will find lots of ways to layout the latter if you google for: definition list layout form

Resources