1👍
✅
You can use the ::after element to provide the circle, just use CSS variables to provide a constant image.
function applyZoom() {
const zoomValue = document.getElementById('sizeinput').value;
const zoom = '--zoom:' + zoomValue + ";"
document.getElementById('myavatar').setAttribute('style', zoom);
}
.mydiv {
--image: url('https://picsum.photos/id/46/300/300');
--size: 400px;
display:grid;
place-items:center;
width:400px;
border-radius: 2rem;
background-image: linear-gradient(rgba(56, 76, 111, 0.5), rgba(56, 76, 111, 0.5)), var(--image);
}
.mydiv, .mydiv::after {
aspect-ratio:1;
background-position: center center;
background-repeat: no-repeat;
background-size: calc(var(--zoom) * var(--size)) calc(var(--zoom) * var(--size));
}
.mydiv::after {
display:block;
content:"";
width:200px;
border:2px solid white;
border-radius:100vh;
background-image: var(--image);
}
<div class='mydiv' id='myavatar' style='--zoom: 1;'>
</div>
<br>
<input id='sizeinput'><button onclick='applyZoom()'>Zoom</button>
Edited to add
In the comment, there’s a need to zoom the image. Just using the ::after pseudo elemnt, the overlay shading sizes with the image. This isn’t a problem for zooms greater than 1 but if it’s less than 1, it breaks. This can be solved by using the ‘before’ element and z-index as follows:
function applyZoom() {
const circleWidth = 200;
const zoomValue = document.getElementById('sizeinput').value;
document.getElementById('zoomText').textContent = zoomValue;
const zoom = '--zoom:' + zoomValue + ";"
const element = document.getElementById('myavatar');
const containerSize = parseInt(window.getComputedStyle(element).getPropertyValue("--size"));
const resizedImageSize = containerSize * zoomValue;
if(resizedImageSize >= circleWidth) {
element.setAttribute('style', zoom);
}
}
.mydiv {
--image: url('https://picsum.photos/id/46/300/300');
--size: 400px;
position:relative;
overflow: hidden;
display:grid;
place-items:center;
width:400px;
border-radius: 2rem;
background-image: var(--image);
}
.mydiv, .mydiv::after {
aspect-ratio:1;
background-position: center center;
background-repeat: no-repeat;
background-size: calc(var(--zoom) * var(--size)) calc(var(--zoom) * var(--size));
}
.mydiv::before {
display:block;
position: absolute;
content:"";
inset: 0;
width:100%;
background-color: rgba(56, 76, 111, 0.8);
}
.mydiv::after {
display:block;
content:"";
width:200px;
border:2px solid white;
border-radius:100vh;
background-image: var(--image);
z-index: 1;
}
<div class='mydiv' id='myavatar' style='--zoom: 1;'>
</div>
<br>
<input type="range" min="0" max="2" value="1" step="0.1" id="sizeinput" oninput='applyZoom()'>
Zoom: <span id='zoomText'></span>
👤Adam
1👍
This snippet makes use of the mask-box-image
property
.masking{
width: 300px;
height: 300px;
-webkit-mask-box-image: radial-gradient(circle at 50% 50%, gray 60%, rgba(140, 140, 140, 0.3) 60%);
}
<img src="https://music.columbia.edu/sites/default/files/styles/page_image_square/public/images/stylianos_dimou_profile-alt.jpg?itok=mOF8wxnL" class="masking">
1👍
What about making it two distinct elements?
* {
box-sizing: border-box;
}
.background, .foreground {
background: url("https://picsum.photos/500") 50% 50%/500px 500px;
}
.background {
width: 500px;
height: 500px;
position: relative;
padding: 50px;
}
.background::after {
content: "";
background: rgba(0, 0, 0, 0.5);
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.foreground {
position: relative;
height: 100%;
z-index: 1;
border-radius: 100%;
border: 2px solid #fff;
}
<div class="background">
<div class="foreground"></div>
</div>
Source:stackexchange.com