Image exceeds flex parent size [duplicate] - html

This question already has answers here:
flex child is growing out of parent
(3 answers)
Closed 4 years ago.
I am having an issue with making <img> flexible inside a flex parent. Image start exceeding parent dimensions. I would like to leave parent with display: flex; and restrict image from crossing parent's dimensions.
.full
{
width: 400px;
height: 200px;
background-color: blue;
display: flex;
flex-direction: row;
justify-content: flex-start;
}
.half
{
width: 50%;
background-color: red;
padding: 20px;
}
img
{
width: auto;
height: auto;
max-width: 100%;
max-height: 100%;
}
<div class="full">
<div class="half">
<h1>title</h1>
<img src="http://placehold.it/90x200">
</div>
</div>
Can you please explain and give some useful links that would explain the shown behavior and possible solution of it?
I am using both Firefox and Chrome to view that. Issue persist in both browsers.
It seems that question is duplicate of this question

In order for it to work .half div also needs to be a flexbox container and the image needs to have min-height: 0, as explained here.
.full
{
width: 400px;
height: 200px;
background-color: blue;
display: flex;
flex-direction: row;
justify-content: flex-start;
}
.half
{
width: 50%;
background-color: red;
padding: 20px;
display: flex;
flex-flow: column nowrap;
justify-content: flex-start;
}
img
{
min-height: 0;
max-width: 100%;
max-height: 100%;
}
<div class="full">
<div class="half">
<h1>title</h1>
<img src="http://placehold.it/90x200">
</div>
</div>

Related

Make a flexbox container with wrapped items scrollable

I have a grid of images that are spaced into columns dynamically using flex-wrap: wrap. However there is one problem, I don't know how to make the container scrollable because it has a dynamic height. I have searched for solutions to this problem but I don't really know how to adapt them for my use case.
This is my code:
.imagegrid {
display: flex;
width: 100%;
height: 100%;
background-color: var(--background);
}
.image-container {
display: flex;
flex-direction: row;
width: 100%;
height: 100%;
flex-wrap: wrap;
justify-content: space-between;
padding-left: 30px;
padding-right: 30px;
}
.image {
width: auto;
max-height: 270px;
margin-bottom: 10px;
cursor: pointer;
}
I want to make either the image-container or imagegrid scrollable on the y-axis.
This is the HTML, if needed:
<div class="imagegrid">
<div class="image-container">
<img class="image" src="image"/>
<img class="image" src="image2"/>
(multiple images)
</div>
</div>
The images are added dynamically from a database. I do not know what the height of the container will be.
In order for elements to scroll vertically you must do 2 things
Give them an explicit height that makes them have to scroll
Give them an overflow setting of auto or scroll
I've added a working example with both applied:
.imagegrid {
display: flex;
width: 100%;
height: 200px;
overflow: auto;
background-color: var(--background);
}
.image-container {
display: flex;
flex-direction: row;
width: 100%;
height: 100%;
flex-wrap: wrap;
justify-content: space-between;
padding-left: 30px;
padding-right: 30px;
}
.image {
width: auto;
max-height: 270px;
margin-bottom: 10px;
cursor: pointer;
}
<div class="imagegrid">
<div class="image-container">
<img class="image" src="https://source.unsplash.com/random/200x200" />
<img class="image" src="https://source.unsplash.com/random/250x250" /> (multiple images)
</div>
</div>

wrap a flexbox to allow maximum child scaling, while preserving aspect ratios

I'd like to display images in a row, using a flexbox container. In order to play nicely with the other elements onscreen, the container must have a height of exactly 30vh.
The images inside should be scaled as large as possible, while keeping their aspect ratio and not overflowing the row.
The problem is wrapping. On a very wide screen, the images should all be in one row.
But on a tall screen, the row should wrap automatically. This is something I can't manage to do. Either the elements in the flexbox shrink to fit, or they wrap around. But I can't get the to wrap and scale at the same time.
Is it possible to do this with flexbox?
Here's my approach so far. I'm using scss:
.App {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
background-color: yellow;
}
.row {
display: flex;
flex-direction: row;
justify-content: center;
flex-wrap: wrap;
background-color: blue;
height: 30vh;
}
.item {
// make items grow
flex-basis: 0;
flex: 1;
// only as large as necessary
width: max-content;
height: max-content;
// align image and text
display: flex;
flex-direction: column;
align-items: center;
// just a visual helper
background-color: red;
border-style: solid;
}
img {
// make image shrink to fit
min-width: 0;
min-height: 0;
// contain in parent
max-height: 100%;
max-width: 100%;
// keep aspect ratio
width: auto;
height: auto;
}
A minimal fiddle: https://jsfiddle.net/89jekw4p/8/
Here's a screenshot that illustrates the problem. These images could be much larger, if the row would wrap around:
I might have an idea what is the solution to your problem. First of all, I removed
// make image shrink to fit min-width: 0; , min-height: 0; // contain in parent max-height: 100%; max-width: 100%; // keep aspect ratio width: auto; height: auto;. Because when you have written repeatedly browser only sees what's written on the end of the line so the browser only seeing the width: auto; height: auto; so that is why images keep getting smaller and flex-wrap: wrap does not work. But right now it will work. I hope I could explain it.
<div class="App">
<div class="row">
<div class="item">
<img src="https://www.fillmurray.com/200/300"></img>
</div>
<div class="item">
<img src="https://www.fillmurray.com/200/300"></img>
</div>
<div class="item">
<img src="https://www.fillmurray.com/200/300"></img>
</div>
<div class="item">
<img src="https://www.fillmurray.com/200/300"></img>
</div>
<div class="item">
<img src="https://www.fillmurray.com/200/300"></img>
</div>
</div>
</div>
.App {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: yellow;
}
.row {
display: flex;
flex-direction: row;
justify-content: center;
flex-wrap: wrap;
flex: 0 0 100%;
background-color: blue;
height: 30vh;
}
.item {
height: 30vh;
width: auto;
}
img {
max-width: 100%;
height: 30vh;
}

Why are the children of a flexbox scaling down even though I've set a width for them? [duplicate]

This question already has an answer here:
Why is a flex item limited to parent size?
(1 answer)
Closed 2 years ago.
As you can see in the snippet below, I have 3 children to the flexbox with a set width of 200px, 150px and 300px. However, when I resize the browser and the elements run out of space, they start scaling down even though they have hard coded width and I'm not sure why is this happening.
.row {
display: flex;
justify-content: space-between;
width: 100%;
height: 50px;
}
.column1 {
width: 200px;
background-color: red;
}
.column2 {
width: 150px;
background-color: blue;
}
.column3 {
width: 300px;
background-color: green;
}
<div class="row">
<div class="column1"></div>
<div class="column2"></div>
<div class="column3"></div>
</div>
Your items are shrinking because flexbox tries to fit all children into its width. You can change this behaviour by specifying flex-shrink: 0 on your column divs which tells flexbox that your items should not shrink beyond their defined width. You can also read more about flex-shrink at https://css-tricks.com/almanac/properties/f/flex-shrink/.
.row {
display: flex;
justify-content: space-between;
width: 100%;
height: 50px;
}
.row > div {
flex-shrink: 0;
}
.column1 {
width: 200px;
background-color: red;
}
.column2 {
width: 150px;
background-color: blue;
}
.column3 {
width: 300px;
background-color: green;
}
<div class="row">
<div class="column1"></div>
<div class="column2"></div>
<div class="column3"></div>
</div>

Center one flex item and bottom-align another [duplicate]

This question already has answers here:
Center and bottom-align flex items
(3 answers)
Closed 5 years ago.
I'm trying to get one flex item to be centered vertically and horizontally.
I'd like for some text to be fixed to the bottom of the flex container.
margin-top:auto on the text just shoves the inner box to the top. Ideas?
.container {
background: lightblue;
width: 300px;
height: 300px;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
padding: 10px;
}
.container .box {
background: goldenrod;
height: 30px;
width: 30px;
}
<div class="container">
<div class="box"></div>
<span>Text</span>
</div>
Here's the codepen.
Try the below instead:
.box {
background:goldenrod;
height: 30px;
width: 30px;
margin: auto;
}
Here is one way of doing it.
Add position: relative to your .container CSS rule, and then use absolute positioning on .box to position the span to the bottom of the parent container.
You can center the text by allowing .box to have 100% width and then using text-align: center.
.container {
background: lightblue;
width: 300px;
height: 300px;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
padding: 10px;
position: relative;
}
.box {
background: goldenrod;
height: 30px;
width: 30px;
}
span {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
text-align: center;
}
<div class="container">
<div class="box"></div>
<span>Text</span>
</div>
Since flexbox alignment involves the distribution of free space in the container, margin-top: auto won't work in this case because there's no counterweight on the other side.
Therefore, one method for centering the box and bottom-aligning the text involves creating a duplicate of the text element and placing it on the opposite side of the box. This will create a counterweight.
With equal balance on both ends, flex alignment properties (including auto margins) can work.
In this case, even justify-content: space-between would work.
Of course, you'll need to apply visibility: hidden to the duplicate element.
.container {
background: lightblue;
width: 300px;
height: 300px;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
padding: 10px;
}
.box {
background: goldenrod;
height: 30px;
width: 30px;
margin: auto 0; /* or instead use justify-content: space-between on .container */
}
span:first-child {
visibility: hidden;
}
<div class="container">
<span>Text</span>
<div class="box"></div>
<span>Text</span>
</div>
OR, instead of a duplicate element, use a pseudo-element.
A less intrusive and more semantically proper method would use a pseudo-element as the duplicate. However, for this method to work, you would need to know the height of the actual element, because you would need to match it precisely.
Something like this will work to create equal balance:
.container::before {
content: "";
height: 15px; /* must match actual element's height */
}
.container {
background: lightblue;
width: 300px;
height: 300px;
display: flex;
justify-content: space-between;
flex-direction: column;
align-items: center;
padding: 10px;
}
.box {
background: goldenrod;
height: 30px;
width: 30px;
}
span {
height: 15px;
}
.container::before {
content: "";
height: 15px;
}
<div class="container">
<div class="box"></div>
<span>Text</span>
</div>

How to fit an image vertically in a flex container with direction: column

I'm trying to fit an image vertically in a flex container which has a specific height.
The flex-direction is column, and the image is contained in a flex-item with flex-basis: 100%.
In addition, the image's max-height is 100%.
As you can see in the example, the image does not fit into the red container.
#container {
background-color: red;
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 200px;
width: 320px;
justify-content: space-between;
}
#container > * {
padding: 5px;
}
#img {
flex: 0 1 100%;
/* height: 100%; */
}
img {
max-height: 100%;
max-width: 100%;
}
<div id="container">
<div id="img">
<img src="https://placeholdit.imgix.net/~text?txtsize=33&txt=img&w=340&h=500">
</div>
<div>
Something else
</div>
</div>
Shouldn't the image shrink to fit vertically into the flex container, according to the specification?
The workaround I found is to set the height of #img to 100%, but I have the sensation that it's not the way it should be done.
As an additional note, if I set flex-direction: row to the container, it fits the image horizontally (which is the behaviour I would expect).
You wrote:
The workaround I found is to set the height of #img to 100%, but I have the sensation that it's not the way it should be done.
Actually, it is the way it should be done. The predominant implementation of the spec requires that the height property be applied to the parent when using percentage heights on the child. (Although this is slowly evolving. See my second reference below.)
References:
Working with the CSS height property and percentage values
Heights rendering differently in Chrome and Firefox (includes alternative solutions)
CSS height property definition (W3C)
For some reason, I couldn't get the <img> to behave (probably because it's a replaced element). So I removed it, and used the .img div with an image as background.
Relevant Changes
.container {
...
justify-content: center;
align-items: center;
}
.img {
flex: 1 0 auto;
background: url(https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png) no-repeat;
background-size: contain;
background-position: center;
width: 100%;
}
SNIPPET
.container {
background-color: red;
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 200px;
width: 320px;
justify-content: center;
align-items: center;
}
.container > * {
padding: 5px;
}
.somethingElse {
outline: 1px dashed yellow;
background: rgba(128,0,255,.3);
color: white;
}
.img {
flex: 1 0 auto;
background: url(https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png) no-repeat;
background-size: contain;
background-position: center;
width: 100%;
}
<figure class="container">
<div class="img">
</div>
<figcaption class="somethingElse">
True Dimentions: 512 x 512 px
</figcaption>
</figure>
try this css. its works fine.
#container {
background-color: red;
/*display: flex;*/
flex-direction: column;
flex-wrap: wrap;
height: 200px;
width: 320px;
justify-content: space-between;
}
#img {
height: 85%;
width: 100%;
}