Why does using an input group break the baseline alignment in bootstrap? - html

If I have a form with a label next to an input, in plain HTML, and both are inline (or inline block), then they are aligned by their baseline. But when using bootstrap and putting the input in an input group, it seems they get aligned by their bottom.
I tried to replicate this without bootstrap, but I couldn't, it just works. I created fiddle to show the problem:
http://jsfiddle.net/pupeno/9aJCF/3/
The HTML is:
<p>A case working, with just an input:</p>
<div class="form-group without-input-group">
<label>label</label>
<input type="text" class="form-control" value="value" />
</div>
<hr/>
<p>A case broken with the same HTML structure, but not using bootstrap:</p>
<div class="without-bootstrap">
<label>label</label>
<div class="group">
<input type="text" class="form-control" value="value" />
<span>addon</span>
</div>
</div>
<hr/>
<p>The broken situation, with the input group:</p>
<div class="form-group with-input-group">
<label>label</label>
<div class="input-group">
<input type="text" class="form-control" value="value" />
<span class="input-group-addon">addon</span>
</div>
</div>
and the CSS:
.without-input-group input {
max-width: 250px;
display: inline-block;
}
.without-bootstrap .group {
max-width: 250px;
display: inline-table;
}
.without-bootstrap .group input {
display: table-cell;
}
.without-bootstrap .group span {
display: table-cell;
}
.with-input-group .input-group {
max-width: 250px;
display: inline-table;
}

Because the input group is display: inline-table; and the label is outside the input-group.
If you inspect the input-group-addon element, you see that it is set to display: table-cell; and vertical-align: middle;.
If you move the label inside the input-group and style it same as the input-group-addon it lines up correctly.
<div class="form-group with-input-group">
<div class="input-group">
<label>label</label>
<input type="text" class="form-control" value="value" />
<span class="input-group-addon">addon</span>
</div>
</div>
.
.input-group label {
padding: 4px;
display: table-cell;
vertical-align: middle;
}
http://jsfiddle.net/N62he/

Related

Label sticking next to another label

I am having a simple registration form, but one of the label fields sticks next to another label field.
Currently it looks like this:
Email should be under the Username, not next to it. Other form elements align nicely, but not these two.
label {
float: left;
}
input {
float: right;
}
<div class="form-wrapper">
<div>
<div>
<label for="user-name">Username:</label>
<input type="text" id="user-name" name="user-name" required>
</div>
<div>
<label for="user-email">Email:</label>
<input type="email" id="user-email" name="user-email" required>
</div>
</div>
</div>
Why don't you just use flex, clean and less code.
.form-wrapper {
width: 400px;
border: 1px solid blue;
}
.username,
.useremail {
display: flex;
margin: 10px;
width: 350px;
justify-content: space-between;
font-weight: bold;
}
<div class="form-wrapper">
<div>
<div class="username">
<label for="user-name">Username:</label>
<input type="text" id="user-name" name="user-name" required>
</div>
<div class="useremail">
<label for="user-email">Email:</label>
<input type="email" id="user-email" name="user-email" required>
</div>
</div>
</div>
If you are going with float you have to know about using clear property for it's next elements. So a best way to handle is, to create a after pseudo-element on the parent and clear:both.
In the below code have added 'field' class for each container and styled it with :after.
.field::after{
content: '';
display: block;
height: 0;
clear: both;
visibility: hidden;
}
label {
float: left;
}
input {
float: right;
}
<div class="form-wrapper">
<div>
<div class="field">
<label for="user-name">Username:</label>
<input type="text" id="user-name" name="user-name" required>
</div>
<div class="field">
<label for="user-email">Email:</label>
<input type="email" id="user-email" name="user-email" required>
</div>
</div>
</div>
Labels and input fields are stacked from the left and the right, resp., due to the css float properties. Note that the label/input pairs render on individual lines when removing the css, though without proper vertical alignment.
The CSS display: table property and friends can be employed to rectify this. Basically they cause the renderer to apply table layouting to elements other than tableand descendants.
.d-t {
display: table;
}
.d-tr {
display: table-row;
}
.d-tr > label, .d-tr > input {
display: table-cell;
}
<div class="form-wrapper">
<div class="d-t">
<div class="d-tr">
<label for="user-name">Username:</label>
<input type="text" id="user-name" name="user-name" required>
</div>
<div class="d-tr">
<label for="user-email">Email:</label>
<input type="email" id="user-email" name="user-email" required>
</div>
</div>
</div>

How can I make input fields line up next to the middle of the labels?

Here's an example of the problem I am facing:
https://jsfiddle.net/v10un11s/1/
This is my HTML:
<div>
<div class="component">
<div>
<label for="test1" id="short-label">Short label: </label>
</div>
<div>
<input type="text" id="test1" />
</div>
</div>
<div class="component">
<div>
<label for="test2" id="long-label">This is my very very very very very very very very very very very very very very very very very very long label: </label>
</div>
<div>
<input type="text" id="test2" />
</div>
</div>
</div>
My css:
.
component > div:first-child {
width: 150px;
text-align: right;
margin-right: 5px;
margin-bottom: 10px;
}
.component > div {
display: inline-block;
}
This results in the input field lining up to the right of the labels. This is what I want, however, it lines at the end of the line of a very long label.
What I really want is that the input field line to the right AND to the relative middle of the label.
So in the JS Fiddle example above, I would want the input field to line up to the right of the third line of the long label.
I've been playing around with margins, paddings, line-height, etc etc, and I've not been able to figure out the correct solution.
Just one line of CSS should do the trick!
.component > div {
display: inline-block;
vertical-align: middle;
}
Just remember, this works both ways - so if your input is taller than your label, the label will center to the input.
You can use Flexbox and set align-items: center on .component
.component {
display: flex;
align-items: center;
}
.component > div:first-child {
width: 150px;
text-align: right;
}
<div>
<div class="component">
<div>
<label for="test1" id="short-label">Short label:</label>
</div>
<div>
<input type="text" id="test1" />
</div>
</div>
<div class="component">
<div>
<label for="test2" id="long-label">This is my very very very very very very very very very very very very very very very very very very long label:</label>
</div>
<div>
<input type="text" id="test2" />
</div>
</div>
</div>

"Fluid" hanging indent in CSS

On a website, I would like this layout:
Some text [input 1]
[input 2]
I want:
the first input to be placed where the next word would appear and the distance between "text" and "[input 1]" to be one space
the second input to be placed below the first and aligning with it
both inputs moving to the left or right if the text width changes
Here is what I tried, but did not succeed:
When I surround the two inputs in a DIV, without any styling, it looks like this:
Some text
[input 1]
[input 2]
When I style the DIV as display: inline-block, it looks like this, i.e. the text drops to the bottom:
[input 1]
Some text [input 2]
When I style the DIV as display: inline or float the text to the left, it looks like this:
Some text [input 1]
[input 2]
When I style the div with margin left, I get:
Text [input 1]
[input 2]
i.e. the position does not change when I change the text width.
I can easily do this with tables. Please show me how to do it in CSS, without JavaScript. Thank you.
DEMO
HTML
<div>
<div id="text-container">
Some text
</div>
<div id="input-container">
<input />
<input />
</div>
</div>
CSS
#text-container:after {
content:"\00a0"; /*spacing*/
}
#text-container,
#input-container {
display:inline-block;
vertical-align:top;
}
#input-container input {
display:block;
}
This is repeatable and responsive!
Live demo (click).
<form>
<div>
<label>Set One</label>
<label>Set Two</label>
<label>Set Three</label>
</div>
<div class="inputs">
<input type="text" placeholder="set 1">
<input type="text" placeholder="set 1">
<input type="text" placeholder="set 2">
<input type="text" placeholder="set 2">
<input type="text" placeholder="set 3">
<input type="text" placeholder="set 3">
</div>
</form>
CSS:
form {
position: relative;
}
form div {
display: inline-block;
vertical-align: top;
}
label, input {
display: block;
}
label {
margin-top: 26px;
}
label:first-child {
margin-top: 0;
}
#media (max-width: 300px) {
label {
margin-bottom: 62px;
}
form .inputs {
display: block;
position: absolute;
top: 0;
}
input {
margin-top: 20px;
}
}
This is probably really the easiest way, which is to emulate a table using CSS and a few more non-semantic elements. Live demo (click).
<form class="table">
<div class="row">
<label class="cell">Set One</label>
<div class="cell">
<input type="text" placeholder="set 1">
<input type="text" placeholder="set 1">
</div>
</div>
<div class="row">
<label class="cell">Set Two</label>
<div class="cell">
<input type="text" placeholder="set 2">
<input type="text" placeholder="set 2">
</div>
</div>
</form>
CSS:
.table {
display: table;
}
.row {
display: table-row;
}
.cell {
display: table-cell;
}
input {
display: block;
}
#media (max-width: 300px) {
.cell {
display: block;
}
}
A version using CSS3 flexbox:
DEMO
Works even when inputs are inline elements and they wrap.
HTML
<div class="flexbox">
<div>
Some text
</div>
<div class="inputs">
<input />
<input />
</div>
</div>
CSS
.flexbox { display: flex }
.inputs input { display: block }

Vertically align horizontal inline-block elements

I've got a checkbox group. Which are centrally aligned with checkboxes on top and text below. Here is what I mean :
So I want to align
So each checkbox + label is wrapped in a div with class choice. All choice divs are part of div with additional-info. choice divs are inline-block elements with fixed width.
How do I align div choice to be in the same height as the first one?
I've tried setting the additional-info position to relative and choice to absolute. But then they overlap each other so that wasn't good.
Also tried setting the choice div display to inline but then the current layout breaks and divs are displayed in the middle in three rows.
Also tried to set additional-info display to table-cell and adding vertical-align top but that didn't work either.
What else can I try? any suggestions is welcome
Update :
Here is my HTML :
<div class="additional-info">
<p class="text required control-label">
Additional info
</p>
<div class="input boolean optional certificate"><input name="user[certificate]" type="hidden" value="0"><label class="boolean optional control-label checkbox" for="certificate"><input class="boolean optional require-one" id="certificate" name="user[certificate]" type="checkbox" value="1">I've got a valid certificate and permits</label></div>
<div class="input boolean optional no_garden"><input name="user[no_garden]" type="hidden" value="0"><label class="boolean optional control-label checkbox" for="no_garden"><input class="boolean optional require-one" id="no_garden" name="user[no_garden]" type="checkbox" value="1">I don't have garden</label></div>
<div class="input boolean optional has_garden"><input name="user[has_garden]" type="hidden" value="0"><label class="boolean optional control-label checkbox" for="has_garden"><input class="boolean optional require-one" id="has_garden" name="user[has_garden]" type="checkbox" value="1">I have a garden</label></div>
</div>
Some css :
.additional-info {
position: relative;
}
.additional-info div {
width: 32.6%;
display: inline-block;
text-align: center;
}
input[type="checkbox"] {
float: none;
display: block;
margin: 0 auto;
}
You can take a look here, I've made it from scratch...
So what I did here is, I've used display: table; for the container element and am using display: table-cell; for the child div and as the child div are now table cells, I used vertical-align: top; so that the elements align to the top in those cells
section {
display: table;
width: 100%;
}
section > div {
vertical-align: top;
display: table-cell;
width: 33%;
text-align: center;
}
<h4>Additional Info</h4>
<section>
<div>
<input type="checkbox" /><br />
<label for="">I've got a valid certificate permits</label>
</div>
<div>
<input type="checkbox" /><br />
<label for="">I've got a valid certificate</label>
</div>
<div>
<input type="checkbox" /><br />
<label for="">I certificate</label>
</div>
</section>
Why not use a simple float to get rid of the remaining 'white space':
.additional-info div {
width: 32.6%;
/*display: inline-block;*/
text-align: center;
float: left;
}
.additional-info {
position: relative;
}
.additional-info div {
width: 32.6%;
/*display: inline-block;*/
text-align: center;
float: left;
}
input[type="checkbox"] {
float: none;
display: block;
margin: 0 auto;
}
<div class="additional-info">
<p class="text required control-label">Additional info</p>
<div class="input boolean optional certificate">
<input name="user[certificate]" type="hidden" value="0">
<label class="boolean optional control-label checkbox" for="certificate">
<input class="boolean optional require-one" id="certificate" name="user[certificate]" type="checkbox" value="1">I've got a valid certificate and permits</label>
</div>
<div class="input boolean optional no_garden">
<input name="user[no_garden]" type="hidden" value="0">
<label class="boolean optional control-label checkbox" for="no_garden">
<input class="boolean optional require-one" id="no_garden" name="user[no_garden]" type="checkbox" value="1">I don't have garden</label>
</div>
<div class="input boolean optional has_garden">
<input name="user[has_garden]" type="hidden" value="0">
<label class="boolean optional control-label checkbox" for="has_garden">
<input class="boolean optional require-one" id="has_garden" name="user[has_garden]" type="checkbox" value="1">I have a garden</label>
</div>
</div>
I have done an inline-block level based on what you said above. Using a set width on the parent div and then child elements forces the items to stack rather than appear in a horizontal list.
<div style="display:inline-block; width:150px;">
<div style="display:inline-block; width:150px;"><input /></div>
<div style="display:inline-block; width:150px;"><input /></div>
<div style="display:inline-block; width:150px;"><input /></div>
<div style="display:inline-block; width:150px;"><input /></div>
</div>
Worth trying to see if it works for your form?
(I know I've done it here as inline-style, but this is just as an example I quickly put together)

Style input element to fill remaining width of its container

Let's say I have an html snippet like this:
<div style="width:300px;">
<label for="MyInput">label text</label>
<input type="text" id="MyInput" />
</div>
This isn't my exact code, but the important thing is there's a label and a text input on the same line in a fixed-width container. How can I style the input to fill the remaining width of the container without wrapping and without knowing the size of the label?
Here is a simple and clean solution without using JavaScript or table layout hacks. It is similar to this answer: Input text auto width filling 100% with other elements floating
It is important to wrap the input field with a span which is display:block. Next thing is that the button has to come first and the the input field second.
Then you can float the button to the right and the input field fills the remaining space.
form {
width: 500px;
overflow: hidden;
background-color: yellow;
}
input {
width: 100%;
}
span {
display: block;
overflow: hidden;
padding-right:10px;
}
button {
float: right;
}
<form method="post">
<button>Search</button>
<span><input type="text" title="Search" /></span>
</form>
A simple fiddle: http://jsfiddle.net/v7YTT/90/
Update 1: If your website is targeted towards modern browsers only, I suggest using flexible boxes. Here you can see the current support.
Update 2: This even works with multiple buttons or other elements that share the full with with the input field. Here is an example.
as much as everyone hates tables for layout, they do help with stuff like this, either using explicit table tags or using display:table-cell
<div style="width:300px; display:table">
<label for="MyInput" style="display:table-cell; width:1px">label text</label>
<input type="text" id="MyInput" style="display:table-cell; width:100%" />
</div>
I suggest using Flexbox:
Be sure to add the proper vendor prefixes though!
form {
width: 400px;
border: 1px solid black;
display: flex;
}
input {
flex: 2;
}
input, label {
margin: 5px;
}
<form method="post">
<label for="myInput">Sample label</label>
<input type="text" id="myInput" placeholder="Sample Input"/>
</form>
Please use flexbox for this. You have a container that is going to flex its children into a row. The first child takes its space as needed. The second one flexes to take all the remaining space:
<div style="display:flex;flex-direction:row">
<label for="MyInput">label text</label>
<input type="text" id="MyInput" style="flex:1" />
</div>
Easiest way to achieve this would be :
CSS :
label{ float: left; }
span
{
display: block;
overflow: hidden;
padding-right: 5px;
padding-left: 10px;
}
span > input{ width: 100%; }
HTML :
<fieldset>
<label>label</label><span><input type="text" /></span>
<label>longer label</label><span><input type="text" /></span>
</fieldset>
Looks like : http://jsfiddle.net/JwfRX/
Very easy trick is using a CSS calc formula. All modern browsers, IE9, wide range of mobile browsers should support this.
<div style='white-space:nowrap'>
<span style='display:inline-block;width:80px;font-weight:bold'>
<label for='field1'>Field1</label>
</span>
<input id='field1' name='field1' type='text' value='Some text' size='30' style='width:calc(100% - 80px)' />
</div>
you can try this :
div#panel {
border:solid;
width:500px;
height:300px;
}
div#content {
height:90%;
background-color:#1ea8d1; /*light blue*/
}
div#panel input {
width:100%;
height:10%;
/*make input doesnt overflow inside div*/
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
/*make input doesnt overflow inside div*/
}
<div id="panel">
<div id="content"></div>
<input type="text" placeholder="write here..."/>
</div>
The answers given here are a bit outdated. So, here I'm with the easiest solution using modern flexbox.
.input-container{
display:flex;
}
input{
flex-grow: 1;
margin-left: 5px;
}
<div style="width:300px;">
<div class="input-container">
<label for="MyInput">label text: </label>
<input type="text" id="MyInput"/>
</div>
<div class="input-container">
<label for="MyInput2">Long label text: </label>
<input type="text" id="MyInput2" />
</div>
</div>
If you're using Bootstrap 4:
<form class="d-flex">
<label for="myInput" class="align-items-center">Sample label</label>
<input type="text" id="myInput" placeholder="Sample Input" class="flex-grow-1"/>
</form>
Better yet, use what's built into Bootstrap:
<form>
<div class="input-group">
<div class="input-group-prepend">
<label for="myInput" class="input-group-text">Default</label>
</div>
<input type="text" class="form-control" id="myInput">
</div>
</form>
https://jsfiddle.net/nap1ykbr/