Resize flex items to fit container (prevent items from overflowing) - html

I've been struggling with an issue that i think will have a pretty simple solution, but i just can't see it right now. I have a nested flexbox layout. The first level of flex items are divs that are display:flex themselves, and depending on class they can have a flex-directon: of row or column. Both the first and second level of these nested flex items should grow to fill up the remaining parent size, and shrink if new elements are added, never overflowing.
My Problem: When adding new flex items to the "first level", this seems to work fine. However, adding new flex items to the second level seems to always overflow the parent container height.
As i'm not really good at describing stuff like this, here's a picture of what i need:
The purple box is the parent container (not flex)
The orange box is the flex container with flex-direction: row, with the red lines being its flex items (each item is a flexbox as well).
The blue lines are the nested flex items.
Nested Flexbox layout
Adding new red items works and expands or shrinks as needed, but adding new blue items, overflows the container.
https://jsfiddle.net/t40x7or8/
Here's my code sample:
CSS
width: 1800px;
height: 500px;
border: 4px blue solid;
}
.flex-container {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.flex-item {
flex-grow: 1;
flex-basis: 0;
display: flex;
}
.flex-item > div {
flex-grow: 1;
border: 1px solid orange;
}
.height-1 {
flex-direction: column;
max-height: 100%;
}
.height-2 {
max-height: 100%;
}
img {
width: 100%;
height: 100%;
object-fit: cover;
}
HTML
<div class="flex-container">
<div class="height-2 flex-item">
<div class="img-div">
<img src="https://picsum.photos/1080/600" />
</div>
</div>
<div class="height-1 flex-item">
<div class="img-div">
<img src="https://picsum.photos/1080/601" />
</div>
<div class="img-div">
<img src="https://picsum.photos/1080/602" />
</div>
</div>
</div>
</div>
Sorry for the chaotic description, i'm quite bad at these kind of things.
Thanks for the help

I think we should use flex: 1 1 0 for the fix the layout of the flex items.
And using width: 100% to control the size of the inner image.
https://jsfiddle.net/ramseyfeng/kxf46bju/
.page {
border: 3px solid green;
width: 600px;
height: 300px;
}
.flex {
display: flex;
}
.cols {
display: flex;
flex-direction: row;
}
.rows {
display: flex;
flex-direction: column;
}
.flex-1-1-0 {
flex: 1 1 0;
}
.img-div {
flex: 1 1 0;
display: flex;
}
.img-div img {
width: 100%;
}
<div class="page cols">
<div class="flex-1-1-0 rows">
<div class="img-div">
<img src="https://picsum.photos/1080/600" />
</div>
</div>
<div class="flex-1-1-0 rows">
<div class="img-div">
<img src="https://picsum.photos/1080/601" />
</div>
<div class="img-div">
<img src="https://picsum.photos/1080/602" />
</div>
</div>
<div class="flex-1-1-0 rows">
<div class="img-div">
<img src="https://picsum.photos/1080/607" />
</div>
<div class="img-div">
<img src="https://picsum.photos/1080/608" />
</div>
</div>
<div class="flex-1-1-0 rows">
<div class="img-div">
<img src="https://picsum.photos/1080/605" />
</div>
<div class="img-div">
<img src="https://picsum.photos/2000/1000" />
</div>
<div class="img-div">
<img src="https://picsum.photos/2000/1001" />
</div>
</div>
</div>

Related

How to make divs stack on top of each other as page is minimized

I am trying to figure out how to make a section of divs on my page responsive so that as the page is minimized, the divs begin stacking on top of each other. I've tried flex-direction: column but that doesn't seem to be working. I have attached photos of what I am trying to achieve.
Here is my HTML:
<div>
<!-- <section> -->
<center>
<div class="container">
<div class="item3">
<image-tag src="https://></image-tag>
</div>
<div class="item3">
<image-tag src="https://></image-tag>
</div>
<div class="item3">
<image-tag src="https://></image-tag>
</div>
<div class="item3 idk">
<image-tag src="https://></image-tag>
</div>
<div class="item3 idk">
<image-tag src="https://></image-tag>
</div>
</div>
</center>
<!-- </section> -->
</div>
CSS
.container {
display: flex;
flex-direction: row;
}
Photos of what I am trying to achieve
Desktop
Tablet
Mobile
FYI I have taken some code out for confidentiality purposes.
try flex-wrap: wrap;
use .item3{ flex: 1 } if needed
A flex-box solution is hard because it is meant for 1 directional layouts where as your desired layout is 2 directional based on screen width. However, you can come close to the desired layout behavior by using flex-wrap which depends on either the width of your flex-items or flex-container to force the items to a new line. Try the below and adjust either the items' or container's width
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
align-items: start;
}
You can give max-width: 1200px; to your body element then
margin:0 auto to center vertically.
Than create a flexbox inside container class and make flex-wrap: wrap; to make flexbox create new row else all the images will always stay in same row.
You can also add padding: 0 1rem; for always having empty spaces when images comes to limit of wrapping.
/* RESET */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background-color: antiquewhite;
min-height: 100vh;
max-width: 1200px;
margin: 0 auto;
}
img {
max-width: 100%;
display: block;
}
/* RESET ENDS */
.container {
display: flex;
flex-direction: row;
justify-content: center;
flex-wrap: wrap;
gap: 1rem;
padding: 0 1rem;
}
<div class="container">
<div class="item">
<img src="https://source.unsplash.com/random/375x375" alt="" />
</div>
<div class="item">
<img src="https://source.unsplash.com/random/375x375" alt="" />
</div>
<div class="item">
<img src="https://source.unsplash.com/random/375x375" alt="" />
</div>
<div class="item">
<img src="https://source.unsplash.com/random/375x375" alt="" />
</div>
<div class="item">
<img src="https://source.unsplash.com/random/375x375" alt="" />
</div>
</div>

How do I make one column in my flex table occupy less width than the others?

I'm trying to create an HTML table using DIVs and the flex CSS property. Roughly, all my rows look like
<div class='row'>
<div class='col'>
<div class='data-cell'>
Col A
</div>
</div>
<div class='col'>
<div class='data-cell'>
Col B
</div>
</div>
<div class='col'>
<div class='data-cell'>
Col C
</div>
</div>
<div class='col'>
<div class='data-cell'>
<div class='img-wrapper'>
<img src='images/delete.png' title='Delete' />
</div>
</div>
</div>
Below is the CSS I'm using
.row {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 100%;
padding: 15px 0 15px 30px;
border-bottom: 1px solid $lightGrey
}
.col {
display: flex;
flex-direction: col;
flex-basis: 100%;
flex: 1;
}
.header-row {
color: $eclipse;
font-weight: bold;
}
.img-wrapper {
width: 100%;
text-align: right;
}
Right now the cells in each row take up 1/4th of the row width. What I would like to change is make the col with the image only be the size of the image and have the remaining rows even split up the remaining space. How do I do that using DIVs and flex?

Shrink images to fit in flexbox with wrapping rows

I want an arbitrary number of images to shrink to fit inside a fixed-width div.
It seems that flexbox is good for this purpose, but I can't seem to get it to work with wrapping multiple rows.
If I set flex-flow to row wrap and flex to 1 1 auto, the images are too big.
.container {
display: flex;
flex-flow: row wrap;
border: 1px solid black;
width: 300px;
height: 300px;
}
.image {
flex: 1 1 auto;
}
img {
max-width: 100%;
}
<div class="container">
<div class="image">
<img src="http://www.placebacon.net/400/300">
</div>
<div class="image">
<img src="http://www.placebacon.net/400/300">
</div>
<div class="image">
<img src="http://www.placebacon.net/400/300">
</div>
</div>
If I set flex-flow to just row or flex to 1 1 0, the images don't wrap onto multiple lines:
.container {
display: flex;
flex-flow: row wrap;
border: 1px solid black;
width: 300px;
height: 300px;
}
.image {
flex: 1 1 0;
}
img {
max-width: 100%;
}
<div class="container">
<div class="image">
<img src="http://www.placebacon.net/400/300">
</div>
<div class="image">
<img src="http://www.placebacon.net/400/300">
</div>
<div class="image">
<img src="http://www.placebacon.net/400/300">
</div>
</div>
How can I make the images expand enough to wrap as much as possible to fill the div, but not so much they break out of it?
If I set flex-flow to row wrap and flex to 1 1 auto, the images are too big.
With flex-basis: auto your item will take the size of its content (the image, in this case). That's what you're getting in your first demo: The intrinsic width of the image.
If I set flex-flow to just row or flex to 1 1 0, the images don't wrap onto multiple lines.
With flex-basis: 0 your item will ignore content size and distribute all space in the row evenly among items. That's what's happening in your second demo: It's creating three equal width items. As a result, there is no reason to wrap.
To control the size of flex items you need to define their flex-basis. Here's a rough sketch:
.container {
display: flex;
flex-flow: row wrap;
align-content: flex-start; /* pack wrapping lines to the top */
border: 1px solid black;
width: 300px;
height: 300px;
}
.image {
flex: 0 0 30%;
margin: 5px;
}
img {
max-width: 100%;
}
<div class="container">
<div class="image">
<img src="http://www.placebacon.net/400/300">
</div>
<div class="image">
<img src="http://www.placebacon.net/400/300">
</div>
<div class="image">
<img src="http://www.placebacon.net/400/300">
</div>
<div class="image">
<img src="http://www.placebacon.net/400/300">
</div>
<div class="image">
<img src="http://www.placebacon.net/400/300">
</div>
</div>
Just for fun.
var container1 = document.querySelector('.container1'),
container2 = document.querySelector('.container2'),
img = container2.querySelectorAll('.container2 img'),
width = 50,
stop = false;
expand();
function expand() {
for (var i = 0; i < img.length; i++) {
img[i].style.width = width + 'px';
}
if (stop) return;
if (container2.clientHeight < container1.clientHeight) {
width++;
setTimeout(function() {
expand()
}, 10);
} else {
width--;
stop = true;
expand();
}
}
.container1 {
border: 1px solid black;
height: 300px;
width: 300px;
}
.container2 {
font-size: 0;
}
<div class="container1">
<div class="container2">
<img src="http://www.placebacon.net/400/300">
<img src="http://www.placebacon.net/400/300">
<img src="http://www.placebacon.net/400/300">
</div>
</div>

How to use `flex: grow` on floating content?

I have a header with 2 rows of 2 Foundation columns of content, as below:
<div class="wrapper">
<div class="header row">
<div class="large-6 columns">
HEADER
</div>
<div class="large-6 columns">
menu
</div>
</div>
<div class="row">
<div class="large-5 none show-for-medium columns info">
Some information to the left
</div>
<div class="large-7 columns">
<div class="image-container">
<div class="image">
image to the right
</div>
</div>
</div>
</div>
</div>
The .header height is dynamic and not set. I want the .image element to take up 100% of the remaining vertical space.
eg:
To that affect I have tried using flex and flex-grow, eg:
.wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%;
}
.image-container {
flex-grow: 1;
}
but had no luck, see fiddle: https://jsfiddle.net/9kkb2bxu/46/
Would anyone know how I could negate the dynamic height of the header from the 100vh of the image container?
.wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%;
border: 1px solid black;
background-color: #ccc;
}
.row {
width: 100%;
}
.header {
background-color: green;
}
.info {
background-color: yellow;
border: 1px solid #ccc;
}
.image-container {
border: 1px solid black;
display: flex;
}
.image {
background-color: red;
flex-grow: 1;
width: 100%;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.1/css/foundation.min.css" rel="stylesheet"/>
<div class="wrapper">
<div class="header row">
<div class="large-6 columns">
<h1>
HEADER
</h1>
</div>
<div class="large-6 columns">
<h1>
menu
</h1>
</div>
</div>
<div class="row">
<div class="large-5 none show-for-medium columns info">
Some information to the left
</div>
<div class="large-7 columns">
<div class="image-container">
<div class="image">
image to the right
</div>
</div>
</div>
</div>
</div>
Set the second row to take up the rest of the remaining height with flex: 1 and make sure you nest that flex with display: flex:
.row.target-row {
flex: 1;
display: flex;
}
Set the .image-container to 100% height of its column parent.
.image-container {
height: 100%;
}
By default both columns will expand. Stop the left column from expanding with:
.large-5 {
align-self: flex-start;
}
(flex-start reference: https://stackoverflow.com/a/40156422/2930477)
Complete Example
.wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%;
border: 1px solid black;
background-color: #ccc;
}
.row {
width: 100%;
}
.header {
background-color: green;
}
.info {
background-color: yellow;
border: 1px solid #ccc;
}
.image-container {
height: 100%;
background-color: red;
}
.large-5 {
align-self: flex-start;
}
.row.target-row {
flex: 1;
display: flex;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.1/css/foundation.min.css" rel="stylesheet" />
<div class="wrapper">
<div class="header row">
<div class="large-6 columns">
<h1>
HEADER
</h1>
</div>
<div class="large-6 columns">
<h1>
menu
</h1>
</div>
</div>
<div class="row target-row">
<div class="large-5 none show-for-medium columns info">
Some information to the left
</div>
<div class="large-7 columns">
<div class="image-container">
<div class="image">
image to the right
</div>
</div>
</div>
</div>
</div>
flex-grow only applies to flex children.
.image-container isn't a direct child of a display: flex element, so that property has no effect.
Plus, it affects the flex axis, which is not what you want.
Instead, you need to put those two elements in their own flex row, and use align-items (on the parent) and align-self (on either child) so that the first one aligns (on the cross axis) to flex-start (stick to top) and the second one to stretch.
You'll also want that flex row (parent) to have flex-grow: 1 so that it stretches along the vertical flex axis of its parent (.wrapper) to fill the rest of the page (otherwise, the grandchild will have nothing to stretch to).
For more information, read a good flex tutorial.
div.wrapper > div:not(.header).row {
flex: 1; /* 1 */
display: flex; /* 1 */
}
div.large-7.columns {
display: flex; /* 2 */
}
div.image-container { /* 3 */
flex: 1;
}
div.large-5.show-for-medium { /* 4 */
align-self: flex-start;
}
jsFiddle
Notes:
flex container and items consume all remaining height of respective parents
give children full height (via align-items: stretch initial setting)
flex item consumes all available width
yellow box does not need to expand to full height; now set to content height

flex-wrap not working in Safari and float left isn't an option

I have a setup where I am trying to have a div centered in the screen, yet the images within the div flex-wrap based on the parent divs width.
This works in all browsers except Safari.
float: left; won't work due to the centering issue.
I have a fiddle with the scene broken down...
http://jsfiddle.net/6f59t7qh/2/
<div class="gallery">
<div class="galleryBlock">
<div class="galleryTile">
<img src="http://hdcomputerwallpaper.com/wp-content/uploads/2013/12/Puppy-images.jpg" />
</div>
<div class="galleryTile">
<img src="http://hdcomputerwallpaper.com/wp-content/uploads/2013/12/Puppy-images.jpg" />
</div>
<div class="galleryTile">
<img src="http://hdcomputerwallpaper.com/wp-content/uploads/2013/12/Puppy-images.jpg" />
</div>
<div class="galleryTile">
<img src="http://hdcomputerwallpaper.com/wp-content/uploads/2013/12/Puppy-images.jpg" />
</div>
<div class="galleryTile">
<img src="http://hdcomputerwallpaper.com/wp-content/uploads/2013/12/Puppy-images.jpg" />
</div>
<div class="galleryTile">
<img src="http://hdcomputerwallpaper.com/wp-content/uploads/2013/12/Puppy-images.jpg" />
</div>
<div class="galleryTile">
<img src="http://hdcomputerwallpaper.com/wp-content/uploads/2013/12/Puppy-images.jpg" />
</div>
</div>
</div>
.gallery {
text-align: center;
background-color: green;
}
.galleryBlock {
width: 585px;
display: -webkit-inline-flex;
display: -ms-inline-flexbox;
display: inline-flex;
flex-wrap: wrap; /* flex-wrap not working in Safari*/
background-color: red;
}
.galleryTile {
position: relative;
height: 100px;
width: 190px;
overflow: hidden;
margin: 0 5px 5px 0;
}
any thoughts would be great!
Thanks.
Check this:
center a block and set its children flex
1.You should always set the size of your image in px of percentage. if it's flexible
width: 100%;
height: 100%;
so the image could change with its parent's size.
2.just use these two can set a block horizontal center. text-align is not appropriate in this situation.
margin-left: auto;
margin-right: auto;
3.set .galleryBlock
display: -webkit-flex; /* Safari */
display: flex;
and set .galleryTile
-webkit-flex: 1; /* Safari 6.1+ */
-ms-flex: 1; /* IE 10 */
flex: 1;
Here's flex tutorial in W3C