Looking at the bellow code, I'm trying to have the 3 child columns as follow:
The first column should be 100% wide and above two other columns.
Two other columns should be bellow the first column and each 50% wide.
Like this:
.flex-container {
width: 80%;
min-height: 300px;
margin: 0 auto;
display: flex;
}
.flex-container .column {
padding: 10px;
background: #dbdfe5;
flex: 1;
}
.column.first {
background: blueviolet;
}
.column.third {
background: #b4bac0;
}
<div class="flex-container">
<div class="column first">Column 1</div>
<div class="column second">Column 2</div>
<div class="column third">Column 3</div>
</div>
But whatever I try it doesn't work that way.
Is it possible or I'm trying an impossible layout?
Flexbox version
You can use flex-wrap: wrap on the container to make children that overflow go below, and use flex-basis: 100% on the first child and flex-basis: 50% on the 2 others.
I have also added box-sizing: border-box on the children, to avoid border or padding count in the percentage.
.flex-container {
width: 80%;
min-height: 300px;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
}
.flex-container .column {
padding: 10px;
background: #dbdfe5;
box-sizing: border-box;
}
.column.first {
background: blueviolet;
flex-basis: 100%;
}
.column.second {
flex-basis: 50%;
}
.column.third {
background: #b4bac0;
flex-basis: 50%;
}
<div class="flex-container">
<div class="column first">Column 1</div>
<div class="column second">Column 2</div>
<div class="column third">Column 3</div>
</div>
Grid version
The grid version is even simpler, you only need display: grid on the container, and grid-column: 1 / 3 on the first child.
.flex-container {
width: 80%;
min-height: 300px;
margin: 0 auto;
display: grid;
}
.flex-container .column {
padding: 10px;
background: #dbdfe5;
}
.column.first {
background: blueviolet;
grid-column: 1 / 3;
}
.column.third {
background: #b4bac0;
}
<div class="flex-container">
<div class="column first">Column 1</div>
<div class="column second">Column 2</div>
<div class="column third">Column 3</div>
</div>
Related
I am trying to create a flex container layout whereby one of the flex items should span two rows. See image below for a better explanation:
Here is my markup:
<div class="container">
<div class="item item-1">ITEM 1</div>
<div class="item item-2">ITEM 2</div>
<div class="item item-3">ITEM 3</div>
</div>
I cannot seem to achieve this, I have tried using flex-wrap and different combinations of the flex property.
I was able to achieve this by putting ITEM 1 & ITEM 2 in a separate <div>, but this presents a problem on a smaller screen, whereby ITEM 3 needs to appear BETWEEN ITEM 1 & ITEM 2. So I would rather keep the markup as is and use the order property to move things around as necessary.
You can use display: contents on your extra div to achieve what you want:
* {
box-sizing: border-box;
}
.container {
display: flex;
width: 100%;
}
.holder {
width: 67%;
}
.item {
border: 1px solid black;
}
.item-1 {
margin-bottom: 40px;
}
.item-3 {
width: 33%;
}
#media screen and (max-width: 700px) {
.container {
flex-direction: column;
}
.item {
margin-bottom: 20px;
}
.item-1 {
order: 1;
}
.item-2 {
order: 3;
}
.item-3 {
order: 2;
width: 100%;
}
.holder {
width: 100%;
display: contents;
}
}
<div class="container">
<div class="holder">
<div class="item item-1">ITEM 1</div>
<div class="item item-2">ITEM 2</div>
</div>
<div class="item item-3">ITEM 3</div>
</div>
You can't achieve it using flexbox. Instead, you should have two parents which are better.
Use Css-grid. Actually, css-grid is the best option in this case.
Flex-Box
* {
color: #fff;
}
.flex {
display: flex;
justify-content: center;
align-items: center;
}
.child {
border-radius: 10px;
}
.container {
display: flex;
width: 500px;
height: 200px;
border: 1px solid #ff0000;
}
.container .first-item {
flex-direction: column;
justify-content: space-between;
align-items: start;
width: 50%;
height: 100%;
margin-right: 10px;
}
.first-item .child {
width: 100%;
height: 50%;
background-color: blue;
}
.first-item .child:first-child {
margin-bottom: 10px;
}
.container .second-item {
width: 50%;
height: 100%;
}
.second-item .child {
width: 100%;
height: 100%;
background-color: blue;
}
<div class="container">
<div class="first-item flex">
<div class="child flex">Item 1</div>
<div class="child flex">Item 2</div>
</div>
<div class="second-item flex">
<div class="child flex">Item 3</div>
</div>
</div>
Grid
.flex {
display: flex;
justify-content: center;
align-items: center;
}
.child {
background-color: blue;
border-radius: 10px;
}
.container {
display: grid;
grid-template-columns: 1fr 10px 1fr;
grid-template-rows: 1fr 10px 1fr;
grid-template-areas: "c1 . c3"
". . c3"
"c2 . c3";
width: 500px;
height: 300px;
border: 1px solid red;
}
.container .child {
border: 1px solid blue;
}
.child1 {
grid-area: c1;
}
.child2 {
grid-area: c2;
}
.child3 {
grid-area: c3;
}
<div class="container">
<div class="child child1 flex">Item 1</div>
<div class="child child3 flex">Item 3</div>
<div class="child child2 flex">Item 2</div>
</div>
i dont know if its a good solution but
put two item3 codes one in the individual div (item1&2) and one outside then put the one in the div to display none in non-small screens and switch between them with mediaquery
#media (max-width: 40rem) {
.item3 {
display: none;
}
.mobile-item3{
display: block;
}
}
I'm playing around with flexbox to get the hang of it but I am running into some issues. My goal is to have the window separated by four background colors where the first is just a header row and then the rest of the page is filled by 3 columns each a different background color. But for some reason if I write display: flex it doesn't show anything. Can someone explain to me how to get this desired effect?
.container {
width: 100%;
height: 100%;
}
.header {
height: 150px;
background-color: red;
}
.col-container {
widows: auto;
height: auto;
display: flex;
flex-direction: row;
}
.col {
flex: 1;
}
.col-container:nth-child(1) {
background: green;
}
.col-container:nth-child(2) {
background: blue;
}
.col-container:nth-child(3) {
background: yellow;
}
<body>
<div class="container">
<div class="header"></div>
<div class="col-container">
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
</div>
</div>
</body>
Here is a working example:
.container {
width: 100%;
height: 100%;
}
.header {
height: 150px;
background-color: red;
}
.col-container {
widows: auto;
height: auto;
display: flex;
flex-direction: row;
}
.col-1 {
flex: 1 1 33.333%;
background-color: green;
}
.col-2 {
flex: 1 1 33.333%;
background-color: blue;
}
.col-3 {
flex: 1 1 33.333%;
background-color: yellow;
}
<body>
<div class="container">
<div class="header"></div>
<div class="col-container">
<div class="col-1">ts</div>
<div class="col-2">dtd</div>
<div class="col-3">dt</div>
</div>
</div>
</body>
Here's what you needed to fix:
Set flex-direction to row. You most likely want the columns next to each other.
Add the classes to your HTML for the col-1, col-2 and col-3.
You need content in those col classes, or you won't see anything anyway.
I set a flex-basis (the third parameter in the flex shorthand) to 33.333%. You don't necessarily need this, but it's nice to see how much space a particular element will fill or change it.
EDIT For the comments:
body {
margin: 0;
padding: 0;
}
.container {
width: 100%;
height: 100%;
}
.header {
height: 150px;
background-color: red;
}
.col-container {
widows: auto;
height: auto;
display: flex;
flex-direction: row;
height: calc(100vh - 150px);
}
.col-1 {
flex: 1 1 33.333%;
background-color: green;
}
.col-2 {
flex: 1 1 33.3333%;
background-color: blue;
}
.col-3 {
flex: 1 1 33.3333%;
background-color: yellow;
}
<body>
<div class="container">
<div class="header"></div>
<div class="col-container">
<div class="col-1"></div>
<div class="col-2"></div>
<div class="col-3"></div>
</div>
</div>
</body>
Basically, you need to give the col-container a height. To achieve this, I used vh units in the calc statement. It subtracts your header height from the viewport height and gives the remainder. This also removes the necessity for filler content.
I have a flex container, and some divs inside of it. Each div has some content inside of it, that set the width of this div. between each of the divs, I want to put a responsive separator-div.
I've tried to give the max-width property for each of the responsive class in the code below, but it not rendering.
I cannot give the inner-wrapper's a fixed width, because it depends on the width of the inner{#}.
<div class='main'>
<div class='item-wrapper'>
<div class='inner1'></div>
<div class='responsive'></div>
</div>
<div class='item-wrapper'>
<div class='inner2'></div>
<div class='responsive'></div>
</div>
<div class='item-wrapper'>
<div class='inner3'></div>
<div class='responsive'></div>
</div>
</div>
.main{
width:100%;
display:flex;
height:40px;
background:yellow;
}
.responsive{
max-width:200px;
}
.item-wrapper{
display:flex;
height:100%;
background:green;
}
to summarize, i expect:
div1 -------------- div2 --------------- div3
such that only the width of the '------' will increase/decrease if i resizing my screen
You can do it like this by adding a rule to your flexbox container:
myContainer{
//other properties
justify-content:space-between;
}
You do need that much of markup
example
.main {
width: 100%;
display: flex;
height: 40px;
background: yellow;
justify-content: space-between;
/* new */
}
.responsive {
flex: 1;
/* new */
max-width: 200px;
margin: auto;
/* new */
border-top: dotted;
/* new */
}
.main>div:not([class]) {
background: green;
display: flex;
align-items: center;
/* new */
}
<div class='main'>
<div>inner 1</div>
<div class='responsive'></div>
<div>inner 2</div>
<div class='responsive'></div>
<div>inner 3</div>
</div>
If you have a only 3 elements, then 2 pseudos can become the seperator via order:
.main {
width: 100%;
display: flex;
height: 40px;
background: yellow;
justify-content: space-between;
}
.main::before,
.main::after {
content: '';
flex: 1;
max-width: 200px;
margin: auto;
border-top: dotted;
}
.main>div:not([class]) {
background: green;
display: flex;
align-items: center;
}
.main>div:first-child {
order: -1
}
.main>div:last-child {
order: 1
}
<div class='main'>
<div>inner 1</div>
<div>inner 2</div>
<div>inner 3</div>
</div>
more about flex : https://css-tricks.com/snippets/css/a-guide-to-flexbox/
I have a pretty basic grid setup in flex, but I recently came across an oversight I made.
I have columns that have a margin-right: 3em and flex-basis: calc(33% - 3em).
My problem is that the 4th and 5th of these don't line up until there is a full "row" of 3.
Any insights as to why this is happening? I imagine I may be over-complicating things as per usual.
section {
width: 1170px;
margin: 0 auto;
padding: 4em;
background-color: lightgray;
}
.flex {
display: flex;
}
.wrap {
flex-wrap: wrap;
}
.column {
flex: 1;
flex-direction: column;
margin-right: 3em;
}
.column:last-child {
margin-right: 0;
}
.three {
max-width: 33%;
flex-basis: calc(33% - 3em);
}
.three:nth-child(3n) {
margin-right: 0;
}
.debug {
margin-bottom: 3em;
background-color: #ebf5fb;
height: 3em;
border: 1px dashed red;
text-align: center;
}
<section>
<div class="flex wrap">
<div class="column three debug">3 Columns</div>
<div class="column three debug">3 Columns</div>
<div class="column three debug">3 Columns</div>
<div class="column three debug">3 Columns</div>
<div class="column three debug">3 Columns</div>
</div>
</section>
Codepen
Since you use flex: 1, it will make the element take all available space, what's left after the flex-basis been retracted.
What stop the 2 last items from filling the entire row is the max-width, and since that its value is wider than the flex-basis, they will expand to it.
Either remove flex: 1 from column, or use the same calc for max-width as used for flex-basis
Stack snippet
section {
width: 1170px;
margin: 0 auto;
padding: 4em;
background-color: lightgray;
}
.flex {
display: flex;
}
.wrap {
flex-wrap: wrap;
}
.column {
flex: 1;
flex-direction: column;
margin-right: 3em;
}
.column:last-child {
margin-right: 0;
}
.three {
max-width: calc(33% - 3em); /* changed */
flex-basis: calc(33% - 3em);
}
.three:nth-child(3n) {
margin-right: 0;
}
.debug {
margin-bottom: 3em;
background-color: #ebf5fb;
height: 3em;
border: 1px dashed red;
text-align: center;
}
<section>
<div class="flex wrap">
<div class="column three debug">3 Columns</div>
<div class="column three debug">3 Columns</div>
<div class="column three debug">3 Columns</div>
<div class="column three debug">3 Columns</div>
<div class="column three debug">3 Columns</div>
</div>
</section>
Updated based on a comment
If to also make the items spread equally inside its parent, one need to divide the sum of the actual margin/gutter/gap space with the amount of items.
So in this case it would be (2 gaps * 3em) / 3 items = 2em
Also, one need the closest possible to a 1/3, which can be either e.g. 33.33333% or (100% / 3)
Stack snippet
section {
width: 1170px;
margin: 0 auto;
padding: 4em;
background-color: lightgray;
}
.flex {
display: flex;
}
.wrap {
flex-wrap: wrap;
}
.column {
flex: 1;
flex-direction: column;
margin-right: 3em;
}
.column:last-child {
margin-right: 0;
}
.three {
max-width: calc(33.33333% - 2em); /* changed */
flex-basis: calc(33.33333% - 2em); /* changed */
}
.three:nth-child(3n) {
margin-right: 0;
}
.debug {
margin-bottom: 3em;
background-color: #ebf5fb;
height: 3em;
border: 1px dashed red;
box-sizing: border-box; /* added */
text-align: center;
}
.debug2 {
border: 1px dashed red; /* added */
box-sizing: border-box; /* added */
}
<section>
<div class="flex wrap debug2">
<div class="column three debug">3 Columns</div>
<div class="column three debug">3 Columns</div>
<div class="column three debug">3 Columns</div>
<div class="column three debug">3 Columns</div>
<div class="column three debug">3 Columns</div>
</div>
</section>
Thank you LGson for pointing me in the right direction.
My math was incorrect.
I needed to take 100% - the total margins in the row.
Instead of flex-basis: calc(33% - 3em); it needed to be flex-basis: calc( (100% - 6em) / 3);
Updated Snippet
*,
::before,
::after {
background-repeat: no-repeat; /* 1 */
box-sizing: inherit; /* 2 */
}
html {
box-sizing: border-box; /* 1 */
cursor: default; /* 2 */
-ms-text-size-adjust: 100%; /* 3 */
-webkit-text-size-adjust: 100%; /* 3 */
}
section {
width: 1170px;
margin: 0 auto;
padding: 4em;
background-color: lightgray;
}
.flex {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
.wrap {
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.column {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
margin-right: 3em;
/*overflow: hidden;*/
}
.column:last-child {
margin-right: 0;
}
.three {
max-width: calc( (100% - 6em) / 3);
-ms-flex-preferred-size: calc( (100% - 6em) / 3);
flex-basis: calc( (100% - 6em) / 3);
}
.three:nth-child(3n) {
margin-right: 0;
}
.debug {
background-color: #EBF5FB;
margin-top: 1em;
padding: .75em;
text-align: center;
border: 1px dashed #E8DAEF;
}
<section>
<h2>Layout for 2 Dimensions</h2>
<h3>Specific Widths (or not)</h3>
<div class="flex wrap">
<div class="column three debug">1/3 Columns</div>
<div class="column three debug">1/3 Columns</div>
<div class="column three debug">1/3 Columns</div>
<div class="column three debug">1/3 Columns</div>
<div class="column three debug">1/3 Columns</div>
</div>
</section>
I have a vertically central adaptable scrollable flexbox element, which itself should have two columns (I solved this with two child-divs). The central flexbox should have a frame and a central divider line.
I can't get the central divider line to run all the way to the bottom of the scrollable flexbox. I tried it with a third child div element but the line only appears for the vertical extent of the flexbox.
How can I make two columns in a scrollable flexbox with a frame and central divider line running all the way to the bottom?
Thank you for your help.
Here is the example:
https://jsfiddle.net/soliman/0d0tn22x/2/
<body>
<div class="wrapper">
<div class="header">
<h1>Header</h1>
</div>
<div class="content">
<div class="leftContent"> Column 1
With a lot of lines.
</div>
<div class="divider"></div>
<div class="rightContent"> Column 2
With fewer lines
</div>
</div>
<div class="footer">
Footer
</div>
</div>
</body>
CSS:
html,
body {
height: 100%;
margin: 0;
padding: 0;
background: black;
color: red;
}
.wrapper {
display: flex;
/* use the flex model */
height: 100%;
flex-direction: column;
}
.header {
margin: 1em 1em 0 1em;
}
.content {
flex: 1 1 auto;
display: flex;
overflow-y: auto;
position: relative;
min-height: 100px;
margin: 0 1em 0 1em;
border: 6px double red;
}
.content > div {
width: 50%;
padding: 3%;
}
.content > div:first-child {
margin-right: 10px;
}
.footer {
margin: 0 1em 1em 1em;
}
.divider {
position: absolute;
left: 50%;
top: 0%;
bottom: 0%;
border-left: 6px double red;
}
Try this mixed flexbox and CSS table layout. You can set the content area as a table, and the three columns as table cells, so they always be equal height.
There is one issue with the approach is - it only works properly if the content is taller than the container, otherwise the vertical line will stop in the middle. See the other approach at the bottom.
jsFiddle
html,
body {
height: 100%;
margin: 0;
}
.wrapper {
height: 100%;
display: flex;
flex-direction: column;
}
.content {
flex: 1;
overflow-y: auto;
min-height: 100px;
border: 1px solid;
}
.wrapContent {
display: table;
width: 100%;
}
.wrapContent > div {
display: table-cell;
}
.leftContent,
.rightContent {
width: 50%;
}
.divider {
border-left: 1px solid;
}
<div class="wrapper">
<div class="header">
<h1>Header</h1>
</div>
<div class="content">
<div class="wrapContent">
<div class="leftContent">
<div style="height:500px;">Left</div>
</div>
<div class="divider"></div>
<div class="rightContent">
<div style="height:auto;">Right</div>
</div>
</div>
</div>
<div class="footer">
<p>Footer</p>
</div>
</div>
Another way would be using background image for the vertical line, set that to the center of the content container, with repeat-y, the image can be just a square dot. It works well even if the content is shorter than the container.
jsFiddle
html,
body {
height: 100%;
margin: 0;
}
.wrapper {
height: 100%;
display: flex;
flex-direction: column;
}
.content {
flex: 1;
display: flex;
overflow-y: auto;
min-height: 100px;
border: 1px solid;
background: url("http://i.imgur.com/oyQ4xsL.png") center top repeat-y;
background-size: 1px;
}
.leftContent,
.rightContent {
width: 50%;
}
<div class="wrapper">
<div class="header">
<h1>Header</h1>
</div>
<div class="content">
<div class="leftContent">
<div style="height:500px;">left</div>
</div>
<div class="rightContent">
<div style="height:auto;">right</div>
</div>
</div>
<div class="footer">
<p>Footer</p>
</div>
</div>