I'm trying to create a visual layout using Flexbox.
In this layout, controls are arranged in rows. Some of the rows will have a predefined height, and some of the rows will be anchored to both the top and bottom of the screen, which means they'll stretch their height to occupy all available space.
I've got a working layout that will achieve this, but there seems to be an issue when the rows with predefined height need stretch because their contents no longer fit. They seem to not actually be stretching, which causes them to overlap with one another.
Anyone know how to get the rows to resize in height, properly?
You can have a look at the current status here:
https://jsfiddle.net/cgledezma1101/o9zwa7na/
I'm using the following CSS for my containers:
.main-container {
display: flex;
flex-flow: column nowrap;
justify-content: flex-start;
align-items: flex-start;
align-content: flex-start;
height: 100vh;
}
.row {
flex: 1 1 auto;
display: flex;
flex-flow: row wrap;
justify-content: flex-start;
align-items: flex-start;
align-content: flex-start;
width: 100%;
}
.row2 {
height: 200px;
min-height: 200px;
}
.row1 {
height: 100px;
min-height: 100px;
}
.not-anchored {
height: 100px;
}
.anchored {
height: 100%;
}
A fixed height on the container means it cannot expand to accommodate a taller layout. Hence, flex items are forced to overlap on smaller screens.
Instead of height: 100vh, use min-height: 100vh.
Also, remove fixed heights on flex items. They override align-items: stretch.
revised fiddle
.main-container {
display: flex;
flex-flow: column nowrap;
min-height: 100vh;
}
.row {
display: flex;
flex-flow: row wrap;
}
.row.anchored { flex: 1; }
body { margin: 0; }
.item12 {
flex: 1 1 100px;
height: 200px;
min-width: 100px;
background: tomato;
}
.item21 {
flex: 1 1 200px;
height: 100px;
min-width: 100px;
background: deepskyblue;
}
.item {
text-align: center;
color: white;
font-weight: bold;
font-size: 3em;
border: 1px dashed black;
line-height: 100px;
margin-left: auto;
margin-right: auto;
}
.item.anchored {
flex: 1;
/* height: 100%; */
min-height: 150px;
background: hotpink;
}
<body>
<div class="main-container">
<div class="row row2 not-anchored">
<div class="item item12">
1.1
</div>
<div class="item item12">
1.2
</div>
<div class="item item12">
1.3
</div>
</div>
<div class="row anchored">
<div class="item anchored">
A.1
</div>
</div>
<div class="row row1 not-anchored">
<div class="item item21">
2.1
</div>
<div class="item item21">
2.2
</div>
</div>
<div class="row anchored">
<div class="item anchored">
A.2
</div>
</div>
</div>
</body>
It seems the issue arises from giving the .main-container element a height: 100vh;. Changing that to height: 100%; seems to fix it.
.main-container {
display: flex;
flex-flow: column nowrap;
justify-content: flex-start;
align-items: flex-start;
align-content: flex-start;
height: 100%;
}
.main-container {
display: flex;
flex-flow: column nowrap;
justify-content: flex-start;
align-items: flex-start;
align-content: flex-start;
height: 100%;
}
.row {
flex: 1 1 auto;
display: flex;
flex-flow: row wrap;
justify-content: flex-start;
align-items: flex-start;
align-content: flex-start;
width: 100%;
}
.row2 {
height: 200px;
min-height: 200px;
}
.row1 {
height: 100px;
min-height: 100px;
}
.not-anchored {
height: 100px;
}
.anchored {
height: 100%;
}
.item12 {
flex: 1 1 100px;
height: 200px;
min-width: 100px;
background: tomato;
}
.item21 {
flex: 1 1 200px;
height: 100px;
min-width: 100px;
background: deepskyblue;
}
.item {
text-align: center;
color: white;
font-weight: bold;
font-size: 3em;
border: 1px dashed black;
line-height: 100px;
margin-left: auto;
margin-right: auto;
}
.item.anchored {
flex: 1 1 100%;
height: 100%;
min-height: 150px;
background: hotpink;
}
<body>
<div class="main-container">
<div class="row row2 not-anchored">
<div class="item item12">
1.1
</div>
<div class="item item12">
1.2
</div>
<div class="item item12">
1.3
</div>
</div>
<div class="row anchored">
<div class="item anchored">
A.1
</div>
</div>
<div class="row row1 not-anchored">
<div class="item item21">
2.1
</div>
<div class="item item21">
2.2
</div>
</div>
<div class="row anchored">
<div class="item anchored">
A.2
</div>
</div>
</div>
</body>
The following produces:
Related
I cannot understand WHY I am not getting this:
.container {
width: 600px;
height: 400px;
border: 3px solid green;
}
.cg-panel {
display: flex;
flex-flow: column;
align-items: stretch;
justify-content: center;
}
.cg-panel .content {
flex: 1;
background-color: tomato;
}
<div class="container">
<div class="cg-panel">
<div class="content"></div>
</div>
</div>
I, for the life of me, cannot understand why the content panel does not vertically stretch the entire container. What is the purpose of "flex:1" if it isn't going to work? Am I not reading the documentation correctly?
There's nothing in your CSS that is expanding the height of .cg-panel to fit its parent .container.
Adding height: 100%; to .cg-panel fixes this:
.container {
width: 600px;
height: 400px;
border: 3px solid green;
}
.cg-panel {
display: flex;
flex-flow: column;
align-items: stretch;
justify-content: center;
height: 100%; /* add this */
}
.cg-panel .content {
flex: 1;
background-color: tomato;
}
<div class="container">
<div class="cg-panel">
<div class="content"></div>
</div>
</div>
I'm trying to create a Slider Layout with flex boxes, like this photo :
Here I've big photo at right side and thumbnail items on the left. I want to align left side and thumbnails wrapper with big photo height. But unfortunately It's not possible only with flex boxes and I should check big photo height with JavaScript and align left side with that.
For example check this code:
main{
position: absolute;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
display: flex;
align-items: center;
justify-content: center;
}
.wrapper{
width: 500px;
overflow: hidden;
background: gray;
display: flex;
align-items: flex-start;
justify-content: center;
}
.right{
width: calc(100% - 150px);
height: 450px;
background: red;
}
.left{
width: 150px;
display: flex;
align-items: center;
justify-content: space-between;
flex-direction: column;
}
.item{
width: 100%;
height: 50px;
color: white;
background: green;
display: flex;
align-items: center;
justify-content: center;
}
<main>
<div class="wrapper">
<div class="left">
<div class="item">
<strong>Item</strong>
</div>
<div class="item">
<strong>Item</strong>
</div>
<div class="item">
<strong>Item</strong>
</div>
<div class="item">
<strong>Item</strong>
</div>
<div class="item">
<strong>Item</strong>
</div>
</div>
<div class="right"></div>
</div>
</main>
In sample code I've not image and I handled this issue with 450px height in CSS.
So how can I align the left side with out JS and only with CSS? I want to use space-between mode to show all items in this height. Consider it, height:100% didn't work for this issue.
As per my comment, in order for your left column to extend to the height of your right column, all you need to do is remove the align items from your wrapper:
main{
position: absolute;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
display: flex;
align-items: center;
justify-content: center;
}
.wrapper{
width: 500px;
overflow: hidden;
background: gray;
display: flex;
/* align-items: flex-start; -- remove this */
justify-content: center;
}
.right{
/* width: calc(100% - 150px); I would swap this for flex grow, then you don't need hard values */
flex-grow: 1;
height: 450px;
background: red;
}
.left{
width: 150px;
display: flex;
align-items: center;
justify-content: space-between;
flex-direction: column;
}
.item{
width: 100%;
height: 50px;
color: white;
background: green;
display: flex;
align-items: center;
justify-content: center;
}
<main>
<div class="wrapper">
<div class="left">
<div class="item">
<strong>Item</strong>
</div>
<div class="item">
<strong>Item</strong>
</div>
<div class="item">
<strong>Item</strong>
</div>
<div class="item">
<strong>Item</strong>
</div>
<div class="item">
<strong>Item</strong>
</div>
</div>
<div class="right"></div>
</div>
</main>
This solution uses CSS Grid layouts - use display: grid on your wrapper that lays out your left and right sections using grid-template-columns: 150px 1fr (remove the width definitions in right and left elements.).
Now add height: 100% to left and then for the items flex: 1 for the flexbox items to occupy the dynamic height coming from the right section - see demo below:
main {
position: absolute;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
display: flex;
align-items: center;
justify-content: center;
}
.wrapper {
width: 500px;
overflow: hidden;
background: gray;
display: grid; /* make this a grid container */
grid-template-columns: 150px 1fr; /* 150px for left and rest for right*/
align-items: flex-start;
justify-content: center;
}
.right {
/* width: calc(100% - 150px);*/
height: 450px;
background: red;
}
.left {
/*width: 150px;*/
display: flex;
align-items: center;
justify-content: space-between;
flex-direction: column;
height: 100%; /* ADDED */
}
.item {
width: 100%;
height: 50px;
color: white;
background: green;
display: flex;
align-items: center;
justify-content: center;
flex: 1; /* ADDED */
}
<main>
<div class="wrapper">
<div class="left">
<div class="item">
<strong>Item</strong>
</div>
<div class="item">
<strong>Item</strong>
</div>
<div class="item">
<strong>Item</strong>
</div>
<div class="item">
<strong>Item</strong>
</div>
<div class="item">
<strong>Item</strong>
</div>
</div>
<div class="right"></div>
</div>
</main>
Something like this can be done with flexbox, if you set the height of the container to be the height you want all your sliders to be:
.container {
display: flex;
flex-flow: column wrap;
height: 250px;
width: 250px;
}
.container > * {
display: flex;
flex-flow: row wrap;
flex: 1 100%;
}
.thumbs {
flex-direction: row;
margin-right: 5px;
}
.thumb {
background: red;
flex: 1 100%;
margin: 5px 0;
}
.large {
background: blue;
margin: 5px;
}
<div class="container">
<div class="thumbs">
<div class="thumb"></div>
<div class="thumb"></div>
<div class="thumb"></div>
<div class="thumb"></div>
<div class="thumb"></div>
</div>
<div class="large"></div>
</div>
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/
I have a flex parent container set to flex-wrap: wrap and justify-content: flex-end. I have one flex-child, button-group which i want to align to flex-start, but align-self is not working.
.container{
width: 500px;
height: 500px;
background: pink;
display: flex;
justify-content: flex-end;
flex-wrap: wrap;
}
.button-group {
background: lightblue;
align-self: flex-start; /* Not working!*/
padding: 5px 10px;
}
.main-box {
width: 450px;
height: 300px;
background: lime;
}
.myfooter {
width: 50%;
height: 10%;
background-color: black;
}
<div class="container">
<div class="button-group">
<button></button>
<button></button>
<button></button>
</div>
<div class="main-box"></div>
<div class="myfooter"> </div>
</div>
How can I get the button group to align itself to the left while preserving the flex wrap?
Flexbox aligns items in 1D direction. Thats why the flex-start didnt work,
In oreder to make it work wrap it with a div and add appropriate styles as shown in the snippet
.container {
width: 500px;
height: 500px;
background: pink;
display: flex;
justify-content: flex-end;
flex-wrap: wrap;
}
.button-group {
background: lightblue;
padding: 5px 10px;
display: inline-block;
}
.main-box {
width: 450px;
height: 300px;
background: lime;
}
.myfooter {
width: 50%;
height: 10%;
background-color: black;
}
.holder{width: 100%;}
<div class="container">
<div class="holder">
<div class="button-group">
<button>1</button>
<button>2</button>
<button>3</button>
</div>
</div>
<div class="main-box"></div>
<div class="myfooter"> </div>
</div>
If you don't need margin to the right side of button-group, you can simply use .margin-right:auto; on .button-group to make it align itself to the left.
.container{
width: 500px;
height: 500px;
background: pink;
display: flex;
justify-content: flex-end;
flex-wrap: wrap;
}
.button-wrap {
display: flex;
flex-basis: 100%;
}
.button-group {
background: lightblue;
align-self: flex-start;
padding: 5px 10px;
margin-right: auto;
}
.main-box {
width: 450px;
height: 300px;
background: lime;
}
.myfooter {
width: 50%;
height: 10%;
background-color: black;
}
<div class="container">
<div class="button-wrap">
<div class="button-group">
<button></button>
<button></button>
<button></button>
</div>
</div>
<div class="main-box"></div>
<div class="myfooter"> </div>
</div>
Try this. You need to use a additional wrapper for button group and apply display: flex; flex-basis: 100%; for that wrapper.
https://jsfiddle.net/Sampath_Madhuranga/7ad2u804/
.container{
width: 500px;
height: 500px;
background: pink;
display: flex;
justify-content: flex-end;
flex-wrap: wrap;
}
.button-wrap {
display: flex;
flex-basis: 100%;
}
.button-group {
background: lightblue;
align-self: flex-start; /* Not working!*/
padding: 5px 10px;
}
.main-box {
width: 450px;
height: 300px;
background: lime;
}
.myfooter {
width: 50%;
height: 10%;
background-color: black;
}
<div class="container">
<div class="button-wrap">
<div class="button-group">
<button></button>
<button></button>
<button></button>
</div>
</div>
<div class="main-box"></div>
<div class="myfooter"> </div>
</div>
Here what happened, the flex-direction default is row, so your child elements is placed horizontally, but because the container width is static and it cant expand to wrap all of your child elements, it push them down, that cause your layout may look vertically but it is still placed horizontally. And in that case (flex-direction: row) the align-self property only set the flex items in the vertical direction.
How to fix it, first, you need to apply flex-direction: column. Then you can set the align-self for your flex-items and now and it will align self horizontally
.container{
width: 500px;
height: 500px;
background: pink;
flex-direction: column;
display: flex;
flex-wrap: wrap;
}
.button-group {
background: lightblue;
align-self: flex-start; /*working now!*/
padding: 5px 10px;
}
.main-box {
width: 450px;
height: 300px;
background: lime;
align-self: flex-end;
}
.myfooter {
width: 50%;
height: 10%;
background-color: black;
align-self: flex-end;
}
<div class="container">
<div class="button-group">
<button></button>
<button></button>
<button></button>
</div>
<div class="main-box"></div>
<div class="myfooter"> </div>
</div>
I need to place the orange button align at the bottom of the blue one.
With my current flex code I cannot get the result wanted. Any ideas how to fix it? Thanks
.content {
width: 350px;
height: 150px;
background-color: yellow;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.row1 {
background-color: red;
}
.row2 {
background-color: blue;
height: 100px
}
.icon {
width: 50px;
height: 50px;
background-color: orange;
align-items: center;
justify-content: center;
}
<div class="content">
<div class="row1">
</div>
<div class="row2">
<div class="icon">
</div>
</div>
</div>
You also need to set display: flex on row2 and then you can use align-self: flex-end on orange element.
.content {
width: 350px;
height: 150px;
background-color: yellow;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.row1 {
background-color: red;
}
.row2 {
background-color: blue;
display: flex;
height: 100px
}
.icon {
width: 50px;
height: 50px;
background-color: orange;
align-self: flex-end;
}
<div class="content">
<div class="row1"></div>
<div class="row2">
<div class="icon"></div>
</div>
</div>
Here we add this css in "row 2",
display: flex;
flex-direction: column;
its means if any object put at bottom then just parent block set above css and element we need to set as bottom add css "margin-top:auto;"
.content {
width: 350px;
height: 150px;
background-color: yellow;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.row1 {
background-color: red;
}
.row2 {
background-color: blue;
height: 100px;
display: flex;
flex-direction: column;
}
.icon {
width: 50px;
height: 50px;
background-color: orange;
align-items: center;
justify-content: center;
margin-top: auto;
}
<div class="content">
<div class="row1">
</div>
<div class="row2">
<div class="icon">
</div>
</div>
</div>
There is lot of stylings that can be removed from your code if it is not required, please find it here, I have changed .content and .row2 stylings
.content {
width: 350px;
height: 150px;
background-color: yellow;
display: flex;
}
.row1 {
background-color: red;
}
.row2 {
background-color: blue;
height: 100px;
flex: 1;
align-self: flex-end;
display: flex;
align-items: flex-end;
}
.icon {
width: 50px;
height: 50px;
background-color: orange;
align-items: center;
justify-content: center;
}
<div class="content">
<div class="row1">
</div>
<div class="row2">
<div class="icon">
</div>
</div>
</div>