This question already has an answer here:
Why are not all flexbox elements behaving like flexbox divs?
(1 answer)
Closed 8 years ago.
I want to use the flex display property on my web form in order to have two text fields side-by side and automatically growing to fill the space. I chose to use flex over a table layout because I want them to move to their own line when the window shrinks.
I believe I am misunderstanding how to use flexbox.
Below is my work so far (simplified for posting here). I am using a fieldset as a flex parent, and each form element which should "grow" side-by-side is encased in a div (set to display: inline so they can be on the same line). I also have a legend for the fieldset, set to display:block and width:100% so that it will be on its own line.
jsFiddle link
fieldset {
display: flex;
flex-direction: row;
justify-content: space-between;
border: none;
}
label {
display: none;
}
legend {
display: block;
width: 100%;
}
fieldset > div {
display: inline;
flex: 1 1 auto;
}
input {
width: 100%;
}
<form>
<fieldset>
<legend>These are Text Fields</legend>
<div>
<input type="text" id="text1">
<label for="text1">Text Field</label>
</div>
<div>
<input type="text" id="text2">
<label for="text2">More Text</label>
</div>
</fieldset>
</form>
As you can see, the divs are each on their own line (despite the display: inline and flexbox stuff). If you add a border to the div elements, you'll see that they are 100% width right now; but even if you manually define a width (like 30%), they remain on their own lines.
How can I use flex to display the divs side-by-side and allow them to scale to fill the parent's width?
EDIT: This bug has been fixed in Firefox and Chrome. The example as originally posted in the question now works as intended.
https://bugzilla.mozilla.org/show_bug.cgi?id=1230207
https://bugs.chromium.org/p/chromium/issues/detail?id=375693
Two things here:
When you do display: flex on an element, every single direct child is affected. So in your example (if it were working) the legend will also be displayed on the same line.
For whatever reason, fieldset doesn't like to play nicely with flexbox. since you don't want the legend to be on the same line anyway, I would suggest specifically wrapping the elements you want to be on the same line.
<form>
<fieldset>
<legend>These are Text Fields</legend>
<div class="flex-wrapper">
<div>
<input type="text" id="text1">
<label for="text1">Text Field</label>
</div>
<div>
<input type="text" id="text2">
<label for="text2">More Text</label>
</div>
</div>
</fieldset>
</form>
fieldset {
border: none;
}
.flex-wrapper {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: stretch;
}
.flex-wrapper > div {
flex: 1 1 auto;
}
label {
display: none;
}
legend {
display: block;
width: 100%;
}
input {
width: 100%;
}
Related
This question already has answers here:
In CSS Flexbox, why are there no "justify-items" and "justify-self" properties?
(6 answers)
Closed 1 year ago.
I don't understand Why justify-content:center not working?
I think it's a inputs width issue i already tried give width to input fields but still not working.
Here is my code:
.container {
width: 100vw;
}
.container form {
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
}
.container form input {
width: 80%;
}
<div class="container">
<form action="" method="post" novalidate>
<div>
<label for="my_username">Username:</label>
<input type="text" name="username" class="inputs" autofocus required id="my_username">
</div>
<div>
<label for="my_email">Email:</label>
<input type="email" name="email" maxlength="254" id="my_email">
</div>
<div>
<label for="my_password1">Password1:</label>
<input type="password" name="password1" class="inputs" required id="my_password1">
</div>
<div>
<label for="my_password2">Confirm Password:</label>
<input type="password" name="password2" class="inputs" required id="my_password2">
</div>
</form>
</div>
justify-content defines the alignment along the main axis (in your case column. So you are centering the content within its row.
It also works only for the direct decendents of the flex container (in this case the div elements that are direct children of the form. If you change justify-content to align-items (which works for the cross-axis) then this should center the div elements horizontally, and then you can add the css to align the label and input elements within those divs.
There's a really good guide available for the properties of flex-box and what they affect here.
.container {
width: 100vw;
}
.container form {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
.container form input {
width: 80%;
}
It can be solved if you use align-items instead of justify-content. It's because of justify-content works in main axis and align-items in cross-axis, perpendicular to the main axis.
.container form {
display: flex;
flex-direction: column;
align-items: center;
}
This question already has answers here:
Center one and right/left align other flexbox element
(11 answers)
Closed 2 years ago.
The header is aligning to the center, and the checkbox-div to the next line, what css should i use to align the checbox-div to the right end on the same line as the header!
Here is the sample code!
<div class="header-wrapper">
<h2 class="header">Header</h2>
<div class="checkbox-div">
<input type="checkbox" class="checkbox" value="Some Value" id="checkbox">
<label for="sub-folder-checkbox">Some Name</label>
</div>
</div>
Currently the css am using is,
.header {
text-align: center;
}
Thanks in advance!
Here is a flexbox Example using an empty div as a "spacer" Element. I left comments in the code that explain what the code below them does. I added colors to some elements so you can see what happens to them.
.header {
text-align: center;
}
.header-wrapper {
display: flex;
/*We want 1 row and we dont want items to wrap into other rows*/
flex-flow: row nowrap;
width: 100%;
background-color: green;
/*Positions elements to the start, end and whatever is between while keeping some space between them */
justify-content: space-between;
/*You can add this if you also want to horizontally align items*/
align-items: center;
}
/*gives all divs (the spacer and the checbox-div) inside of the header-wrapper the same size and leaves the rest of space for the header, with this the header is centered and looks better*/
.header-wrapper div {
width: 33%;
}
.checkbox-div {
background-color: red;
}
<div class="header-wrapper">
<!--Add an empty container to fill in the place on the left-->
<div class="empty-div"></div>
<h2 class="header">Header</h2>
<div class="checkbox-div">
<input type="checkbox" class="checkbox" value="Some Value" id="checkbox">
<label for="sub-folder-checkbox">Some Name</label>
</div>
</div>
Here is a second snippet with a different solution, code is commented for explanation again.
.header-wrapper {
/*make the container a flex item and make it relative*/
display: flex;
position: relative;
width: 100%;
background-color: green;
/*Center the header*/
justify-content: center;
/*if horizontal centering is required add this*/
align-items: center;
}
.checkbox-div {
/*give the div an absolute position inside the parent container all the way on the right*/
position: absolute;
right: 0;
background-color: red;
}
<div class="header-wrapper">
<h2 class="header">Header</h2>
<div class="checkbox-div">
<input type="checkbox" class="checkbox" value="Some Value" id="checkbox">
<label for="sub-folder-checkbox">Some Name</label>
</div>
</div>
I recommend using CSS grid (Basic Concepts of grid layout (on MDN)).
We make the wrapper a grid with three columns. The first column is ignored, the header goes into the second one and the checkbox div in the last one.
Then we align (vertical) and justify (horizontal) the grid items (i.e. the header and the div).
Note that I added borders to help see the boxes.
Also note that in your example code, the id of the checkbox doesn't match the for attribute on the label.
Here's the code:
.header-wrapper {
display: grid;
/* Creates three equally sized columns. */
grid-template-columns: 1fr 1fr 1fr;
align-items: center;
/* Centering is done with this.
* Also centers the div. */
justify-items: center;
}
.header {
grid-column: 2;
border: 1px blue solid;
}
.checkbox-div {
grid-column: 3;
border: 1px red solid;
/* If you don't want to center the checkbox div: */
justify-self: end;
}
<div class="header-wrapper">
<h2 class="header">Header</h2>
<div class="checkbox-div">
<input type="checkbox" class="checkbox" value="Some Value" id="sub-folder-checkbox" />
<label for="sub-folder-checkbox">Some Name</label>
</div>
</div>
#radio1,
#radio2 {
vertical-align: middle;
}
<input type="radio" name="konk" id='radio1' value="abc">Dady
<input type="radio" name="konk" id='radio2' value="abc">Oliva
I tried on jsfiddle and using vertical-align:top - buttons are is perfectly middle aligned with text.
In my files (localhost and remote) code is the same, but it's impossible to get middle alignement , using any of the css options top - middle - bottom.
You can wrap inputs in one parent element and then use display: flex and align-items: center on parent, also remove margin from inputs.
.wrap {
display: flex;
align-items: center;
}
input {
margin: 0;
}
<div class="wrap">
<input type="radio" name="konk" id='radio1' value="abc">Dady
<input type="radio" name="konk" id='radio2' value="abc">Oliva
</div>
So, I understand that tables are the spawn of satan. How should I align this without a table?
I have a bunch of input fields, each with a label to the left of it, and I would like the left side of the input fields to be aligned. Bad ascii art follows:
name ________________
date of birth ________________
Shakespeare villain I would like to be ________________
favo(u)rite do(gh)nut ________________
pet's blood group ________________
mother's maiden name ________________
favo(u)rite Led Zeppelin track ________________
I don't need exact code, just to be told how to do it.
This page looks incredibly helpful, but how do I do it with the text & input fileds?
Maybe a <div> with the text floating right and the input field vertically aligned at 50% ?
Try display: table-cell;
.wrapper {
display: table;
}
.inner {
display: table-cell;
}
#wrapper div.td1 {
text-align: right;
padding: 0;
margin: 0;
vertical-align: middle;
/* added incase of too long label text */
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
#wrapper div {
width: 50%;
display: inline-block;
text-align: left;
padding-left: 5px;
margin-right: -5px;
}
#wrapper {
width: 100%;
line-height: 1.5em;
}
<div id="wrapper">
<div class="td1">name</div><div><input type="text"></div>
<div class="td1">date of birth</div><div><input type="text"></div>
<div class="td1">Shakespeare villain I would like to be</div><div><input type="text"></div>
<div class="td1">favo(u)rite do(gh)nut</div><div><input type="text"></div>
<div class="td1">pet's blood grou </div><div><input type="text"></div>
<div class="td1">mother's maiden name</div><div><input type="text"></div>
<div class="td1">favo(u)rite Led Zeppelin track</div><div><input type="text"></div>
</div>
The best thing you can get here is to recreate table layout with different DOM elements plus some display:table-*** declarations :
div.parent { display:table; }
div.parent > row { display:table-row; }
div.parent > row > * { display:table-cell; }
div.parent > row > label { text-align:right; padding: 0 0.25em; }
div.parent > row > label::after { content:":"; }
<div class="parent">
<row>
<label>name</label>
<p>_____________</p>
</row><row>
<label>date of birth</label>
<p>_____________</p>
</row><row>
<label>Shakespeare villain I would like to be</label>
<p>_____________</p>
</row><row>
<label>favo(u)rite do(gh)nut</label>
<p>_____________</p>
</row><row>
<label>pet's blood group</label>
<p>_____________</p>
</row><row>
<label>mother's maiden name</label>
<p>_____________</p>
</row><row>
<label>favo(u)rite Led Zeppelin track</label>
<p>_____________</p>
</row>
</div>
A touch of flex
This may have some limitations depending on the rest of your layout; treat it as an experiment.
To reduce the amount of HTML used along with a tiny amount of CSS, we can play around with a flexbox layout.
Compatibility: IE 11+ and all modern browsers
The <form> container is given display: flex and, to align each label in the center of its input, align-items: center. flex-wrap: wrap is used to form rows.
The inputs and labels are given flex: 1 1 50%. This gives them an initial width of 50% which will then grow and shrink with the container. The initial value of 50% can be changed to make the inputs wider or smaller, as long as the label and inputs initial values add up to 100%.
The rows are spaced out with margin: 5px 0 5px on the inputs to provide a top and bottom margin. The top and bottom margin value should remain the same so the labels are centered.
box-sizing: border-box incorporates border and padding into the elements width and height
A guide to Flexbox is very useful.
Full Example
The form can be nicely controlled with min-width and max-width to maintain some flexibility.
* {
box-sizing: border-box;
}
form {
display: flex;
flex-wrap: wrap;
align-items: center;
max-width: 600px;
min-width: 300px;
}
label {
text-align: right;
flex: 1 1 50%;
padding-right: 10px;
}
input {
flex: 1 1 50%;
margin: 5px 0 5px;
}
<form>
<label for="label1">This is a really long label</label>
<input id="label1" type="text">
<label for="label2">Smaller label</label>
<input id="label2" type="text">
<label for="label3">Tiny</label>
<input id="label3" type="text">
</form>
I'm trying to build out a form module so that regardless of the various inputs a form may have, the following conditions are always met:
The form is centered within its containing element. (I think this is just inline-block combined with text-align: center.)
The inputs are all the same width and line up along their left edge.
The labels can be any length (within reason), and their right edges all line up.
The form is only as wide as its longest label/input combination (in other words, the width of the form is dynamic and determined by its longest label). (The red lines in the image below represent the bounding edges of the form as per the given labels and inputs.)
Basically, I want something like the following:
This type of layout is really easy to do with tables, but I have read that tables are not advisable to use for forms, so my question is, how can I do all of this without using a table?
Thank you.
Edit: The layout must work in IE8.
You can accomplish the required behavior using flex.
HTML structure (it's just an approach):
<div id="container">
<div class="form-container">
<form>
<div class="column">
<label for="text1">This is a label</label>
<label for="text2">Label</label>
<label for="text3" style="flex-grow:2;">Another larger label :D</label>
<label for="text4">A short one!</label>
</div>
<div class="column">
<input type="text" name="text1" />
<input type="text" name="text2" />
<textarea name="text4" style="flex-grow:2;"></textarea>
<input type="text" name="text3" />
</div>
</form>
</div>
</div>
CSS:
#container {
text-align: center;
}
#container .form-container {
display: inline-block;
}
#container form {
background: #eee;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
padding: 20px;
}
#container form .column {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
}
#container form .column label {
padding: 2px;
text-align: right;
}
#container form .column input,
#container form .column textarea {
align-self: flex-start;
width: 200px;
}
Here is a working demo: http://jsfiddle.net/gopafm4g/2/