Issue
I have an image where the height should be constrained so the container height is a maximum of 400px. The image should maintain its natural aspect ratio.
Critically, I cannot use object-fit
because I want to provide the image a border-radius
.
I am looking for a no-JS solution that works in all modern browsers. I have found a quite simple solution using CSS grid, but it only works in Firefox.
// Solution should not use Javascript.
// Below is simply to rotate images for testing.
const heights = [100, 200, 300, 400, 1000, 2000]
const widths = [200, 350, 1200]
let wIndex = 0, hIndex = 0;
setInterval(() => {
hIndex = (hIndex + 1) % heights.length;
wIndex = (wIndex + 1) % widths.length;
const h = heights[hIndex];
const w = widths[wIndex];
document.querySelector("img").src = `https://placehold.co/${w}x${h}`;
}, 1_000)
.container {
display: flex;
flex-direction: column;
width: 400px;
max-height: 400px; /* I want to constrain entire container to 400px tall */
border: 3px solid rebeccapurple;
}
img {
/* Because I want to round corners of image, cannot use object-fit */
border-radius: 16px;
}
/* ------ FIREFOX SOLUTION BELOW -------
*
* The below only works in Firefox
*/
.img-container {
display: grid;
min-height: 0;
}
img {
margin: auto;
height: 100%;
max-width: 100%;
}
<p>Rebeccapurple container has max height of 400px.</p>
<div class="container">
<div class="img-container">
<img>
</div>
<p>This text is some more content of arbitrary height and should not be pushed out of container</p>
</div>
Please see the below demonstration of the result that I am looking for (in firefox):
Solution
At its most basic, this doesn't need much CSS.
A grid
layout on the parent with a row template that accommodates for the text's max-content
and leaves the img occupy the rest of the space (1fr
). And you set the max-height
on it.
Then the img
should get a min-height
of 0
and a max-height
that's 100%
of the grid cell it occupies.
That's it. 5 CSS declarations. Anything else is just fluff adjacent to the demo:
.container {
display: grid;
grid-template-rows: 1fr max-content;
max-height: 25em
}
img { min-height: 0; max-height: 100% }
And you've also said you want to set a border-radius
on it, though I cannot understand for the life of me what object-fit
might have to do do with it - how it could mess with border-radius
or how it might help with this situation when you don't know the image's aspect ratio since you need to use its intrinsic one to begin with.
You may also want to prevent the image from overflowing horizontally when the viewport and consequently container get too narrow, so that's setting max-width: 100%
on it. You may want it to be middle aligned horizontally, which means you should set justify-self: center
on it.
In case you want a bit of space around the img
within its grid, you can set box-sizing: border-box
on it and give it a padding
You can also have a padding
around the text. But all of this is just fluff. All that's really needed for this layout are those first 5 declarations.
.container {
display: grid; /* essential style */
overflow: hidden; /* prevent text overflow after img shrunk to nothing */
grid-template-rows: 1fr max-content; /* essential style */
margin: .5em 0; /* space separate examples */
max-height: 25em; /* essential style */
background: dimgrey /* just to show container area */
}
img {
box-sizing: border-box; /* make dimensions refer to border-box */
justify-self: center; /* middle-align horizontally */
padding: .5em; /* space around img in its grid cell */
max-width: 100%; /* prevent horizontal overflow */
min-height: 0; max-height: 100%; /* essential style */
border-radius: 1em /* round corners */
}
p {
margin: 0; /* replace margin */
padding: .5em; /* with padding */
background: hotpink /* highlight boundary */
}
<section class="container">
<img src="https://images.unsplash.com/photo-1700159915592-004562ddcf6f?w=500"/>
<p contentEditable="true">I'm editable, write some more stuff here! Sesame snaps marzipan sweet donut marshmallow sweet roll lollipop apple pie. Macaroon carrot cake jelly pie marzipan lemon drops candy canes. Macaroon macaroon gingerbread apple pie donut toffee caramels pudding croissant. Tootsie roll donut marzipan croissant cookie biscuit.</p>
</section>
<section class="container">
<img src="https://images.unsplash.com/photo-1687960507238-5f6565a08b2f?w=300"/>
<p contentEditable="true">I'm editable, write some more stuff here! Sesame snaps marzipan sweet donut marshmallow sweet roll lollipop apple pie. Macaroon carrot cake jelly pie marzipan lemon drops candy canes. Macaroon macaroon gingerbread apple pie donut toffee caramels pudding croissant. Tootsie roll donut marzipan croissant cookie biscuit.</p>
</section>
<section class="container">
<img src="https://images.unsplash.com/photo-1610177498573-78deaa4a797b?w=400"/>
<p contentEditable="true">I'm editable, write some more stuff here! Sesame snaps marzipan sweet donut marshmallow sweet roll lollipop apple pie. Macaroon carrot cake jelly pie marzipan lemon drops candy canes. Macaroon macaroon gingerbread apple pie donut toffee caramels pudding croissant. Tootsie roll donut marzipan croissant cookie biscuit.</p>
</section>
Answered By - Ana
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.