Example:
https://jsfiddle.net/killymxi/gjb10oqa/26/
<html>
<body>
<div class="container-1">
1 - cover
</div>
<div class="container-2">
2 - scale-down
</div>
<div class="container-1">
<img src="http://placekitten.com/80/120"/>
</div>
<div class="container-2">
<img src="http://placekitten.com/80/120"/>
</div>
<div class="container-1">
<img src="http://placekitten.com/320/480"/>
</div>
<div class="container-2">
<img src="http://placekitten.com/320/480"/>
</div>
</body>
</html>
body {
display: grid;
grid-template-columns: 200px 200px;
grid-template-rows: auto 200px 200px;
gap: 2px;
}
.container-1 {
background-color: #dfd;
display: flex;
}
.container-2 {
background-color: #ddf;
display: flex;
}
.container-1 > img {
object-fit: cover;
flex: 1 1;
}
.container-2 > img {
object-fit: scale-down;
flex: 1 1;
}
object-fit: cover
(left column) causes ugly stretching of small images. Keeping them small works best for my purposes;object-fit: scale-down
(right column), by definition, produces image at most equal to object-fit: contain
, leaving empty areas even when image is big enough to cover the container.Is there a way to achieve combined behavior? (Top right and bottom left images.)
Paraphrasing the definition of scale-down
, I want to achieve the following:
The content is sized as if
none
orcover
were specified, whichever would result in a smaller concrete object size.
Note: I can't change the HTML layout (but I might be able to use two layers of containers - image inside tag inside tag) and image URLs are not static.
Update:
If CSS-only solution exists, I suspect it should involve recreating the cover
fit in some way.
For now, I only see a partial solution, when image is known to always have aspect ratio on the same side relative to container (always taller or always wider).
Full solution seems to require a condition on content aspect ratio, which doesn't seem to be achievable today.
There is fit-content
, but it can't participate in calc()
, max()
, etc., and no other ways to access natural size of images as in JS.
Best CSS-only attempt so far: https://jsfiddle.net/killymxi/gjb10oqa/30/
You could consider using JavaScript to inspect the size of the images and then apply object-fit: cover
if they are large enough:
function setSize(img) {
img.style.objectFit = (img.naturalHeight > 200 && img.naturalWidth > 200)
? 'cover'
: 'none';
}
document.querySelectorAll('img').forEach(img => {
if (img.complete) {
setSize(img);
} else {
img.addEventListener('load', () => setSize(img));
}
});
body {
display: grid;
grid-template-columns: 200px 200px;
grid-template-rows: auto 200px 200px;
gap: 2px;
}
.container-1 {
background-color: #dfd;
display: flex;
}
.container-2 {
background-color: #ddf;
display: flex;
}
:is(.container-1, .container-2) > img {
flex: 1 1;
}
<html>
<body>
<div class="container-1">
1 - cover
</div>
<div class="container-2">
2 - scale-down
</div>
<div class="container-1">
<img src="http://placekitten.com/80/120"/>
</div>
<div class="container-2">
<img src="http://placekitten.com/80/120"/>
</div>
<div class="container-1">
<img src="http://placekitten.com/320/480"/>
</div>
<div class="container-2">
<img src="http://placekitten.com/320/480"/>
</div>
</body>
</html>