Align labels and inputs in nested elements - css

Semantically, my data is structured something like the following:
<div class="inputs">
<div class="top">
<h4>Top</h4>
<label for="top-1">Label 1</label>
<input id="top-1"/>
<label for="top-2">Label 2 is longer than the others</label>
<input id="top-2"/>
</div>
<div class="middle">
<h4>Middle</h4>
<label for="middle-1">Label 3</label>
<select id="middle-1">
<option value="middle-value-1">Value 1</option>
<option value="middle-value-2" selected>This is a longer value</option>
</select>
<label for="middle-2">Label 4</label>
<input id="middle-2"/>
</div>
<div class="bottom">
<h4>Bottom</h4>
<label for="bottom-1">Label 5</label>
<input id="bottom-1"/>
<label for="bottom-2">Label 6</label>
<input id="bottom-2"/>
</div>
</div>
I'd like to display these as distinct but related groups. For aesthetic purposes, I'd like to align and equally size all of the inputs and selects. Is it possible to do this without using explicit widths for everything? I greatly prefer to let things size themselves whenever possible.
Below is an implementation using display: grid with fixed widths for the columns and the grid itself. Is there any way to do this with dynamic sizes?
I'm not stuck on display: grid, by the way. It's just the simplest solution I've come up with so far. I like that it helps keep my HTML simple and semantic. I can use display: table just as well if I nest the labels and inputs in a div with display: table-row. But I still can't let things size dynamically, unless I flatten it by removing the top, middle, and bottom divs.
.inputs > div {
display: grid;
grid-template-columns: 13em 10em;
width: 24em;
gap: 0.5em;
padding: 0.5em;
}
.inputs label {
grid-column: 1;
}
.inputs select, .inputs input {
grid-column: 2;
}
.inputs h4 {
grid-column: 1 / span 2;
margin: 0;
}
.top, .bottom {
background-color: #c0c0c0;
}
.middle {
background-color: #e0e0e0;
}
.middle, .bottom {
margin-top: 0.5em;
}
<div class="inputs">
<div class="top">
<h4>Top</h4>
<label for="top-1">Label 1</label>
<input id="top-1"/>
<label for="top-2">Label 2 is longer than the others</label>
<input id="top-2"/>
</div>
<div class="middle">
<h4>Middle</h4>
<label for="middle-1">Label 3</label>
<select id="middle-1">
<option value="middle-value-1">Value 1</option>
<option value="middle-value-2" selected>This is a longer value</option>
</select>
<label for="middle-2">Label 4</label>
<input id="middle-2"/>
</div>
<div class="bottom">
<h4>Bottom</h4>
<label for="bottom-1">Label 5</label>
<input id="bottom-1"/>
<label for="bottom-2">Label 6</label>
<input id="bottom-2"/>
</div>
</div>

I found a solution with display: table. It's a little uglier than the grid solution and not quite as semantic as I'd like, but it's close, and it does what I want.
.inputs {
display: table;
border-collapse: collapse;
}
.inputs > .top, .inputs > .bottom {
display: table-row-group;
background-color: #c0c0c0;
}
.inputs > .middle {
display: table-row-group;
background-color: #e0e0e0;
}
.input {
display: table-row;
}
.input > * {
display: table-cell;
}
.input > h4, .input > label {
padding: 0.5em 0.25em 0 0.5em;
}
.input > select, .input > input {
margin: 0 0.5em 0.25em 0;
box-sizing: border-box;
width: calc(100% - 0.5em);
}
.input:last-child > * {
margin-bottom: 0.5em;
}
.padding {
padding: 0.5em 0;
}
<div class="inputs">
<div class="top">
<div class="input">
<h4>Top</h4>
<div class="empty"></div>
</div>
<div class="input">
<label for="top-1">Label 1</label>
<input id="top-1"/>
</div>
<div class="input">
<label for="top-2">Label 2 is longer than the others</label>
<input id="top-2"/>
</div>
</div>
<div class="input">
<div class="padding"></div>
</div>
<div class="middle">
<div class="input">
<h4>Middle</h4>
<div class="empty"></div>
</div>
<div class="input">
<label for="middle-1">Label 3</label>
<select id="middle-1">
<option value="middle-value-1">Value 1</option>
<option value="middle-value-2" selected="selected">This is a longer value</option>
</select>
</div>
<div class="input">
<label for="middle-2">Label 4</label>
<input id="middle-2"/>
</div>
</div>
<div class="input">
<div class="padding"></div>
</div>
<div class="bottom">
<div class="input">
<h4>Bottom</h4>
<div class="empty"></div>
</div>
<div class="input">
<label for="bottom-1">Label 5</label>
<input id="bottom-1"/>
</div>
<div class="input">
<label for="bottom-2">Label 6</label>
<input id="bottom-2"/>
</div>
</div>
</div>

You can set your grid up more dynamically with something like this:
.inputs {
width: 33%;
min-width: 25em;
}
.inputs > div {
display: grid;
grid-template-columns: 1.3fr 1fr;
gap: 0.5em;
padding: 0.5em;
}
I used your outer container to deal with the width as it relates to the screen. The hard min-width of 25px keeps the long label from wrapping to another line, instead showing a horizontal scrollbar if the screen size causes 33% of the width to go below 25px.
For your inner containers, you can change the unit in grid-template-columns to fr, which means fraction of available space. This will let your columns dynamically size along with your window (until you hit the min-width for the outer container). You can experiment with the width percentage to work out just how much dynamic sizing you would like to do.
This is a good writeup of fr if you would like one.

Related

bootstrap 5: display multiple form input-group inline

How can one display multiple form input-groups inline with Bootstrap 5?
Tried this, but input group components show on top of each other:
<div class="container">
Your username is
<div class="input-group form-control-inline">
<span class="input-group-text">#</span>
<input type="text" class="form-control " placeholder="Username">
</div>
and your email <is></is>
<div class="input-group form-control-inline">
<input type="text" class="form-control form-control-inline" placeholder="">
<span class="input-group-text">#example.com</span>
</div>
</div>
.form-control-inline {
display: inline-block;
width: auto;
vertical-align: middle;
margin-top: -8px;
}
.form-control-inline.form-control, .form-control-inline.input-group-text {
display: inline-block;
}
Fiddle: https://jsfiddle.net/46se871g/
I used flex to help me achieve what you need. as flex gives more controls from the parent to the entire child for your HTML. read more details for flex.
Also, I moved the text into the .input-group class to have every div with all of it's content.
HTML:
<div class="container">
<div class="input-group">
Your username is
<span class="input-group-text">#</span>
<input type="text" class="form-control" placeholder="Username">
</div>
<div class="input-group">
and your email <is></is>
<input type="text" class="form-control form-control-inline"
placeholder="">
<span class="input-group-text">#example.com</span>
</div>
</div>
CSS:
.input-group {
display: flex;
align-items: center
}
.container {
display: flex;
grid-template-columns: repeat(1, 1fr);
align-items: center;
}

Pure CSS (no jQuery), hide one div, show another?

I want to do something like this, but i want the Collapse 2 to stay right under Collapse 1 when I show Content 1. Is that possible? I tried to arrange the code differently, but it just went crazy. :D
.collapse{
cursor: pointer;
display: block;
background: #cdf;
}
.collapse + input{
display: none; /* hide the checkboxes */
}
.collapse + input + div{
display:none;
}
.collapse + input:checked + div{
display:block;
}
<label class="collapse" for="_1">Collapse 1</label>
<input id="_1" type="radio" name="c1">
<div>Content 1</div>
<label class="collapse" for="_2">Collapse 2</label>
<input id="_2" type="radio" name="c1">
<div>Content 2</div>
A little bit tricky but its work!
section {
position: relative;
}
section > .content {
position: absolute;
top:100%;
left: 0;
}
.collapse{
cursor: pointer;
display: block;
background: #cdf;
}
.collapse + input{
display: none; /* hide the checkboxes */
}
.collapse + input + div{
display:none;
}
.collapse + input:checked + div{
display:block;
}
<section>
<label class="collapse" for="_1">Collapse 1</label>
<input id="_1" type="radio" name="c1">
<div class="content">Content 1</div>
<label class="collapse" for="_2">Collapse 2</label>
<input id="_2" type="radio" name="c1">
<div class="content">Content 2</div>
</section>
Fiddle demo
Your code actually works great. As far as making the content show up after the labels, that just means we have to change the HTML order, which means we cannot use the plus(adjacent sibling selector). instead we use general sibling selector (~) you can read more about that here http://www.w3schools.com/css/css_combinators.asp
Here is an example of your code using the tilde. note the content divs now need some kind of unique identifier like a class.
.collapse{
cursor: pointer;
display: block;
background: #cdf;
}
input{
display: none; /* hide the checkboxes */
}
input ~ .content{
display:none;
}
input#_1:checked ~ .content1, input#_2:checked ~ .content2{
display:block;
}
<label class="collapse" for="_1">Collapse 1</label>
<input id="_1" type="radio" name="c1">
<label class="collapse" for="_2">Collapse 2</label>
<input id="_2" type="radio" name="c1">
<div class="content content1">Content 1</div>
<div class="content content2">Content 2</div>

Bootstrap - Two column layout with text between the columns

Trying to create a layout that has two columns, and text between those columns
Something like this:
But I am running into spacing issues with twitter bootstrap to make it actually work. On top of making these items the same width with the text between, they should all be vertically aligned.
You can do that using 3 columns
Live Demo jsfiddle
<div class="container-fluid">
<div class="row">
<div class="col-xs-6">.col-sm-6</div>
<div class="col-xs-6">.col-sm-6</div>
</div>
<br/>
<p>Create an account...............................</p>
<div class="row">
<div class="col-xs-6 test" >
<form class="form-horizontal vmid" role="form">
<div class="form-group">
<label class="control-label col-sm-2" for="email">Email:</label>
<div class="col-sm-10">
<input type="email" class="form-control" id="email" placeholder="Enter email"/>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="pwd">Password:</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="pwd" placeholder="Enter password"/>
</div>
</div></form>
</div>
<div class="col-xs-1 test" >
<p class="asd"> ~OR~</p>
</div>
<div class="col-xs-5 test" >
<button type="submit" class="asd btn-primary btn-lg">Facebook</button>
</div>
</div>
</div>
Style
.vmid{
position:relative;
top:50%;
transform:translateY(-50%);
}
.asd{
position:relative;
top:50%;
transform:translateY(-35%);
}
This is not a bootstrap answer just a plain simple CSS one. Although you can adapt it to bootstrap easily because the basic underlying principle is the same. Instead of using width percentages that I have used in my example, bootstrap grid system columns can be used instead. Saying all that, you can achieve your desired effect by dividing the wrapper div into 3 columns and then using the display table for parent and table-cell and vertical align middle for the child to place the respective input elements and button elements in its place as needed.
The fiddle can be found here
The code snippet follows...
.wrapper {
height: 300px;
width: 100%;
background: pink;
}
.leftSide,
.rightSide,
.midPart {
box-sizing: border-box;
height: 100%;
display: table;
}
.leftSide {
width: 45%;
background: lightgray;
float: left;
}
.midPart {
width: 10%;
background: aqua;
}
.midPart p {
display: table-cell;
vertical-align: middle;
text-align: center;
}
.leftSide div,
.rightSide div {
display: table-cell;
vertical-align: middle;
text-align: center;
}
.rightSide {
width: 45%;
background: lightcyan;
float: right;
}
button {
height: 3em;
width: 100px;
background: blue;
color: white;
}
<div class="wrapper">
<div class="leftSide">
<div>
<input placeholder="Enter Username" />
<br/>
<br/>
<input placeholder="Enter password" />
</div>
</div>
<div class="rightSide">
<div>
<button>Hello</button>
</div>
</div>
<div class="midPart">
<p>-or-</p>
</div>
</div>
Hope this helps. Happy coding :)
Update::
***Another updated Fiddle without colors***

Inline div not wrapping correctly

I have a series of inline divs that aren't wrapping correctly. As the browser is resized, the divs should be aligning flush left but sometimes they are flush right. I've read several articles on this but they don't seem to be the same issue. Any help would be much appreciated. My jsfiddle is http://jsfiddle.net/7uuLaLg4/.
<style type="text/css">
.box
{
float: left;
border: 1px solid black;
}
.address .item
{
display: inline;
float: left;
}
</style>
<div class="box">
<div class="address">
<div class="item">
<div>Address (Number & Road) <label class="required">*</label></div>
<div><input id="User_Address_Address1" name="User.Address.Address1" style="width: 13em;" type="text" value="1 Main St." /></div>
</div>
<div class="item">
<div>Address 2 (APT, Suite...)</div>
<div><input id="User_Address_Address2" name="User.Address.Address2" type="text" value="" /></div>
</div>
<div class="item">
<div>City<label class="required">*</label></div>
<div><input id="User_Address_City" name="User.Address.City" type="text" value="Anytown" /></div>
</div>
<div class="item">
<div>State<label class="required">*</label></div>
<div>
<select id="User_Address_StateID" name="User.Address.StateID">
<option selected="selected" value="3">Kentucky</option>
</select>
</div>
</div>
<div class="item">
<div>Zip<label class="required">*</label></div>
<div><input class="zip-mask" id="User_Address_Zip" maxlength="5" name="User.Address.Zip" style="width: 5em;" type="text" value="12345" /></div>
</div>
<div class="item">
<div>County<label class="required">*</label></div>
<div>
<select id="User_Address_CountyID" name="User.Address.CountyID">
<option value="0"></option>
<option selected="selected" value="125542">Campbell</option>
</select>
</div>
</div>
<div class="item">
<div>Country<label class="required">*</label></div>
<div>
<select id="User_Address_CountryID" name="User.Address.CountryID">
<option value="0"></option>
<option selected="selected" value="1">United States</option>
</select>
</div>
</div>
</div>
</div>
Here is fixed example.
http://jsfiddle.net/7uuLaLg4/2/
.box{
border: 1px solid black;
text-align: left;
}
.address .item{
display: inline-block;
margin: 0 0 10px 0;
}
They are not all the same height which is why sometimes they act like they are floating right.
Something like min-height: 60px; should help.
.address .item {
display: inline-block;
min-height: 60px;
}
http://jsfiddle.net/bb1ooguo/1/

Bootstrap centre horizontal form

I'm trying to centre a horizontal form in a hero unit, by setting text-align:center; and then display:block-inline;
See jsfiddle for a demo http://jsfiddle.net/bVJZ2/
But this hasn't quite worked in that the checkbox and submit button are not correctly aligned any more. Any suggestions how to fix this?
There are some problems that doesn't allow you to center the checkbox.
<div class="controls"> has a margin-left. You shouldn't put your checkbox inside a that div.
The input[checkbox] has a float: left. You should remove that float with:
.radio input[type="radio"], .checkbox input[type="checkbox"] {
float: none;
}
The checkbox is bad aligned. You should add vertical-align: top to the last selector.
To sum up:
HTML:
<div class="control-group">
<label class="checkbox">
<input type="checkbox"> Remember me
</label>
<button type="submit" class="btn">Sign in</button>
</div>
CSS:
.radio input[type="radio"], .checkbox input[type="checkbox"] {
float: none;
vertical-align: top;
}
You can see the result here: http://jsfiddle.net/GW8zk/
Well This is how you can implement a Hero-unit with form centered in middle .
JSFiddle with centered form http://jsfiddle.net/shail/YmmVS/
First the css :
.hero-unit {
padding:50px 50px 50px 50px;
}
.form-horizontal .control-label {
width: 61px;
}
.form-horizontal .controls {
margin-left: 80px;
}
/* Landscape phones and down */
#media (max-width: 480px) {
.hero-unit{
margin-left:-20px;
margin-right:-20px;
}
.form-horizontal .controls {
margin-left: 0;
}
}
The Html Part :
<div class="container">
<div class="hero-unit">
<div class="row-fluid">
<div class="offset4 span4">
<legend>Sign in to WebApp</legend>
<form class="form-horizontal">
<div class="control-group">
<label class="control-label" for="inputEmail">Email</label>
<div class="controls">
<input type="text" id="inputEmail" placeholder="Email">
</div>
</div>
<div class="control-group">
<label class="control-label" for="inputPassword">Password</label>
<div class="controls">
<input type="password" id="inputPassword" placeholder="Password">
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox">
<input type="checkbox">Remember me</label>
<button type="submit" class="btn">Sign in</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>

Resources