Fill vertical space with Flexbox in a list of items - css

I have a list of items, each one in display: flex to position its children elements. The height of the item is given by the image, and the button at the right position should fill the vertical space of the item. But I can't do that.
.Main-item {
display: flex;
border: 1px solid gray;
margin-bottom: 2px;
}
.Main-img {
height: 50px;
width: 50px;
overflow: hidden;
object-fit: cover;
object-position: center;
border-radius: 50%;
}
.Main-name {
display: flex;
flex-wrap: wrap;
flex-direction: column;
justify-content: space-evenly;
align-items: flex-start;
flex: 1 1;
padding: 0 10px;
}
.Main-buttonWrapper {
height: 100%;
width: 146px;
}
.Main-button {
height: 100%;
width: 100%;
}
<div>
<div class="Main-item">
<img class="Main-img" src="https://picsum.photos/200/300" />
<div class="Main-name">Lorem ipsum</div>
<div class="Main-buttonWrapper"><button class="Main-button">button</button></div>
</div>
<div class="Main-item">
<img class="Main-img" src="https://picsum.photos/200/300" />
<div class="Main-name">Lorem ipsum</div>
<div class="Main-buttonWrapper"><button class="Main-button">button</button></div>
</div>
<div class="Main-item">
<img class="Main-img" src="https://picsum.photos/200/300" />
<div class="Main-name">Lorem ipsum</div>
<div class="Main-buttonWrapper"><button class="Main-button">button</button></div>
</div>
<div class="Main-item">
<img class="Main-img" src="https://picsum.photos/200/300" />
<div class="Main-name">Lorem ipsum</div>
<div class="Main-buttonWrapper"><button class="Main-button">button</button></div>
</div>
</div>
Any idea will be welcome!

When you create a flex container various default flex rules come into play.
Two of these default rules are flex-direction: row and align-items: stretch. This means that flex items will automatically align in a single row, and each item will fill the height of the container.
If you change the value of align-items to for example flex-start it will change the default behavior 'stretch' as well if you set a specific height to the child of a flex container.
So just remove the height: 100% from .Main-buttonWrapper and it will have the default behavior.
For a better understanding look this answer: https://stackoverflow.com/a/33220564/4966662

I've given a height to the Main-item + align-items:stretch;. I hope this is what you need.
.Main-item {
align-items:stretch;
height: 50px;
}
.Main-element {
padding-top: 16px;
}
.Main-item {
display: flex;
border: 1px solid gray;
margin-bottom: 2px;
align-items:stretch;
height: 50px;
}
.Main-img {
width: 50px;
overflow: hidden;
object-fit: cover;
object-position: center;
border-radius: 50%;
}
.Main-name {
display: flex;
flex-wrap: wrap;
flex-direction: column;
justify-content: space-evenly;
align-items: flex-start;
flex: 1 1;
padding: 0 10px;
}
.Main-buttonWrapper {
width: 146px;
}
.Main-button {
width: 100%;
height: 100%;
}
<div class="Main-element">
<div class="Main-item">
<img class="Main-img" src="https://picsum.photos/200/300" />
<div class="Main-name">Lorem ipsum</div>
<div class="Main-buttonWrapper"><button class="Main-button">button</button></div>
</div>
<div class="Main-item">
<img class="Main-img" src="https://picsum.photos/200/300" />
<div class="Main-name">Lorem ipsum</div>
<div class="Main-buttonWrapper"><button class="Main-button">button</button></div>
</div>
<div class="Main-item">
<img class="Main-img" src="https://picsum.photos/200/300" />
<div class="Main-name">Lorem ipsum</div>
<div class="Main-buttonWrapper"><button class="Main-button">button</button></div>
</div>
<div class="Main-item">
<img class="Main-img" src="https://picsum.photos/200/300" />
<div class="Main-name">Lorem ipsum</div>
<div class="Main-buttonWrapper"><button class="Main-button">button</button></div>
</div>
</div>

A flex item stretches along the container cross axis by default, so the only thing you need to make the button stretch visually as well, is to make the button container a flex container by adding display: flex to .Main-buttonWrapper.

Related

Image goes out of flexbox

I have an image that I want to fit in flexbox.
Card has fixed size, and I want the image to fit in without specifying size but it just ignores flexbox.
.card {
border: 2px solid #072227;
border-radius: 20px;
display: flex;
height: 30vh;
width: 40vw;
}
.card__profile-image {
display: flex;
flex-direction: column;
}
.img__cont img {
height: 100%;
}
.img__cont {
}
.card__name {
min-height: 100%;
}
<div class="card">
<div class="card__section card__profile-image">
<div class="img__cont">
<!-- <div class="image"> -->
<img src="https://scontent.fkiv9-2.fna.fbcdn.net/v/t39.30808-6/317808332_704091791080096_1098720845539800517_n.jpg?_nc_cat=1&ccb=1-7&_nc_sid=09cbfe&_nc_ohc=FFO8v3dmkM8AX_aR9js&_nc_ht=scontent.fkiv9-2.fna&oh=00_AfDQCQcHmZH4QuauHvdxiLEFX0rExv9gMENs8ptsEzdoYg&oe=63DEF9AD" alt="Profile Picture" />
<!-- </div> -->
</div>
<div class="card__name">Alex Hill</div>
</div>
<div class="card__section">
<div class="card__info-top">
<span class="info__top-job">Senior Developer | A1-D</span>
<span class="info__top-contact">alexhill#0001</span>
</div>
<div class="card__info-bottom">6 000$</div>
</div>
</div>
https://codepen.io/watermelon-and-me/pen/jOpQGje
UPD.
Expected result:
https://i.imgur.com/MBRLAMp.png
On .img__cont and .img__cont img, set max-width and max-height to 100% each.
.card {
border: 2px solid #072227;
border-radius: 20px;
display: flex;
height: 30vh;
width: 40vw;
}
.card__profile-image {
display: flex;
flex-direction: column;
}
.img__cont, .img__cont img {
max-width: 100%;
max-height: 100%;
}
.card__name {
min-height: 100%;
}
<div class="card">
<div class="card__section card__profile-image">
<div class="img__cont">
<!-- <div class="image"> -->
<img src="https://scontent.fkiv9-2.fna.fbcdn.net/v/t39.30808-6/317808332_704091791080096_1098720845539800517_n.jpg?_nc_cat=1&ccb=1-7&_nc_sid=09cbfe&_nc_ohc=FFO8v3dmkM8AX_aR9js&_nc_ht=scontent.fkiv9-2.fna&oh=00_AfDQCQcHmZH4QuauHvdxiLEFX0rExv9gMENs8ptsEzdoYg&oe=63DEF9AD" alt="Profile Picture" />
<!-- </div> -->
</div>
<div class="card__name">Alex Hill</div>
</div>
<div class="card__section">
<div class="card__info-top">
<span class="info__top-job">Senior Developer | A1-D</span>
<span class="info__top-contact">alexhill#0001</span>
</div>
<div class="card__info-bottom">6 000$</div>
</div>
</div>

What am i doing wrong with flexbox trying to align these images?

So I am trying to align images one next to another with display flex but they're not working, tried a lot of things but none of them helped
.container {
display: flex;
width: 100%;
flex-wrap: wrap;
}
.image {
width: 100%;
margin-right: 10px;
}
<div class="container">
<div class="image">
<img src="photo.jpg">
</div>
<div class="image">
<img src="photo.jpg">
</div>
<div class="image">
<img src="photo.jpg">
</div>
<div class="image">
<img src="photo.jpg">
</div>
</div>
You need to remove
width: 100%;
from your .image styles.
Working Example:
.container {
display: flex;
width: 100%;
flex-wrap: wrap;
}
.image {
margin-right: 10px;
}
<div class="container">
<div class="image">
<img src="photo.jpg">
</div>
<div class="image">
<img src="photo.jpg">
</div>
<div class="image">
<img src="photo.jpg">
</div>
<div class="image">
<img src="photo.jpg">
</div>
</div>
Update:
Do you want a single row of 4 images? If so, you'll need to give each image a width or a flex-basis of equal to or less than 25% of the .container.
Otherwise an image will be assumed to have a width corresponding to its original size.
You can achieve this by inserting .image {flex: 0 1 25%;} into your CSS:
.container {
display: flex;
width: 100%;
flex-wrap: wrap;
}
.image {
flex: 0 1 25%;
margin-right: 10px;
}

How to scale a number of images to fill area

I'm trying to fill an area of web page of a certain, fixed size with an unknown number of images (max 10), maximising the size of the images without overflowing the area. To be mobile friendly, I want it to work both in landscape and portrait mode without needing scrolling.
I've been trying to use flexboxes to have the images wrap, but then they don't scale down and end up overflowing the area. If I use non-wrapping flexboxes, the images scale in landscape mode, but not in portrait. I feel there should be a nice, simple solution to this. Any ideas?
Update:
Here's the essence of the code I've got so far. I've been trying a lot of different things, but this is the cleanest.
html {
height: 100%;
}
body {
padding-top: 0;
padding-bottom: 0;
height: 100%;
}
.container {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
flex-wrap: nowrap;
text-align: center;
}
.above {
margin-bottom: 20px;
font-size: larger;
background-color: lightgrey;
}
.middle {
flex-grow: 1;
max-height: 100%;
}
.below {
margin-top: 20px;
background-color: lightgrey;
}
img {
border: 5px solid transparent;
height: 100%;
}
.images {
flex-direction: row;
justify-content: center;
display: flex;
flex-wrap: wrap;
height: 100%;
}
.image {
margin: 5px;
}
<html>
<body>
<div class="container">
<div class="above">
Some text about the images
</div>
<div class="middle">
<div class="images">
<div class="image">
<img src="https://dummyimage.com/200x200/000/fff" alt="" />
</div>
<div class="image">
<img src="https://dummyimage.com/200x200/000/fff" alt="" />
</div>
<div class="image">
<img src="https://dummyimage.com/200x200/000/fff" alt="" />
</div>
<div class="image">
<img src="https://dummyimage.com/200x200/000/fff" alt="" />
</div>
<div class="image">
<img src="https://dummyimage.com/200x200/000/fff" alt="" />
</div>
<div class="image">
<img src="https://dummyimage.com/200x200/000/fff" alt="" />
</div>
<div class="image">
<img src="https://dummyimage.com/200x200/000/fff" alt="" />
</div>
<div class="image">
<img src="https://dummyimage.com/200x200/000/fff" alt="" />
</div>
<div class="image">
<img src="https://dummyimage.com/200x200/000/fff" alt="" />
</div>
<div class="image">
<img src="https://dummyimage.com/200x200/000/fff" alt="" />
</div>
</div>
</div>
<div class="below">
<button>Ok</button>
<button>Cancel</button>
</div>
</div>
</body>
</html>
The point is to try to get the images to stay completely within the div called "middle", but scaled as large as possible. Here are a few wireframes.
Landscape, 10 images:
Portrait, 10 images:
Portrait, 4 images
I Think you need to consider flex property here, it's the short hand version of flex-grow, flex-shrink, and flex-basis properties. See if this is what you're looking for.
html,body{
padding: 0;
margin: 0;
width: 100vw;
box-sizing: border-box;
}
.container{
width: 100%;
display: flex;
align-items: flex-start;
justify-content: flex-start;
flex-direction: column;
}
.row{
display: flex;
width: 100%;
flex-direction: row;
}
.col{
display: flex;
width: 100%;
flex-wrap: wrap;
justify-content: center;
align-items: center;
text-align: center;
}
.item{
display: flex;
max-width: 100%;
height: 150px;
background-color: #222;
margin: 1%;
flex: 1 1 15%;
}
#media only screen and (max-width: 600px) {
.item {
height: 100px;
flex: 1 1 45%;
max-width: 100%;
}
}
<div class="container">
<div class="row ">
<div class="col">
<h1>some text about images</h1>
</div>
</div>
<div class="row">
<div class="col">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</div>
<div class="row">
<div class="col">
<p>Some other elements</p>
</div>
</div>
</div>

Align flex children to top

How do I get flexbox children to line up vertically to the top edge of each row?
HTML:
#container {
align-items: flex-start;
align-content: flex-start;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.child {
margin: auto;
border: 1px dotted #CCC;
}
img, h3 {
width: 160px;
}
<div id="container">
<div class="child">
<img src="http://via.placeholder.com/160x160">
<h3>Title</h3>
</div>
<div class="child">
<img src="http://via.placeholder.com/160x160">
<h3>The quick brown fox jumps over the lazy dog</h3>
</div>
<div class="child">
<img src="http://via.placeholder.com/160x160">
<h3>Title</h3>
</div>
<div class="child">
<img src="http://via.placeholder.com/160x160">
<h3>Title</h3>
</div>
</div>
Demo: https://codepen.io/anon/pen/GOBzOp
What I see is but I want it to look like
change margin:auto of .child to margin: 0px auto.
Give justify-content: space-around; to #container id instead of justify-content: space-between; and remove margin: auto; to .child class.
#container {
align-items: flex-start;
align-content: flex-start;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
}
.child {
border: 1px dotted #CCC;
}
img, h3 {
width: 160px;
}
<div id="container">
<div class="child">
<img src="http://via.placeholder.com/160x160">
<h3>Title</h3>
</div>
<div class="child">
<img src="http://via.placeholder.com/160x160">
<h3>The quick brown fox jumps over the lazy dog</h3>
</div>
<div class="child">
<img src="http://via.placeholder.com/160x160">
<h3>Title</h3>
</div>
<div class="child">
<img src="http://via.placeholder.com/160x160">
<h3>Title</h3>
</div>
</div>
A simple fix would be changing margin: auto; to margin: 0 auto; this will prevent the box auto centralize vertically but retaining its horizontal alignment, like so:
.child {
border: 1px dotted #CCC;
margin: 0 auto;
}
you can try like
.child {
vertical-align: baseline; //either of them
margin: 0px auto; // any one
}

flexbox height adjust to content

I use a "full design" flexbox.
I have a weird issue : I have a container that takes all the remaining space and I want in this container that the child, which is also flexbox, to have their height adjust to their content.
Here is the issue:
body, html {
width:100%;
height:100%;
display:flex;
}
.container {
display:flex;
flex:1;
flex-wrap:wrap;
}
.icon {
width:10vh;
margin:10px;
display:flex;
flex-direction:column;
}
.img {
width:10vh;
height:10vh;
display:flex;
align-items:center;
justify-content:center;
background-color:red;
}
.text {
text-align:center;
}
<div class="container">
<div class="icon">
<div class="img">
</div>
<div class="text">
action 1
</div>
</div>
<div class="icon">
<div class="img">
</div>
<div class="text">
Action 2
</div>
</div>
<div class="icon">
<div class="img">
</div>
<div class="text">
Action 3
</div>
</div>
<div class="icon">
<div class="img">
</div>
<div class="text">
Action 4
</div>
</div>
<div class="icon">
<div class="img">
</div>
<div class="text">
Action 5
</div>
</div>
</div>
As you can see, the icon takes the full height of the container : in fact, I don't want to specify a height because I don't know the text length and really want that, if the content is huge, the icon takes the height of its content ( don't want to cut the text). Moreover, if the page is resized, I really want the icon to be aligned (like on smartphone).
Also, I don't understand why the icon takes the height of its parent and not its content because I didn't specify "flex:1" on it. I assume that the default behaviour it's to fit the content size, but this seems not to be working.
image of the issue
.icon's are flex-column which makes .img's stretch by default unless .icon's have align-items. The reason why I didn't apply align-items to .icon's is because other nested flex-containers/flex-items started collapsing. Instead of adjusting down through the hierarchy, I went up and adjusted .container instead.
The relevant CSS:
.container {
display: flex;
flex: 1; /* If you remove this .container will shrink to wrap around .icon's */
flex-wrap: wrap;
justify-content: center; /* This centers .icon's along a horizontal axis. */
align-items: baseline; /* This aligns .icon's along a common baseline vertically. */
outline: 3px dashed blue; /* To show the size of .container */
}
.icon {
width: 10vh;
margin: 10px;
display: flex;
flex-direction: column;
outline: 1px dashed red; /* To show the size of .icon */
}
body,
html {
width: 100%;
height: 100%;
display: flex;
}
.container {
display: flex;
flex: 1;
flex-wrap: wrap;
justify-content: space-between;
align-items: baseline;
align-content: flex-start;
outline: 3px dashed blue;
}
.icon {
width: 10vh;
margin: 10px;
display: flex;
flex-direction: column;
outline: 1px dashed red;
}
.img {
width: 10vh;
height: 10vh;
display: flex;
align-items: center;
justify-content: center;
background-color: red;
}
.text {
text-align: center;
}
<div class="container">
<div class="icon">
<div class="img">
</div>
<div class="text">
Action 1
</div>
</div>
<div class="icon">
<div class="img">
</div>
<div class="text">
Action 2
</div>
</div>
<div class="icon">
<div class="img">
</div>
<div class="text">
Action 3
</div>
</div>
<div class="icon">
<div class="img">
</div>
<div class="text">
Action 4
</div>
</div>
<div class="icon">
<div class="img">
</div>
<div class="text">
Action 5
</div>
</div>
</div>

Resources