wrap and stretch inputs on form resize - html

I have two inputs on form in one row. First one should be stretching on form resize, second is of fixed width. But when form is narrowed to a particular breakpont, second input should wrap to second line and stretch as well as first one.
Is it possible to achieve using CSS?
Tried using grid, but it won't wrap at all.
When using flexbox the result is better, but still have to set flex-grow for second input and it's width is not fixed, while inputs are in one row
.box {
background: grey;
padding: 20px 20px 20px 20px;
}
.wrapper {
display: grid;
grid-column-gap: 6px;
grid-row-gap: 6px;
grid-template-columns: minmax(320px, 1fr) 200px;
}
.flexWrapper {
display: flex;
flex-wrap: wrap;
}
.flex1 {
flex-basis: 320px;
flex-grow: 10;
flex-shrink: 0;
}
.flex2 {
flex-basis: 200px;
flex-shrink: 0;
flex-grow: 1;
}
<div class="wrapper">
<div class="box">One</div>
<div class="box">Two</div>
</div>
<div class="flexWrapper">
<div class="flex1 box">One</div>
<div class="flex2 box">Two</div>
</div>
https://codepen.io/C4off/pen/WNKjJaK

The easiest way to do this is to use a media query. At 600px I've reset the wrapper to be display: block with the children at 100% width which forces them to stack on top of each other. I've set the width of flex2 to 200px to fix it at that.
.box {
background: grey;
padding: 20px 20px 20px 20px;
}
.flexWrapper {
display: flex;
padding-top: 12px;
column-gap: 6px;
row-gap:6px;
}
.flex1 {
flex: 1;
}
.flex2 {
width: 200px;
}
#media only screen and (max-width: 600px) {
.flexWrapper {
display: block;
}
.flex1, .flex2 {
width: 100%;
}
}
<div class="container">
<div class="flexWrapper">
<div class="flex1 box">One</div>
<div class="flex2 box">Two</div>
</div>
</div>
Using flexbox only and the min-width proprty. Note .flex2 will overflow at container widths less than 200px
.container {
width: 60%;
outline: 1px solid red;
}
.box {
background: grey;
padding: 20px 20px 20px 20px;
}
.flex-wrapper {
display: flex;
padding-top: 12px;
column-gap: 6px;
row-gap:6px;
flex-wrap: wrap;
}
.flex1 {
flex: 2 0;
}
.flex2 {
min-width: 200px;
flex-grow: 1;
}
<div class="container">
<div class="flex-wrapper">
<div class="flex1 box">One</div>
<div class="flex2 box">Two</div>
</div>
</div>
The final way this can be done is using container queries which are quite well supported now. The max size is applied to the container and not the screen as the example below
* {
box-sizing:border-box;
}
.container {
container-type: inline-size;
container-name: my-container;
width: 60%;
}
.box {
background: grey;
padding: 20px 20px 20px 20px;
}
.flex-wrapper {
display: flex;
padding-top: 12px;
column-gap: 6px;
row-gap:6px;
}
.flex1 {
flex: 1;
}
.flex2 {
width: 200px;
}
#container my-container (max-width: 600px) {
.container {outline: 1px solid red;}
.flex-wrapper {
display: block;
}
.flex1, .flex2 {
width: 100%;
}
}
<div class="container">
<div class="flex-wrapper">
<div class="flex1 box">One</div>
<div class="flex2 box">Two</div>
</div>
</div>

Related

reallocate items inside a div with responsive pages

I edited literally a few lines from the code taken from this question link
#wrap {
margin: 20px auto;
width: 80%;
}
.separator {
margin-top: 30px;
}
.row {
height: 30px; margin-bottom: 10px; background-color: green;
}
.left,
.right {
width: 33%; height: 30px; line-height: 30px;
display: inline-block;
text-align: center;
background-color: grey;
}
.left { margin-right: 10px; }
.right { margin-left: 10px; }
.center {
min-height: 30px; line-height: 30px;
text-align: center;
background-color: blue;
display: inline-block;
width: 30%;
}
<div id="wrap">
<div class="left">left</div>
<div class="center">center</div>
<div class="right">right</div>
<div class="separator"></div>
<div class="left">left</div>
<div class="center">center</div>
<div class="right">right</div>
</div>
when the sizes of the windows becomes too small, for example on mobile, it will become a mess. When this happens, how can I reallocate items vertically, one items for line, where the left will be the first, the center the second, and so.
I'm actually using this in React, just to know.
With display grid
You can use grid-template-areas on the grid parent selectors and grid-areas on the grid children selectors to place the elements in the order you want them to be displayed in the document despite their order in the HTML. You just change the grid properties in your media query.
#cont {
display: grid;
grid-auto-columns: 1fr;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: auto;
grid-template-areas:
"left-1 center-1 right-1"
"left-2 center-2 right-2";
gap: .5rem;
}
.box {
height: 100px;
background: blue;
margin: 0.5rem;
}
.left-1 {
grid-area: left-1;
}
.left-2 {
grid-area: left-2;
}
.center-1 {
grid-area: center-1;
}
.center-2 {
grid-area: center-2;
}
.right-1 {
grid-area: right-1;
}
.right-2 {
grid-area: right-2;
}
/* mobile */
#media screen and (max-width: 700px) {
#cont {
display: grid;
grid-auto-columns: auto;
grid-template-columns: auto;
grid-template-rows: auto;
grid-template-areas:
"left-1"
"left-2"
"center-1"
"center-2"
"right-1"
"right-2";
gap: .5rem;
}
}
<div id="cont">
<div class="left-1 box">left</div>
<div class="center-1 box">center</div>
<div class="right-1 box">right</div>
<div class="left-2 box">left</div>
<div class="center-2 box">center</div>
<div class="right-2 box">right</div>
</div>
You could do the following without using display grid and just adding a media query:
You however do not have control of re-ordering the elements like you do with grid or flex display, you could use box-ordinal-group to change the order of the elements, however it has been taken out of the standard with the introduction of flex - order and grid.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#cont {
width: calc(100% - 5px);
height: auto;
margin: 5px;
}
.box {
min-width: calc(33.3% - 5px);
height: 100px;
background: blue;
display: inline-block;
}
.box~.box {
margin-top: 5px;
}
#media screen and (max-width: 700px) {
#cont {
width: calc(100% - 5px);
margin: 5px;
}
.box {
min-width: calc(100% - 5px);
height: 100px;
}
}
<div id="cont">
<div class="box">left</div>
<div class="box">center</div>
<div class="box">right</div>
<div class="box">left</div>
<div class="box">center</div>
<div class="box">right</div>
</div>
Using flex box with order
~ Change the visual order of your content when using Flexbox.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#cont {
display: flex;
flex-wrap: wrap;
}
.box {
min-width: calc(33.3% - 10px);
height: 100px;
background: blue;
display: inline-block;
margin: 5px;
}
#media screen and (max-width: 700px) {
#cont {
width: calc(100% - 10px);
margin: 5px;
}
.box {
min-width: calc(100% - 10px);
height: 100px;
}
.box:nth-of-type(1) {
order: 1;
}
.box:nth-of-type(2) {
order: 3;
}
.box:nth-of-type(3) {
order: 5;
}
.box:nth-of-type(4) {
order: 2;
}
.box:nth-of-type(5) {
order: 4;
}
.box:nth-of-type(6) {
order: 6;
}
}
<div id="cont">
<div class="box">left row 1</div>
<div class="box">center row 1</div>
<div class="box">right row 1</div>
<div class="box">left row 2</div>
<div class="box">center row 2</div>
<div class="box">right row 2</div>
</div>
You can use CSS Flexbox to position the items side-by-side on large screens, and use a media query to detect mobile devices and align the items vertically.
#wrap {
margin: 20px auto;
width: 80%;
}
.row {
display: flex;
}
/* mobile */
#media screen and (max-width: 700px) {
.row {
flex-direction: column;
}
}
.box {
width: 100%;
height: 100px;
background: blue;
margin: 0.5em;
}
<div id="wrap">
<div class="row">
<div class="box">left</div>
<div class="box">center</div>
<div class="box">right</div>
</div>
<div class="row">
<div class="box">left</div>
<div class="box">center</div>
<div class="box">right</div>
</div>
</div>

CSS: Refactor grid to a flex layout with different childs

I'm currently trying to build a flex layout which should have 3 possible childs:
If the wrapper has just one button, it should have the full width of the wrapper.
If the wrapper has two childs, the last one should have a max width of 75px and the first one must fill the available space.
If the wrapper has at all three childs, the first row should be like at the example before but the last child should be in the next row with 100% width.
I've build this grid layout but I need change it to flex because of the compatibility of some browsers. How can I do this? I've tried a lot but the result is always bad.
.wrapper {
width: 60%;
display: grid;
display: -ms-grid;
grid-template-columns: 1fr 75px;
text-align: center;
position: relative;
margin-bottom: 20px;
}
.wrapper div+div {
margin-left: 6px;
}
.wrapper div {
background-color: yellow;
padding: .6em 1em;
text-align: center;
}
.wrapper div.show.single-button {
grid-column: 1/span 2;
}
.wrapper div.cancel {
grid-column: 1/span 2;
-ms-grid-row: 2;
-ms-grid-column-span: 2;
margin-top: 6px;
margin-left: 0;
}
<div class="wrapper">
<div class="show single-button">Show</div>
</div>
<div class="wrapper">
<div class="show">Show</div>
<div class="invoice">Invoice</div>
</div>
<div class="wrapper">
<div class="show">Show</div>
<div class="invoice">Invoice</div>
<div class="cancel">Cancel</div>
</div>
Judicious use of flex:1 and flex-wrap seems to work.
* {
box-sizing: border-box;
}
.wrapper {
width: 60%;
margin: auto;
display: flex;
flex-wrap: wrap;
margin-bottom: 20px;
justify-content: space-between;
border: 1px solid green;
}
.wrapper div {
background-color: lightblue;
padding: .6em 1em;
text-align: center;
margin: 6px;
}
.wrapper div.show {
flex: 1;
}
.wrapper div.invoice {
flex: 1;
max-width: 75px;
}
.wrapper div.cancel {
flex: 1 1 100%;
}
<div class="wrapper">
<div class="show single-button">Show</div>
</div>
<div class="wrapper">
<div class="show">Show</div>
<div class="invoice">Invoice</div>
</div>
<div class="wrapper">
<div class="show">Show</div>
<div class="invoice">Invoice</div>
<div class="cancel">Cancel</div>
</div>
Flexbox offers everything you need for this. No need to hack around by mixing flexbox with box-model or width properties:
.wrapper {
height: 100px;
display: flex;
flex-wrap: wrap;
margin-bottom: 10px;
}
.wrapper > div {
flex: 1;
border: 1px dotted #999;
background-color: aliceblue;
}
.wrapper > div:nth-child(2) {
flex-shrink: 0;
flex-grow: 0;
flex-basis: 75px;
-webkit-flex-basis: 75px;
}
.wrapper > div:nth-child(3) {
flex-shrink: 0;
flex-grow: 0;
flex-basis: 100%;
-webkit-flex-basis: 100%;
}
<div class="wrapper">
<div>1</div>
</div>
<div class="wrapper">
<div>1</div>
<div>2</div>
</div>
<div class="wrapper">
<div>1</div>
<div>2</div>
<div>3</div>
</div>
You can use flex-basis to tell the initial width of the elements and flex-grow to tell if they should take more space, and flex-wrap so it does not force them to fit in one line, something like:
.wrapper {
display: flex;
flex-wrap: wrap; // make it multiline
margin-bottom: 1rem;
}
.wrapper div {
background: yellow;
margin: .2rem;
padding: .2rem;
text-align: center;
}
.invoice {
flex-basis: 75px; // make it have 75px
flex-grow: 0; // can't grow
flex-shrink: 0; // can't shrink
}
.show {
flex-grow: 1; // no basis width, just grow and take the space left from .invoice
}
.cancel {
flex-basis: 100%; // takes the whole width so it must go on a single row
}
https://codepen.io/anon/pen/KJLqVj

Flex last row to take available vertical space [duplicate]

This question already has answers here:
Stretch columns in two columns layout with shared header using flexbox
(2 answers)
Closed 4 years ago.
I have this layout, where a row wrap flex container has a first child with 100% width and 2 more children on the second row. The container has a fixed height and the first child (Filters block below) is collapsible (i.e. has 2 possibles values for height).
I would like the blocks on the last line to take all available height in all cases (filters block collapsed or expanded), but I can't find a solution.
I've tried various combinations of height, align-items/align-self: stretch, to no avail. Setting the pdt/list blocks height to 100% makes them effectively 100% of parent container, so they overflow due to the filters.
I know I could achieve it by making the first container flex column and throw in a second one with flex row,but I'd like to keep the current markup if possible. Any idea?
JSfiddle: https://jsfiddle.net/Lp4j6cfw/34/
HTML
<div id="lp-tag">
<div id="header">HEADER</div>
<div id="lp-ctnr">
<div id="filters" onclick="toggle()">FILTERS</div>
<div id="pdt">PDT</div>
<div id="list">LIST</div>
</div>
CSS
#lp-tag{
display: flex;
flex-flow: column nowrap;
width: 350px;
margin: auto;
border: 1px solid red;
height: 250px;
}
#header{
background: lightblue;
height: 80px;
}
#lp-ctnr{
display: flex;
flex-flow: row wrap;
justify-content: space-between;
align-content: flex-start;
align-items: stretch;
border: 1px solid green;
flex: 1;
}
#filters{
width: 100%;
background: lightgreen;
height: 45px;
}
.close{
height: 20px !important;
}
#pdt, #list {
flex: 1;
border: 1px solid blue;
text-align: center;
align-self: stretch;
}
#pdt{
background: yellow;
}
#list{
background: pink;
}
If you are open to alternative layout methods, I'd recommend CSS-Grid
.lp-tag {
width: 250px;
margin: 1em auto;
border: 1px solid red;
height: 250px;
display: inline-grid;
grid-template-rows: auto 1fr;
}
.header {
background: lightblue;
height: 80px;
}
.header.small {
height: 40px;
}
.lp-ctnr {
display: grid;
grid-template-rows: auto 1fr;
grid-template-columns: repeat(2, 1fr);
border: 1px solid green;
flex: 1;
}
.filters {
grid-column: 1 / span 2;
background: lightgreen;
height: 45px;
}
.filters.large {
height: 80px;
}
.pdt,
.list {
border: 1px solid blue;
text-align: center;
}
.pdt {
background: yellow;
}
.list {
background: pink;
}
<div class="lp-tag">
<div class="header">HEADER</div>
<div class="lp-ctnr">
<div class="filters" onclick="toggle()">FILTERS</div>
<div class="pdt">PDT</div>
<div class="list">LIST</div>
</div>
</div>
<div class="lp-tag">
<div class="header small">HEADER</div>
<div class="lp-ctnr">
<div class="filters large" onclick="toggle()">FILTERS</div>
<div class="pdt">PDT</div>
<div class="list">LIST</div>
</div>
</div>
This is the only solution I can see without an intermediary container. https://jsfiddle.net/5j38ouvs/
However, I would probably do like Nandita and add a surrounding container like here: https://jsfiddle.net/8md4oyLx/
CSS
#lp-ctnr{
display: flex;
flex-direction: column;
border: 1px solid green;
height: 550px;
width: 350px;
margin: auto;
}
#filters{
width: 100%;
background: lightgreen;
}
.close{
height: 20px !important;
}
#pdt{
flex-grow: 1;
background: yellow;
}
#list{
flex-grow: 1;
background: pink;
}
.list-container {
flex-grow: 1;
border: 1px solid blue;
text-align: center;
display: flex;
flex-direction: row;
}
HTML
<div id="lp-ctnr">
<div id="filters" onclick="toggle()">FILTERS</div>
<div class="list-container">
<div id="pdt">PDT</div>
<div id="list">LIST</div>
</div>
</div>

larger flex child causing previous sibling's padding to be ignored

So I have a flexbox but I'm having trouble understanding why the first child's padding gets ignored when the second child's content overflows.
here's an example when the second child's content aren't overflowing.
body {
padding: 0;
margin: 0;
}
.flex {
display: flex;
flex-direction: column;
width: 100vw;
height: 100vh;
}
.title {
background-color: green;
border-bottom: 10px solid black;
display: flex;
height: 50px;
padding-bottom: 40px;
}
.body {
background-color: blue;
flex: 1;
}
.content {
background-color: red;
height: 10vh;
}
<div class="flex">
<div class="title">
</div>
<div class="body">
<div class="content">
</div>
</div>
</div>
Here's an example when the child's content are overflowing
body {
padding: 0;
margin: 0;
}
.flex {
display: flex;
flex-direction: column;
width: 100vw;
height: 100vh;
}
.title {
background-color: green;
border-bottom: 10px solid black;
display: flex;
height: 50px;
padding-bottom: 40px;
}
.body {
background-color: blue;
flex: 1;
}
.content {
background-color: red;
height: 100vh;
}
<div class="flex">
<div class="title">
</div>
<div class="body">
<div class="content">
</div>
</div>
</div>
you can see in the second example that the title's height has greatly reduced.
It's because you're using flex css, which tries to accommodate all the children. If the title is supposed to not change in size no matter what, you need to set its flex-shrink to 0.
So try changing the css to:
.title {
background-color: green;
border-bottom: 10px solid black;
display: flex;
height: 50px;
padding-bottom: 40px;
flex-shrink: 0;
}

Wrap element to new line/row using flexbox

I have trouble forcing an item into the next row in a flexbox layout.
How can I do something like the following image?
This is what I got so far:
#wrap {
display: flex;
width: 86vw;
height: auto;
box-sizing: border-box;
margin: 0 auto;
}
.item1,
.item2 {
width: 50%;
height: 24.5vw;
background: #4add69;
}
.item1 {
margin-right: 10px;
}
.item2 {
margin-left: 10px;
}
.item3 {
width: 60%;
height: 40vw;
background: #d56c6c;
}
<div id="wrap">
<div class="item1"></div>
<div class="item2"></div>
<div class="item3"></div>
</div>
Your code is fine but missing two things.
Use flex-wrap: wrap to
create a new row. Modify the width of the first two items to be
present in a single row.
For the last two items, you need to nest it inside a container and
then wrap them again.
Manipulate the dimension(width, height) and margin values to achieve the perfect/suitable layout.
JSfiddle Demo
* {
margin: 0;
padding: 0;
}
body {
background: #232323;
padding: 10px;
}
#wrap {
display: flex;
width: 86vw;
height: auto;
box-sizing: border-box;
margin: 0 auto;
flex-wrap: wrap;
background: #232323;
/* Added */
}
.item1,
.item2 {
width: 48%;
/* Modified */
height: 24.5vw;
background: #4add69;
margin-bottom: 10px;
}
.item1 {
margin-right: 10px;
}
.item2 {
margin-left: 10px;
}
.item3 {
width: 55%;
height: 40vw;
background: #d56c6c;
margin-right: 10px;
}
.nested-items {
display: flex;
width: 42%;
flex-wrap: wrap;
align-content: space-between;
}
.item4,
.item5 {
background: lightblue;
width: 100%;
height: 49%;
}
<div id="wrap">
<div class="item1"></div>
<div class="item2"></div>
<div class="item3"></div>
<div class="nested-items">
<div class="item4"></div>
<div class="item5"></div>
</div>
</div>
Essentially you need an extra wrapping div for the two 'small' elements like so:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wrap {
width: 75%;
margin: 1em auto;
border: 1px solid green;
padding: .25em;
display: flex;
flex-wrap: wrap;
}
.wrap div {
border: 1px solid grey;
margin-bottom: 1px;
}
.box {
height: 80px;
background: lightblue;
flex: 0 0 50%;
}
.tall {
flex: 0 0 65%;
height: 160px;
}
.col {
flex: 0 0 35%;
display: flex;
flex-wrap: wrap;
}
.mini {
flex: 0 0 100%;
height: 80px;
background: pink;
}
<div class="wrap">
<div class="box"></div>
<div class="box"></div>
<div class="box tall"></div>
<div class="box col">
<div class="mini"></div>
<div class="mini"></div>
</div>
</div>
I've used a single overall element here with wrapping but the image suggests that this would be much simpler with actual rows and the extra wrapper mentioned before.
Codepen Demo of 2nd option with rows.