"Fluid" hanging indent in CSS - html

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 }

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>

CSS - Align div elements in three columns

I am trying to align a list of labels, input radios and icons. The alignment should be:
Label Icon
() LongLabel Icon
() Label Icon
Here my code:
div.mygrid {
display:grid;
grid-template-columns: max-content max-content;
grid-gap:5px;
}
div.mygrid > div > label { text-align:left; }
<div class="mygrid">
<div>
<label> Long Text #1</label>
<i>Colum2</i>
</div>
<div>
<label><input type="radio">Label #2</label>
<i>Colum2</i>
</div>
<div>
<label><input type="radio">Label #3</label>
<i>Colum2</i>
</div>
</div>
Also I find awful to define spaces to replace the space of the radiobutton:
<label> Long Text #1</label>
Any idea how can I achieve that?
If you don't insist on using Grid, I propose a solution similar to the following (should be self-explanatory). Adjust values (width and padding) as needed.
label {
text-align: left;
display: inline-block;
width: 160px;
}
label.L1 {
padding-left: 30px;
}
input[type="radio"] {
width: 30px;
margin: 0;
}
i {
width: 200px;
}
<div class="mygrid">
<div>
<label class="L1">Long Text #1</label>
<i>Colum2</i>
</div>
<div>
<input type="radio"><label>Label #2</label>
<i>Colum2</i>
</div>
<div>
<input type="radio"><label>Label #3</label>
<i>Colum2</i>
</div>
</div>
div.mygrid {
display:flex;
flex-direction: column;
}
div.mygrid > div > label { text-align:left; }
.ml-3 {
margin-left: 17px;
}
<div class="mygrid">
<div class="ml-3">
<label>Long Text #1</label>
<i>Colum2</i>
</div>
<div>
<label><input type="radio">Label #2</label>
<i>Colum2</i>
</div>
<div>
<label><input type="radio">Label #3</label>
<i>Colum2</i>
</div>
</div>

Add '*' to the label of input fields with the 'required' attribute with CSS

I am wondering if there is a way using only CSS to add an asterisk to a label element when the label's for attribute is for an input element with a required html attribute. Alternatively, we could use logic around if the label is directly followed by an input element which has the required attribute.
What does work is something like this:
input[required] + label:after {
content: '*';
color: red;
}
<form>
<div>
<input for="name" type="text" required />
<label id="name">Name</label>
</div>
<div>
<input for="age" type="text" />
<label id="age">Age</label>
</div>
</form>
But what I'm talking about is if the label and input are swapped around like the example below, which is more common. The CSS sibling selector + doesn't work for this case. Is there any way to do some like above when the label element is first and the input is second?
/* ??? */
<form>
<div>
<label for="name">Name</label>
<input id="name" type="text" required />
</div>
<div>
<label for="age">Age</label>
<input id="age" type="text" />
</div>
</form>
Thanks
I suggest you keep old html and use css flex to order position
input[required] + label:after {
content: '*';
color: red;
}
div {
display: flex;
text-align: center;
align-items: flex-start;
}
div input {
width: 100px;
height: 20px;
order: 2;
}
div label {
width: 100px;
height: 20px;
order: 1;
}
<form>
<div>
<input for="name" type="text" required />
<label id="name">Name</label>
</div>
<div>
<input for="age" type="text" />
<label id="age">Age</label>
</div>
</form>
See the codepen
You can use float for label to positining label at left like below:
label {
float: left;
}
input[required] + label:after {
content: '*';
color: red;
}
}
<form>
<div>
<input for="name" type="text" required />
<label id="name">Name</label>
</div>
<div>
<input for="age" type="text" />
<label id="age">Age</label>
</div>
</form>
There is no way for CSS to "render backwards" the way you want it too (not without SASS/SCSS).
One solution would be to add a "required" class to the labels that correspond to required fields.
<style>
label.required:after { content: '*';color:red; }
</style>
<form>
<div>
<label for="name" class="required">Name</label>
<input id="name" type="text" required />
</div>
<div>
<label for="age">Age</label>
<input id="age" type="text" />
</div>
</form>
Another option is the use of CSS3 Orders property, but the parent element would need to be set to "display:flex".
<style>
div { display:-webkit-flex;display:flex; }
div label { order:1; }
div input { order:2; }
div input[required] + label:after { content: '*';color:red; }
</style>
<form>
<div>
<input id="name" type="text" required />
<label for="name">Name</label>
</div>
<div>
<input id="age" type="text" />
<label for="age">Age</label>
</div>
</form>
EDIT 6/25/2019 SASS/SCSS Example
div {
display:-webkit-flex;
display:flex;
label {
order:1;
}
input {
order:2;
&[required] + label:after {
content: '*';color:red;
}
}
}
More information about Parent Selectors in SCSS.

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>

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

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/