I have a row of 3 inputs. One of them has label text placed above its input. I do not want this label text to interfere with the alignment of the inputs. Right now I'm using flexbox in my example. My hack/approach is to use position: absolute; on my optional label text to remove it from the flex flow so the inputs stay align. However, this creates a bit of spacing inconsistency when wrapping on smaller viewports. I've tried CSS grid as well but had issues where I was stuck writing a media query for every time I needed to wrap, which seemed worse than this. I would also like the solution to have no fixed widths/heights. As the elements and text can be dynamic. What is the best way to achieve this functionality that allows for a cleaner wrapping?
.container {
display: flex;
flex-wrap: wrap;
align-items: center;
}
.optionalContainer {
position: relative;
/*hack to container optional text*/
padding: 20px 0;
}
.optional {
position: absolute;
top: 0;
margin: 0;
}
<form class="container">
<input required type="text"/>
<div class="optionalContainer">
<p class="optional">Optional:</p>
<input type="text"/>
</div>
<input required type="text"/>
</form>
Example of what I'm shooting for at different viewports:
Here is a solution avoid both positioning and the padding hack using flex with row-gap of the input-height:
:root {
--input-height: 21.2px;
}
.container {
display: flex;
align-items: end;
flex-wrap: wrap;
row-gap: var(--input-height);
}
<form class="container">
<input required type="text" />
<div>
<div>Optional:</div>
<input type="text" />
</div>
<input required type="text" />
</form>
Here is a another solution which avoid both positioning and the padding hack using grid and a grid-template-columns hack:
:root {
--input-width: 146.867px;
--input-height: 21.2px;
}
.container {
display: grid;
/* wrapping hack from https://stackoverflow.com/a/43664701/1248177 */
grid-template-columns: repeat(auto-fill, minmax(var(--input-width), 1fr));
row-gap: var(--input-height);
align-items: end;
}
.optionalContainer > input {
box-sizing: border-box;
width: 100%;
}
<form class="container">
<input required type="text" />
<div class="optionalContainer">
<div class="optional">Optional:</div>
<input type="text" />
</div>
<input required type="text" />
</form>
Related
How to make input field change size without pushing text to next line?
enter image description here
Easiest way is going to be using display: flex, for more details read Basic concepts of flexbox on MDN.
Getting the labels the right width will require a bit of tweaking on your part, I've used .fieldGroup label { width: 10vw } as a loose value. Best is to use a pixel (px) value which will very much depend on the font family and size
/* BASIC RESET - not relvant to answer */ body { font: 16px sans-serif; margin: 0 }
.fieldGroup {
align-items: center;
display: flex;
gap: 1rem;
}
.fieldGroup:not(:last-of-type) { margin-bottom: 1rem }
.fieldGroup label { width: 10vw }
.fieldGroup input { flex-grow: 1 }
<form style="padding: 2rem">
<div class="fieldGroup">
<label>Name</label>
<input type="text" placeholder="Enter your name…">
</div>
<div class="fieldGroup">
<label>E-mail</label>
<input type="email" placeholder="Enter your e-mail…">
</div>
<div class="fieldGroup">
<label>Really long label here to easily test wrapping</label>
<input type="text" placeholder="???">
</div>
</form>
Use display: flex in CSS
.container {
width: 100px;
}
.flex {
display: flex;
align-items: center;
gap: 5px;
}
<div class="container">
<b>With Flex:</b>
<div class="flex">
<label>Name</label>
<input />
</div>
<br />
<b>Without Flex:</b>
<div>
<label>Name</label>
<input />
</div>
</div>
Okay then, so I made a nice-looking email-me form using CSS grids. Everything's fine and dandy except when I try to apply some padding on the form elements. Things then start to flow out of the grid.
It seems like the grid system doesn't take padding inside the elements into account when it calculates the final size of the grid items. I tried using fr-s and auto for the width of these elements, and all sorts of useless hacks, but nothing really works.
Here's the code and some screenshots to help you all feel my pain. :D
Without padding in the input fields:
https://imgur.com/a/NB1RcVS and
https://imgur.com/a/nz5lvIw
With padding:
https://imgur.com/a/Ak6CvlX and
https://imgur.com/a/hqLlxBr
<form id="email">
<div class="form-group" id="form-name">
<label for="name-field">Name</label>
<input type="text" name="name-field" id="name-field" required>
</div>
<div class="form-group" id="form-address">
<label for="address-field">Email Address</label>
<input type="text" name="address-field" id="address-field" required>
</div>
<div class="form-group" id="form-message">
<label for="message-field">Message</label>
<textarea name="message-field" id="message-field" cols="32" rows="8" required></textarea>
</div>
<button id="send-button" type="submit" form="email" name="send-it">Send it</button>
And the CSS:
#email {
display: grid;
grid-gap: 2rem;
grid-template-areas:
"name address"
"message message"
"send send";
grid-template-columns: 1fr 1fr;
justify-items: start;
margin: 1rem auto 0 auto;
width: 80%;
}
#form-name {
grid-area: name;
}
#form-address {
grid-area: address;
}
#form-message {
grid-area: message;
}
.form-group * {
display: block;
}
#form-name, #form-address, #form-message {
width: 100%;
}
#name-field, #address-field, #message-field {
width: 100%;
}
#name-field, #address-field, #message-field {
padding: 0.75rem 1.5rem;
}
Add this to the top of your code
*{
padding: 0px;
margin: 0px;
box-sizing: border-box;
}
#name-field, #address-field, #message-field {
padding: 10px;
}
or 15px if you want it to be close
I wanted to create a filter element that can be collapsed using the <details> element as it comes out of the box with an open/close functionality.
However when it came to styling the fields inside, I wanted to use grid and it seems like <details> can't be set to display: grid?
Has anyone come across this behavior?
Your input is much appreciated!
details {
display: grid;
grid-template-columns: 100px 100px;
}
input {
width: 100%;
}
label {
display: block;
}
label:first-of-type {
color: red;
grid-column: 1;
}
label:last-of-type {
color: blue;
grid-column: 2;
}
<form>
<details open>
<summary>Filter</summary>
<label>
I should be on the left
<input type="text">
</label>
<label>
I should be on the right
<input type="text">
</label>
</details>
</form>
Codepen here!
Have had to wrap the form input's within the details in a <div> or another container to get display: grid to work and style them.
Input size seems to disregard the size attribute and instead set a width of 100% to the parent element.
Css:
.lespan {
display: flex;
flex-direction: column;
justify-content: flex-end;
background: red;
min-width: 300px;
input {
min-width: 0px;
size: 5;
}
}
input {
min-width: 0px;
size: 5;
}
html:
<span class="lespan">
hello
<input type="text">
</span>
<input type="text">
Codepen: https://codepen.io/basickarl/pen/Lybvyz
I'd like both inputs to be of size 5.
You are pointing the wrong problem.
Stop using invalid property values.
Size is attribute and attribute belong to HTML. Set input size attribute with CSS?
Always inspect your code in browser.
If you want set size, then set the width of input.
.lespan {
display: flex;
flex-direction: column;
justify-content: flex-end;
background: red;
min-width: 300px;
}
input {
width: 100px;
}
<span class="lespan">
hello
<input type="text" >
</span>
<input type="text">
size is not a valid css atribute, but a html attribute. You may want to set them like so:
<input type="text" size="5">
Also, display:flex will break the size attribute value of the input, you might want to use display:block, use the css width attribute instead of size or change the html structue so that the input element is outside of a container with display:flex
Moreover, You can't nest styles, to apply a specific style to an element using both its tag name and a class name you might want to try something like this:
input.lespan {
min-width: 0px;
size: 5;
}
Just add align-items: flex-start; to .lespan. Here is the updated CodePen
.lespan {
display: flex;
flex-direction: column;
justify-content: flex-end;
background: red;
min-width: 300px;
align-items: flex-start;
}
.lespan input {
min-width: 0px;
size: 5;
}
input {
size: 5;
}
<span class="lespan">
hello
<input type="text">
</span>
<input type="text">
You can use css width property:
input{
width:200px;
}
Or html
<input type="text" size="5">
Having this:
<label>
<button>Create</button>
</label>
I want button to be aligned to the right like this
----------------------------
| [create]|
----------------------------
while having this:
<label>
<button>Delete</button>
<button>Update</button>
</label>
I want buttons to be in the corners
----------------------------
|[delete] [update]|
----------------------------
Without adding additional classes to the label.
You can just use margin-left: auto on last-child and that will produce desired result.
label {
display: flex;
border-bottom: 1px solid #aaa;
margin: 20px 0;
}
label button:last-child {
margin-left: auto;
}
<label>
<button>Create</button>
</label>
<label>
<button>Delete</button>
<button>Update</button>
</label>
You can do this using nothing but standard flexbox properties:
flex-direction: row-reverse - put the items in a row, start from "the end" (depends on reading direction)
justify-content: space-between - put the items as far away from each other as possible
label {
display: flex;
flex-direction: row-reverse;
justify-content: space-between;
}
<label>
<button>Create</button>
</label>
<label>
<button>Delete</button>
<button>Update</button>
</label>
You can use CSS Flexbox justify-content property to align your elements.
Have a look at this Codepen.
Or look at the code below for reference, also I've used <div>s in place of <label> as in the .two they are acting on both the buttons.
div {
display: flex;
background: #ddd;
padding: 10px 20px;
margin-bottom: 10px;
}
div:first-child {
justify-content: flex-end;
}
div:nth-child(2) {
justify-content: space-between;
}
<div>
<button>Create</button>
</div>
<div>
<button>Delete</button>
<button>Update</button>
</div>
Learn more about CSS Flexbox
Hope this helps!