I have a simple flex setup:
.col-12 {
display: flex
}
input {
flex: 0 0 80%
}
label {
flex: 0 0 20%
}
<div class="col-12">
<label>Label</label>
<input type="text" value=""></input>
</div>
However, the label isn't aligned vertically:
I tried vertical-aligment: middle but Message stayed in the same place.
What's the correct way to do this?
You need to use align-items property with the value center:
align-items: center;
Here's a link that I often refer to when I need a refresher and some examples when it comes to flexbox: A Visual Guide to CSS3 Flexbox Properties.
.col-12 {
display: flex;
align-items: center;
}
input {
height: 36px;
flex: 0 0 80%
}
label {
flex: 0 0 20%
}
<div class="col-12">
<label>Label</label>
<input type="text" value="">
</div>
PS <input>s don't have a closing tag, they're void elements. Sometimes referred to as empty elements.
Related
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>
This question already has answers here:
Make a div span two rows in a grid
(2 answers)
Closed 3 years ago.
I'm trying to use flexbox to achieve a column layout with an element "floated" to the right.
Something like this:
Thing is, I cannot alter the HTML since it's an embedded form so trying to achieve this via pure CSS.
So far, I have this:
.form {
display: flex;
flex-direction: column;
text-align: center;
}
.form-container {
display: flex;
flex-direction: column;
text-align: center;
justify-content: space-between;
}
.form-form {
width: 100%;
}
form {
display: flex;
justify-content: center;
}
fieldset {
border: 0;
}
textarea {
resize: none;
}
.form-columns-2 {
display: flex;
}
.form-columns-2 input:first-child {
margin-bottom: .5em
}
.form-columns-1 textarea {
height: 100%
}
.submit-wrapper{
flex-direction:column;
}
<div class="form">
<div class="form-container">
<div class="form-form">
<form>
<fieldset class="form-columns-2">
<input type="text" placeholder="test">
<input type="text" placeholder="test">
</fieldset>
<fieldset class="form-columns-2">
<input type="text" placeholder="test">
<input type="text" placeholder="test">
</fieldset>
<fieldset class="form-columns-1">
<textarea placeholder="test">Text</textarea>
</fieldset>
<div class="submit-wrapper">
<div class="actions">
<input type="submit" value="Submit">
</div>
</div>
</form>
</div>
</div>
</div>
Edit:
I also need the submit button to sit under the textarea, but since the .submit-wrapper is a direct child of form, the only way I can see addressing this is by adding flex-direction: column; to form. However, this turns the whole layout into a column, which I do not want.
You are apllying display: flex to the wrong elements and to more elements than you need to.
Check this: https://codepen.io/anon/pen/dwPoEP
* {
box-sizing: border-box;
}
fieldset{
border:0;
}
textarea{
resize:none;
}
form { // you want the form to be a flex box, not everything!
display: flex;
justify-content: center;
}
.form-columns-2 {
display: flex; //you can use other options here, this works but you can use display: block on the inputs for example
}
// this 2 are just to make it look like the image
.form-columns-2 input:first-child {
margin-bottom: .5em
}
.form-columns-1 textarea {
height: 100%
}
Currently I'm using a mixture between grid and flexbox to try and achieve a layout for a form.
I would like both input elements to horizontally lineup without setting a height on them. If I were to apply for padding on the text input, the range should continue to vertically center with the input adjacent to it.
Additionally I would like the label elements to also remain horizontally aligned too.
Please suggest solutions that DO NOT require changing the markup or using Javascript.
Currently what I have:
What I'm trying to achieve:
I know I could apply a fixed height or padding on the range to align it but I'm trying to make this as fluid as possible.
HTML:
<form class="grid">
<div class="group">
<label for="input-1">Label 1</label>
<input type="text" id="input-1" placeholder="placeholder" />
</div>
<div class="group">
<label for="input-2">Label 2</label>
<div class=range-wrapper>
<input type="range" id="input-2" placeholder="placeholder" />
<output>0</output>
</div>
</div>
</form>
SCSS:
html {
box-sizing: border-box;
}
*, *::before, *::after {
box-sizing: inherit;
}
body {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
font-size: 1.2rem;
}
.grid {
width: 80%;
max-width: 960px;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-gap: 40px 10px;
padding: 50px;
background: #ccc;
}
.group {
display: flex;
flex-direction: column;
margin-top: auto;
label {
margin-bottom: 10px;
}
}
input {
font-size: inherit;
&[type="text"] {
padding: 14px;
}
&[type="range"] {
width: 100%;
}
}
.range-wrapper {
display: flex;
align-items: center;
output {
padding: 10px;
}
You can also check out the codepen here.
Many thanks!
** EDIT **
Should support multiline labels, if the label wraps multiple lines, elements should still horizontally align.
Multiline label example: Codepen
try this for your "group" class.
(or use a new class for that element with this styling)
.group {
display: flex;
flex-direction: column;
justify-content: center;
label {
margin-bottom: 10px;
}
}
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>
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%;
}