Reputation: 210455
Here's what I'm trying to accomplish in pure CSS:
I'm given an arbitrary div
. I know nothing about its layout except that its height can be sufficiently large to contain the content I will put in it.
In particular, to be absolutely explicit, this means I don't know its positioning, padding, margins, width, etc. and hence nothing in the solution should depend on their particular values.
I'm given an image file with arbitrary dimensions to place inside the div
(directly or indirectly).
CSS should scale down the image to ensure its width does not exceed that of its parent.
CSS should then crop the image to a circle.
In the end, then, I should see a circular image fit into the div without any aspect distortion, neither of whose dimensions exceed that of the original.
Here's what this would look like in my ideal world:
<!DOCTYPE html>
<head>
<style type="text/css">
img {
max-width: 100%;
max-height: width; /* I wish this was a thing... */
border-radius: 50%;
object-fit: cover;
}
</style>
</head>
<body>
Arbitrary content...
<div style="width: 25%; margin-left: 10px; top: 1em;"> <!-- arbitrary -->
<img src="https://i.sstatic.net/8mNMb.png"/>
</div>
Arbitrary content...
</body>
</html>
Now obviously that doesn't work, because you can't do height: width
.
But what can I do instead?
I've tried every trick in the book I could find, but they all end up failing spectacularly in some way or the other. Here's an example with the height: 0; padding-bottom: 100%;
trick:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<style type="text/css">
.square {
height: 0px;
padding-bottom: 100%;
}
.circle {
position: absolute;
max-width: 100%;
height: 100%; /* not really sure what to put here */
border-radius: 0%;
object-fit: cover;
}
</style>
</head>
<body>
Arbitrary content...
<div style="width: 25%; margin-left: 50px; top: 1em;">
<div class="square">
<img class="circle" src="https://i.sstatic.net/8mNMb.png"/>
</div>
</div>
Arbitrary content...
</body>
</html>
How do I achieve this?
Upvotes: 0
Views: 579
Reputation: 6368
Your second snippet was close. You need position:relative;
on the square container so you can set the circle's height and with to 100% of that square container. Using object-fit: scale-down;
on the img tag seems to do it.
.circle {
height: 0px;
padding-bottom: 100%;
position: relative;
border-radius: 50%;
overflow: hidden;
}
.circle img {
position: absolute;
width: 100%;
height: 100%;
object-fit: scale-down;
}
Arbitrary content...
<div style="width: 25%; margin-left: 50px; top: 1em;">
<div class="circle">
<img src="https://i.sstatic.net/8mNMb.png" />
</div>
</div>
Arbitrary content...
<div style="width: 250px;">
<div class="circle">
<img src="https://picsum.photos/68/50" />
</div>
</div>
Arbitrary content...
<div style="width: 250px;">
<div class="circle">
<img src="https://picsum.photos/200/300" />
</div>
</div>
Arbitrary content...
<div style="width: 250px;">
<div class="circle">
<img src="https://picsum.photos/300/200" />
</div>
</div>
Arbitrary content...
<div style="width: 250px;">
<div class="circle">
<img src="https://picsum.photos/400/400" />
</div>
</div>
Upvotes: 1
Reputation: 56754
You can capitalize on the fact that percentage-based paddings always refer to the width
of the parent element, even if applied to padding-top
and/or padding-bottom
. So you could work with a height: 0;
and padding: 50% 0;
to get a square div
at all times.
Examples:
div div {
background: #ccc;
border-radius: 50%;
height: 0;
padding: 50% 0;
}
.a {
width: 20px;
}
.b {
width: 80px;
}
<div class="a">
<div></div>
</div>
<div class="b">
<div></div>
</div>
Now you can simply apply the background-image
of your choice to div div
.
Upvotes: 0