Flexbox: how make one item higher than the rest? - css

I am building a page which has 8 items distributed over two rows using a flexbox container. Each item is 25% wide and 50% high. Because it is a horizontal scrolling page, I use px instead of % (values are generated by javascript based on the screen size). For this example I'm using a screen size of 1440px.
Now when I click on one of the items, it has to go to the very start, become twice as wide and twice as high.
It currently looks like this (ignore the blurry images please):
Initial state
Making the items wider is no problem (using flex-basis: 720px), but when I make the first item higher (height 100%), the items that were previously on the second row are no longer visible. Instead they are pushed down because of the first image: State when I make the first item bigger
What I actually want is that the smaller items are evenly distributed next to the bigger item. Is this possible?
This is my HTML markup (it contains web2py syntax, but there are 8 items in total):
<div class="scrollable">
<div class="flexcontainer">
{{for s in stages:}}
<div class="flexitem">
<img src="{{=URL('default', 'download', args=s.image)}}" class="stage-img">
</div>
{{pass}}
</div>
</div>
And this is my CSS:
.flexcontainer {
position: relative;
display: flex;
flex-flow: row wrap;
height: 100%;
width: 3000px; /* Hardcoded width for testing purposes */
}
.flexcontainer .flexitem {
flex: 1;
flex-basis: 360px;
height: 50%;
}
.flexcontainer .flexitem img {
width: 100%;
height: 100%;
}
/* Style for the active/clicked item */
.flexcontainer .flexitem.active {
flex-basis: 720px;
height: 100%;
}

Related

Two column layout taking full screen but allowing one column to expand

I'm trying to create a somewhat complicated layout with two columns taking up the remaining height of their parent but where one of the two columns is able to exceed these bounds if its content requires it. (In my case, this is an image but I don't believe this matters).
Here's a picture of the desired result which I'm sure will explain much better what I'm looking after.
Note: Here the red border represents the screen bounds (100vw x 100vh).
Here's what I tried so far:
.container {
display: flex;
flex-direction: column;
height: 100vh;
}
.top {
background: orchid;
}
.columns {
flex: 1;
display: flex;
}
.columns>* {
flex: 1;
}
.left {
background: lightgreen;
/* Just make it larger than 100% */
height: calc(100% + 25px);
}
.right {
background: cornflowerblue;
}
<div class="container">
<div class="top">
Top Content
</div>
<div class="columns">
<div class="left">
Left Column
</div>
<div class="right">
Right Column
</div>
</div>
</div>
<div class="additional">
Additional Content
</div>
As you can see, the "additional content" section isn't pushed properly. This is because the left column is overflowing but isn't technically affecting its parent. I believe that if it did, then the right column wouldn't be sized properly. So this seems like two conflicting conditions and I'm not sure what to do.
Im not sure if this is the result you are looking for, but give it a try and let me know.
.container {
display: flex;
flex-direction: column;
height:max-content;
}
.top {
background: orchid;
}
.columns {
flex: 1;
display: flex;
}
.columns>* {
flex: 1;
}
.left {
background: lightgreen;
/* Just make it larger than 100% */
height: fit-content;
}
.right {
background: cornflowerblue;
max-height: 100vh;
}
First, the container is set to max-content, meaning that it will be as hight as the highes element inside it. Next, the right column is set to max-height:100vh, meaning that if your left column is not as high as 100vh, your container will be affected by that right column. As soon as left column exceeds 100vh mark of right column, the height:fit-content of left column makes its parent expand, leading to pushing the additional content properly while right column stays at 100vh.
In this case, if left column does not have enough content, it will get smaller then right column, if this is not desired behaviour, change the left-column height as you desire, but always us height properties that are affected by content (or min/max).

Responsive arrangement of divs with flexbox [duplicate]

I have 3 divs inside a container. There are no nested divs.
I am using flex and order property.
On mobile, it is ok with order property.
But on larger screens it fails.
I did not use a container div for divs 2 and 3 in order to order them as 2,1,3 on mobile.
HTML FILE
<div class="container">
<div class="orange">1</div>
<div class="blue">2</div>
<div class="green">3</div>
</div>
CSS FILE
/*************** MOBILE *************/
.container
{
display: flex;
flex-wrap: wrap;
}
div.blue
{
order:1;
width: 100%;
}
div.orange
{
order:2;
width: 100%;
}
div.green
{
order:3;
width: 100%;
}
/***************************/
#media screen and (min-width:1200px)
{
.container
{
justify-content: space-between;
}
div.blue
{
order:2;
width: 36%;
}
div.orange
{
order:1;
width: 60%;
}
div.green
{
order:3;
width: 36%;
}
}
In your layout, using row wrap for the desktop view will be difficult, if not impossible, to implement with CSS. At a minimum, things would get overly complex. Why?
Because flexbox is not a grid system. It's a layout system designed to align content by distribution of space in the container.
In flexbox, items in a row wrap container must wrap to new rows. This means that div3 cannot wrap beneath div2. It must wrap beneath div1.
Here's how items wrap in a flex container with row wrap:
If div3 were to wrap under div2, that wouldn't be a row, that would be a grid, and flex items are confined to a straight, unbending row.
Put another way, you can't make a flex item wrap under another item in the same row.
As a result, white space created by items that aren't the tallest in the row is preserved in each column, creating unsightly gaps.
For your desired layout to work in row wrap, flex items would have to exit their row in order to close the gap – maybe with absolute positioning – which flexbox cannot do.
One way to align the items would be to wrap div2 and div3 in their own container. This new container would be a sibling to div1. It can then become a nested flex container with flex-direction: column. Now the gaps are gone and layout looks right.
Except, in this particular case, you need the order property to work (meaning all items must have the same parent), so a nested flex container is out of the question.
What may work is column wrap instead of row wrap:
/*************** MOBILE *************/
.container {
display: flex;
flex-direction: column;
height: 200px; /* necessary so items know where to wrap */
}
div.orange {
background-color: orange;
}
div.blue {
order: -1;
background-color: aqua;
}
div.green {
background-color: lightgreen;
}
.container > div {
width: 100%;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
/***************************/
#media screen and (min-width: 800px) {
.container {
flex-wrap: wrap;
}
div.orange {
flex-basis: 100%;
width: 50%;
}
div.blue {
flex-basis: 50%;
width: 50%;
order: 0;
}
div.green {
flex-basis: 50%;
width: 50%;
}
}
<div class="container">
<div class="orange">1</div>
<div class="blue">2</div>
<div class="green">3</div>
</div>
jsFiddle
Here are two other options:
Desandro Masonry
Masonry is a JavaScript grid layout library. It
works by placing elements in optimal position based on available
vertical space, sort of like a mason fitting stones in a wall.
source: http://masonry.desandro.com/
CSS Grid Layout Module Level 1
This CSS module defines a two-dimensional grid-based layout system, optimized for user interface design. In the grid layout model, the children of a grid container can be positioned into arbitrary slots in a predefined flexible or fixed-size layout grid.
source: https://drafts.csswg.org/css-grid/
Related post: Is it possible for flex items to align tightly to the items above them?

Masonry with Flexbox, dynamic height [duplicate]

I have 3 divs inside a container. There are no nested divs.
I am using flex and order property.
On mobile, it is ok with order property.
But on larger screens it fails.
I did not use a container div for divs 2 and 3 in order to order them as 2,1,3 on mobile.
HTML FILE
<div class="container">
<div class="orange">1</div>
<div class="blue">2</div>
<div class="green">3</div>
</div>
CSS FILE
/*************** MOBILE *************/
.container
{
display: flex;
flex-wrap: wrap;
}
div.blue
{
order:1;
width: 100%;
}
div.orange
{
order:2;
width: 100%;
}
div.green
{
order:3;
width: 100%;
}
/***************************/
#media screen and (min-width:1200px)
{
.container
{
justify-content: space-between;
}
div.blue
{
order:2;
width: 36%;
}
div.orange
{
order:1;
width: 60%;
}
div.green
{
order:3;
width: 36%;
}
}
In your layout, using row wrap for the desktop view will be difficult, if not impossible, to implement with CSS. At a minimum, things would get overly complex. Why?
Because flexbox is not a grid system. It's a layout system designed to align content by distribution of space in the container.
In flexbox, items in a row wrap container must wrap to new rows. This means that div3 cannot wrap beneath div2. It must wrap beneath div1.
Here's how items wrap in a flex container with row wrap:
If div3 were to wrap under div2, that wouldn't be a row, that would be a grid, and flex items are confined to a straight, unbending row.
Put another way, you can't make a flex item wrap under another item in the same row.
As a result, white space created by items that aren't the tallest in the row is preserved in each column, creating unsightly gaps.
For your desired layout to work in row wrap, flex items would have to exit their row in order to close the gap – maybe with absolute positioning – which flexbox cannot do.
One way to align the items would be to wrap div2 and div3 in their own container. This new container would be a sibling to div1. It can then become a nested flex container with flex-direction: column. Now the gaps are gone and layout looks right.
Except, in this particular case, you need the order property to work (meaning all items must have the same parent), so a nested flex container is out of the question.
What may work is column wrap instead of row wrap:
/*************** MOBILE *************/
.container {
display: flex;
flex-direction: column;
height: 200px; /* necessary so items know where to wrap */
}
div.orange {
background-color: orange;
}
div.blue {
order: -1;
background-color: aqua;
}
div.green {
background-color: lightgreen;
}
.container > div {
width: 100%;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
/***************************/
#media screen and (min-width: 800px) {
.container {
flex-wrap: wrap;
}
div.orange {
flex-basis: 100%;
width: 50%;
}
div.blue {
flex-basis: 50%;
width: 50%;
order: 0;
}
div.green {
flex-basis: 50%;
width: 50%;
}
}
<div class="container">
<div class="orange">1</div>
<div class="blue">2</div>
<div class="green">3</div>
</div>
jsFiddle
Here are two other options:
Desandro Masonry
Masonry is a JavaScript grid layout library. It
works by placing elements in optimal position based on available
vertical space, sort of like a mason fitting stones in a wall.
source: http://masonry.desandro.com/
CSS Grid Layout Module Level 1
This CSS module defines a two-dimensional grid-based layout system, optimized for user interface design. In the grid layout model, the children of a grid container can be positioned into arbitrary slots in a predefined flexible or fixed-size layout grid.
source: https://drafts.csswg.org/css-grid/
Related post: Is it possible for flex items to align tightly to the items above them?

How can I make this vertical list fill the vertical height of the container?

I am using flexbox to create my 2 column layout. Everything is working well, however I'd like to have my list items in my right column always take up the full height. Each <li> element contains an <img> element.
When I start to shrink the window width, as you can see, the <ul> element's height starts to scale up to keep it's aspect.
If I make the window really wide, the list element(s) will start to get clipped off.
I'd like to always be able to see all 4 list items. I'd be OK if I have to lock the width(s) or height(s) down. As you can see, I've set a min/max height but no luck. I am also OK with using the <li> elements as a container/viewable area for the images. Meaning, if the image inside the <li> gets clipped off overflow:hidden or something - that's fine. I am just trying to keep the two columns 50% each, and the right column always take the full height.
HTML
<div id="container">
<div id="foo">
...
</div>
<div id="bar">
<ul>
<li><img></li>
<li><img></li>
</ul>
</div>
</div>
CSS
#container {
display: flex;
flex-direction: row;
height: 600px;
min-height: 600px;
max-height: 600px;
}
#foo {
display: flex;
flex-direction: column;
order: 1;
width: 50%;
}
#bar {
display: flex;
flex-direction: column;
order: 2;
width: 50%;
}
Only give display: flex to the parent container. All children the inside parent container will be equal to the height of the child with the maximum height.
.container {
display: flex;
}
.foo {
width: 50%;
order: 1;
}
.bar {
width: 50%;
order: 2;
}

Flexbox wrapping issues [duplicate]

I have 3 divs inside a container. There are no nested divs.
I am using flex and order property.
On mobile, it is ok with order property.
But on larger screens it fails.
I did not use a container div for divs 2 and 3 in order to order them as 2,1,3 on mobile.
HTML FILE
<div class="container">
<div class="orange">1</div>
<div class="blue">2</div>
<div class="green">3</div>
</div>
CSS FILE
/*************** MOBILE *************/
.container
{
display: flex;
flex-wrap: wrap;
}
div.blue
{
order:1;
width: 100%;
}
div.orange
{
order:2;
width: 100%;
}
div.green
{
order:3;
width: 100%;
}
/***************************/
#media screen and (min-width:1200px)
{
.container
{
justify-content: space-between;
}
div.blue
{
order:2;
width: 36%;
}
div.orange
{
order:1;
width: 60%;
}
div.green
{
order:3;
width: 36%;
}
}
In your layout, using row wrap for the desktop view will be difficult, if not impossible, to implement with CSS. At a minimum, things would get overly complex. Why?
Because flexbox is not a grid system. It's a layout system designed to align content by distribution of space in the container.
In flexbox, items in a row wrap container must wrap to new rows. This means that div3 cannot wrap beneath div2. It must wrap beneath div1.
Here's how items wrap in a flex container with row wrap:
If div3 were to wrap under div2, that wouldn't be a row, that would be a grid, and flex items are confined to a straight, unbending row.
Put another way, you can't make a flex item wrap under another item in the same row.
As a result, white space created by items that aren't the tallest in the row is preserved in each column, creating unsightly gaps.
For your desired layout to work in row wrap, flex items would have to exit their row in order to close the gap – maybe with absolute positioning – which flexbox cannot do.
One way to align the items would be to wrap div2 and div3 in their own container. This new container would be a sibling to div1. It can then become a nested flex container with flex-direction: column. Now the gaps are gone and layout looks right.
Except, in this particular case, you need the order property to work (meaning all items must have the same parent), so a nested flex container is out of the question.
What may work is column wrap instead of row wrap:
/*************** MOBILE *************/
.container {
display: flex;
flex-direction: column;
height: 200px; /* necessary so items know where to wrap */
}
div.orange {
background-color: orange;
}
div.blue {
order: -1;
background-color: aqua;
}
div.green {
background-color: lightgreen;
}
.container > div {
width: 100%;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
/***************************/
#media screen and (min-width: 800px) {
.container {
flex-wrap: wrap;
}
div.orange {
flex-basis: 100%;
width: 50%;
}
div.blue {
flex-basis: 50%;
width: 50%;
order: 0;
}
div.green {
flex-basis: 50%;
width: 50%;
}
}
<div class="container">
<div class="orange">1</div>
<div class="blue">2</div>
<div class="green">3</div>
</div>
jsFiddle
Here are two other options:
Desandro Masonry
Masonry is a JavaScript grid layout library. It
works by placing elements in optimal position based on available
vertical space, sort of like a mason fitting stones in a wall.
source: http://masonry.desandro.com/
CSS Grid Layout Module Level 1
This CSS module defines a two-dimensional grid-based layout system, optimized for user interface design. In the grid layout model, the children of a grid container can be positioned into arbitrary slots in a predefined flexible or fixed-size layout grid.
source: https://drafts.csswg.org/css-grid/
Related post: Is it possible for flex items to align tightly to the items above them?

Resources