Can you make flexbox background height the same? - html

I am using flexbox display and it is working fine. Except when I happen to use a background color on one of the divs, the color does not cover the entire height of the div. It ends up looking like this --
Of course what I'd like is for the background color to extend to the same height as the div to the right. Is this even possible with flexbox?
.row {
display: flex;
align-items: center;
}
.left {
flex: 1 0 auto;
background-color: wheat;
}
.right {
flex: 1 0 auto;
}
<div class="row">
<div class="left">Some text</div>
<div class="right">
<input type="text" style="height:40px" />
</div>
</div>

The problem is that you use
align-items: center;
The default value does what you want:
align-items: stretch;
.row {
display: flex;
}
.left {
flex: 1 0 auto;
background-color: wheat;
}
.right {
flex: 1 0 auto;
}
<div class="row">
<div class="left">
Some text
</div>
<div class="right">
<input type="text" style="height:40px" />
</div>
</div>
But then you will need to center the contents vertically. You can do it with more flexbox. Some examples:
Row layout and align-items:
.left {
display: flex; /* More flexbox */
align-items: center; /* Center in the cross (vertical) axis */
}
.row {
display: flex;
}
.left {
flex: 1 0 auto;
background-color: wheat;
display: flex;
align-items: center;
}
.right {
flex: 1 0 auto;
}
<div class="row">
<div class="left">
Some text
</div>
<div class="right">
<input type="text" style="height:40px" />
</div>
</div>
Column layout and justify-content:
.left {
display: flex; /* More flexbox */
flex-direction: column; /* Column layout */
justify-content: center; /* Center in the main (vertical) axis */
}
.row {
display: flex;
}
.left {
flex: 1 0 auto;
background-color: wheat;
display: flex;
flex-direction: column;
justify-content: center;
}
.right {
flex: 1 0 auto;
}
<div class="row">
<div class="left">
Some text
</div>
<div class="right">
<input type="text" style="height:40px" />
</div>
</div>
Inserting pseudo-elements with auto margins:
.left {
display: flex; /* More flexbox */
flex-direction: column; /* Column layout */
}
.left::before, .left::after {
content: ''; /* Generate pseudo-elements */
margin: auto; /* Push contents */
}
.row {
display: flex;
}
.left {
flex: 1 0 auto;
background-color: wheat;
display: flex;
flex-direction: column;
}
.left::before, .left::after {
content: '';
margin: auto;
}
.right {
flex: 1 0 auto;
}
<div class="row">
<div class="left">
Some text
</div>
<div class="right">
<input type="text" style="height:40px" />
</div>
</div>

Related

Making text align to the left in first cell of flexbox?

I've got a flexbox code working in my file, this is just the relevant parts of the whole file:
.tbl {
display: flex;
flex-direction: column;
}
.row {
display: flex;
min-height: 50px;
}
.cell {
flex: 4;
border: 1px solid red;
}
.cell:nth-child(1) {
flex: 1;
}
.cell:nth-child(2) {
flex: 2;
}
.cell.span4-5 {
flex: 8 24px; /* col 4,5 flex-grow/border/padding */
}
.cell.span3-4 {
flex: 8 24px; /* col 3,4 flex-grow/border/padding */
}
.cell.span3-5 {
align-content: flex-end;
justify-content: flex-end;
flex: 12 36px; /* col 3,4,5 flex-grow/border/padding */
}
.cell.span1-1 {
width: 60px;
}
div.atalign1 {
text-align: left;
margin-bottom: 10px;
}
.row:first-child .cell {
display: flex;
justify-content: center; /* center horiz. */
align-items: center; /* center vert. */
}
.row .cell {
padding: 5px;
box-sizing: border-box;
}
<div class="tbl">
<div class="atalign1">
<div class="row">
<div class="cell span3-5">Text</div>
<div class="cell span1-1">$50,000</div>
</div>
<div class="row">
<div class="cell">1</div>
<div class="cell span3-4">Content</div>
</div>
</div>
<div class="atalign1">
<div class="row">
<div class="cell span3-5">This is my text. This is my text</div>
<div class="cell span1-1">$3,000</div>
</div>
<div class="row">
<div class="cell">1</div>
<div class="cell span3-4">Content</div>
</div>
</div>
</div>
In the second div, the text is aligned to the left; for the first one, the text will NOT align to the left, even when I tried text-align: left;
If anyone could help I'd really appreciate this!
This class is causing the problem:
.row:first-child .cell {
display: flex;
justify-content: center; /* center horiz. */
align-items: center; /* center vert. */
}
The text is actually aligned to the left, you're just justifing it and aligning the item so it's going crazy. See snippet below:
.tbl {
display: flex;
flex-direction: column;
}
.row {
display: flex;
min-height: 50px;
}
.cell {
flex: 4;
border: 1px solid red;
}
.cell:nth-child(1) {
flex: 1;
}
.cell:nth-child(2) {
flex: 2;
}
.cell.span4-5 {
flex: 8 24px; /* col 4,5 flex-grow/border/padding */
}
.cell.span3-4 {
flex: 8 24px; /* col 3,4 flex-grow/border/padding */
}
.cell.span3-5 {
align-content: flex-end;
justify-content: flex-end;
flex: 12 36px; /* col 3,4,5 flex-grow/border/padding */
}
.cell.span1-1 {
width: 60px;
}
div.atalign1 {
text-align: left;
margin-bottom: 10px;
}
.row .cell {
padding: 5px;
box-sizing: border-box;
}
<div class="tbl">
<div class="atalign1">
<div class="row">
<div class="cell span3-5">Text</div>
<div class="cell span1-1">$50,000</div>
</div>
<div class="row">
<div class="cell">1</div>
<div class="cell span3-4">Content</div>
</div>
</div>
<div class="atalign1">
<div class="row">
<div class="cell span3-5">This is my text. This is my text</div>
<div class="cell span1-1">$3,000</div>
</div>
<div class="row">
<div class="cell">1</div>
<div class="cell span3-4">Content</div>
</div>
</div>
</div>
.row:first-child .cell {
display: flex;
justify-content: center; /* center horiz. */
align-items: center; /* center vert. */
}
Because you have the div containing the text set to display: flex, the elements inside (direct descendants) will follow the justify-content and align-items rules. In this case justify-content is causing the text to be centered horizontally, while align-items is centering it vertically.
You can set it to justify-content: flex-start to align the text to the left while keeping it vertically centered.

Flex item getting our of flex container (horizontal)

I'm building a panel where I have a right menu area with some command buttons, scrolled vertically, and a main left area covering the remaining space, scrolled horizontally.
Repair that items must be full available height (up to 100% of the viewport).
In the example code, left area flex item is is "pushing" the right side to move to right... I'm also not getting the scrollbars to appear correctly.
Below the result I'm looking for:
Here is my template code:
.panel-container {
width: 100%;
height: 100vh;
display: flex;
flex-direction: row;
padding: 0px;
}
.panel-container-left {
flex-grow: 1;
flex-shrink: 0;
background-color: grey;
display: flex;
flex-direction: column;
}
.panel-container-right {
margin-left: 3px;
background-color: green;
}
.panel-right-data {
display: flex;
flex-direction: column;
overflow-y: scroll;
}
.panel-right-data-item {
background-color: green;
color: white;
padding: 5px;
margin: 2px;
width: 20px;
}
.panel-left-data {
display: flex;
flex-direction: row;
overflow-x: scroll;
}
.panel-left-data-item {
background-color: blue;
color: white;
padding: 5px;
margin: 2px;
width: 80px;
height: 100%;
}
<div class="panel-container">
<div class="panel-container-left">
<div>LEFT AREA</div>
<div class="panel-left-data">
<div class="panel-left-data-item">
ITEM 1
</div>
<div class="panel-left-data-item">
ITEM 2
</div>
<div class="panel-left-data-item">
ITEM 3
</div>
<div class="panel-left-data-item">
ITEM 4
</div>
<div class="panel-left-data-item">
ITEM 5
</div>
</div>
</div>
<div class="panel-container-right">
<div>RIGHT AREA</div>
<div class="panel-right-data">
<div class="panel-right-data-item">
COMMAND 1
</div>
<div class="panel-right-data-item">
COMMAND 2
</div>
<div class="panel-right-data-item">
COMMAND 3
</div>
<div class="panel-right-data-item">
COMMAND 4
</div>
<div class="panel-right-data-item">
COMMAND 5
</div>
<div class="panel-right-data-item">
COMMAND 6
</div>
<div class="panel-right-data-item">
COMMAND 7
</div>
<div class="panel-right-data-item">
COMMAND 8
</div>
<div class="panel-right-data-item">
COMMAND 9
</div>
</div>
</div>
</div>
For the height : height: 100%; only work when the immediat parent height is defined. So you have to add a specific height size to .panel-left-data, it can be 100% but in turn you have to add a specific height to it's parent node .panel-container-left, it also can be 100% and since .panel-container does have a height defined (100vh), all is good !
For the rest, I commented directly some adjustements I made, there may be better solutions for some of them but it work.
In practice :
.panel-container {
width: 100%;
height: 100vh;
display: flex;
flex-direction: row;
padding: 0px;
}
.panel-container-left {
flex-grow: 1;
flex-shrink: 0;
background-color: grey;
display: flex;
flex-direction: column;
height: 100%; /*added a height*/
overflow-x: scroll; /*moved the scroll here*/
overflow-y:hidden; /*just to be sure*/
}
.panel-container-right {
margin-left: 3px;
background-color: green;
position:absolute; /*added a position absolute*/
right:0px; /*the position let me use the right/left/top/bottom positionning*/
z-index:10; /*let me put this element on top of those with lower z-index*/
width:200px; /*and a width to make it good-looking*/
/*moved the scroll here with some height to restrict it*/
height: calc( 100% - 17px );
overflow-y:scroll;
}
.panel-right-data {
display: flex;
flex-direction: column;
/*overflow-y: scroll; moved on the parent element*/
}
.panel-right-data-item {
background-color: green;
color: white;
padding: 5px;
margin: 2px;
width: 20px;
}
.panel-left-data {
display: flex;
flex-direction: row;
/*overflow-x: scroll; moved on the parent element*/
height: calc( 100% - 40px ); /*added a height, cut it a little to account for the scrollbar and your example*/
}
.panel-left-data-item {
background-color: blue;
color: white;
padding: 5px;
margin: 2px;
width: 80px;
height: 100%;
}
<div class="panel-container">
<div class="panel-container-left">
<div>LEFT AREA</div>
<div class="panel-left-data">
<div class="panel-left-data-item">
ITEM 1
</div>
<div class="panel-left-data-item">
ITEM 2
</div>
<div class="panel-left-data-item">
ITEM 3
</div>
<div class="panel-left-data-item">
ITEM 4
</div>
<div class="panel-left-data-item">
ITEM 5
</div>
</div>
</div>
<div class="panel-container-right">
<div>RIGHT AREA</div>
<div class="panel-right-data">
<div class="panel-right-data-item">
COMMAND 1
</div>
<div class="panel-right-data-item">
COMMAND 2
</div>
<div class="panel-right-data-item">
COMMAND 3
</div>
<div class="panel-right-data-item">
COMMAND 4
</div>
<div class="panel-right-data-item">
COMMAND 5
</div>
<div class="panel-right-data-item">
COMMAND 6
</div>
<div class="panel-right-data-item">
COMMAND 7
</div>
<div class="panel-right-data-item">
COMMAND 8
</div>
<div class="panel-right-data-item">
COMMAND 9
</div>
</div>
</div>
</div>
Looking over the code, you seem to be missing a lot of align-items, justify-content, and flex properties. Also make sure you are using class="" and not className="" in your html unless you are working in JSX. Here's some code that is a little closer to what you seem to want.
.panel-container {
height: 100vh;
display: flex;
flex-direction: row;
justify-content: space-between; /* Added */
align-items: stretch; /* Added */
padding: 0px;
}
.panel-container-left {
flex: 1 1 auto; /* Replace flex-grow flex-shrink*/
background-color: grey;
display: flex;
flex-direction: column;
justify-content: stretch; /* Added */
max-width: calc(100vw - 200px); /* Added - For Horizontal scrolling */
}
.panel-container-right {
margin-left: 3px;
background-color: green;
flex: 0 0 200px; /* Added */
align-items: space-between; /* Added */
justify-content: stretch; /* Added */
display: flex; /* Added */
flex-direction: column; /* Added */
}
.panel-container-right>div:first-child {
flex: 0 0 30px; /* Added */
}
.panel-right-data {
display: flex;
flex: 1 1 80%; /* Added */
flex-direction: column;
overflow-y: scroll;
}
.panel-right-data-item {
background-color: green;
color: white;
padding: 5px;
margin: 2px;
width: 20px;
}
/* Added */
.panel-container-left > div:first-child {
flex: 0 0 30px;
}
.panel-left-data {
flex: 1 1 80%; /* Added */
display: flex;
flex-direction: row;
overflow-x: scroll;
align-items: stretch; /* Added */
justify-content: flex-start; /* Added */
}
.panel-left-data-item {
background-color: blue;
color: white;
padding: 5px;
margin: 2px;
width: 80px;
}
And here's a fiddle: https://jsfiddle.net/wfL8q051/21/

CSS flex grow does not work with added div on top

Consider the following fiddle: https://jsfiddle.net/7naxprzd/1/
Requirements are:
two columns with header and contents
tops of columns should align
bottom of columns should align
on top of each column there should be a horizontally centered arrow
The code is working properly if the arrows are eliminated by deleting the div with class .arrow-wrapper, but I need the arrows.
A solution could be to absolute position the arrow, but is there a way to solve this layout issue with flex without absolute positioning the arrow?
Should work for modern browsers and IE11.
.row-wrapper {
display: flex;
}
.col-wrapper-outer {
display: flex;
flex-wrap: wrap;
}
.arrow-wrapper {
width: 100%;
text-align: center;
font-size: 30px;
}
.col-wrapper {
width: 100%;
display: flex;
flex-direction: column;
border: 2px solid red;
color: white;
}
.col-wrapper .header {
background: blue;
}
.col-wrapper .contents {
flex: 1 0 auto;
background: green;
}
<div class="row-wrapper">
<div class="col-wrapper-outer">
<div class="arrow-wrapper">
↓
</div>
<div class="col-wrapper">
<div class="header">Please align tops.</div>
<div class="contents">Let me grow.</div>
</div>
</div>
<div class="col-wrapper-outer">
<div class="arrow-wrapper">
↓
</div>
<div class="col-wrapper">
<div class="header">please align tops.</div>
<div class="contents">Let me grow.<br>Please<br>align<br>bottoms.</div>
</div>
</div>
</div>
In your div with class col-wrapper-outer, instead of this:
.col-wrapper-outer {
display: flex;
flex-wrap: wrap;
}
Use this:
.col-wrapper-outer {
display: flex;
flex-direction: column;
}
Then add flex: 1 to .col-wrapper so it takes the full height of the container.
revised fiddle
.row-wrapper {
display: flex;
}
.col-wrapper-outer {
display: flex;
/* flex-wrap: wrap; */
flex-direction: column; /* NEW */
}
.arrow-wrapper {
width: 100%;
text-align: center;
font-size: 30px;
}
.col-wrapper {
flex: 1; /* NEW */
width: 100%;
display: flex;
flex-direction: column;
border: 2px solid red;
color: white;
}
.col-wrapper .header {
background: blue;
}
.col-wrapper .contents {
flex: 1 0 auto;
background: green;
}
<div class="row-wrapper">
<div class="col-wrapper-outer">
<div class="arrow-wrapper">
↓
</div>
<div class="col-wrapper">
<div class="header">Please align tops.</div>
<div class="contents">Let me grow.</div>
</div>
</div>
<div class="col-wrapper-outer">
<div class="arrow-wrapper">
↓
</div>
<div class="col-wrapper">
<div class="header">please align tops.</div>
<div class="contents">Let me grow.
<br>Please
<br>align
<br>bottoms.</div>
</div>
</div>
</div>

Flexbox shrinking main container when main container is horizontal flex box

I want to create a simple layout for my SPA where I have a header component, which should be shown all the time. A footer component, which should be either at the bottom of the screen or if the main content component is bigger than the screen, it should be below the content component. And a main content component which should get the rest of the space if the screen is bigger than the content, so the footer component gets rendered at the bottom.
Currently I've reproduced my layout in this codepen. But if you shrink the result window of the codepen enough, you'll get to a point where I can't see the Test2 text because the footer component is on top of it. The behaviour I would expect is, that I can see the Test2 text and I'm able to scroll down to the footer component.
It works if the content component is not a flex box with flex-direction: row. Any ideas why this doesn't work?
In my SPA I'm using React, so I don't want to use any JavaScript for this.
* {
padding: 0;
margin: 0;
font-size: 2rem;
}
.page {
display: flex;
flex-direction: column;
height: 100vh;
width: 100%;
background: yellow;
}
.container {
display: flex;
flex-direction: column;
flex: 1;
overflow: scroll;
}
.main {
flex: 1;
background: red;
display: flex;
flex-direction: row;
min-height: 30px;
}
.test {
display: block;
}
.footer {
background: green;
}
<div class="page">
<div class="header">Header</div>
<div class="container">
<div class="main">
Main
<div class="test">Test1<br />Test2<br/></div>
</div>
<div class="footer">Footer</div>
</div>
</div>
Just add flex: 1 0 auto to .main class. Flex properties are flex-grow, flex-shrink, and the flex-basis. So with 0 it is told to not shrink.
* {
padding: 0;
margin: 0;
font-size: 2rem;
}
.page {
display: flex;
flex-direction: column;
height: 100vh;
width: 100%;
background: yellow;
}
.container {
display: flex;
flex-direction: column;
flex: 1;
overflow: scroll;
}
.main {
flex: 1 0 auto;
background: red;
display: flex;
flex-direction: row;
min-height: 30px;
}
.test {
display: block;
}
.footer {
background: green;
}
<div class="page">
<div class="header">Header</div>
<div class="container">
<div class="main">
Main
<div class="test">Test1<br />Test2<br/></div>
</div>
<div class="footer">Footer</div>
</div>
</div>
I got it working. I needed to add a div with display: block; around my content and I added justify-content: space-between; to my container component. Little hacky but it works...
That's my final code:
* {
padding: 0;
margin: 0;
font-size: 2rem;
}
.page {
display: flex;
flex-direction: column;
height: 100vh;
width: 100%;
background: yellow;
}
.container {
display: flex;
flex-direction: column;
flex: 1;
justify-content: space-between;
overflow: scroll;
}
.block {
display: block;
}
.main {
background: red;
display: flex;
flex-direction: row;
}
.test {
display: block;
}
.footer {
background: green;
}
<div class="page">
<div class="header">Header</div>
<div class="container">
<div class="block">
<div class="main">
Main
<div class="test">Test1<br />Test2<br/></div>
</div>
</div>
<div class="footer">Footer</div>
</div>
</div>

Flexbox - align : center / justify : center with unknown height

I am trying to split the page into 4 equal squares with centered content. The issue I am having is centering the content due to the .flex-item divs having a viewport height, I am looking for a full flexbox solution, Thank you.
I have tried the following from resources:
justify-content center
align-items center
.flex-container {
display: -webkit-flex;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
}
.color_1 {
background: tomato;
}
.color_2 {
background: LightGreen;
}
.color_3 {
background: PowderBlue;
}
.color_4 {
background: SteelBlue;
}
.flex-item {
-webkit-flex: 1 0 auto;
flex: 1 0 auto;
width: 50%;
height: 50vh;
}
<div class="flex-container">
<div class="flex-item color_1"><div class="inner"><p>inner</p></div></div>
<div class="flex-item color_2"><div class="inner"><p>inner</p></div></div>
<div class="flex-item color_3"><div class="inner"><p>inner</p></div></div>
<div class="flex-item color_4"><div class="inner"><p>inner</p></div></div>
</div>
Make the .flex-item be flex containers, and use justify-content and align-items to center their content:
.flex-item {
display: flex;
justify-content: center;
align-items: center;
}
body {
margin: 0;
}
.flex-container {
display: flex;
flex-wrap: wrap;
}
.color_1 {
background: tomato;
}
.color_2 {
background: LightGreen;
}
.color_3 {
background: PowderBlue;
}
.color_4 {
background: SteelBlue;
}
.flex-item {
flex: 1 0 auto;
width: 50%;
height: 50vh;
display: flex;
justify-content: center;
align-items: center;
}
<div class="flex-container">
<div class="flex-item color_1"><div class="inner">inner</div></div>
<div class="flex-item color_2"><div class="inner">inner</div></div>
<div class="flex-item color_3"><div class="inner">inner</div></div>
<div class="flex-item color_4"><div class="inner">inner</div></div>
</div>