You can consider radial-gradient
and multiple backgrounds.
I have used CSS variables to be able to easily control the shape (the image, the radius, the border length, etc.):
.avatar {
--r: 50px; /* The inner radius */
--d: 10px; /* The length of borders */
width: calc(2*(var(--r) + 4*var(--d) + 1px));
height: calc(2*(var(--r) + 4*var(--d) + 1px));
background:
radial-gradient(
transparent var(--r),
#eee calc(var(--r) + 0*var(--d) + 1px), #eee calc(var(--r) + 1*var(--d)),
#ffffd calc(var(--r) + 1*var(--d) + 1px), #ffffd calc(var(--r) + 2*var(--d)),
#ccc calc(var(--r) + 2*var(--d) + 1px), #ccc calc(var(--r) + 3*var(--d)),
#bbb calc(var(--r) + 3*var(--d) + 1px), #bbb calc(var(--r) + 4*var(--d)),
transparent calc(var(--r) + 4*var(--d) + 1px)),
var(--im) center/cover content-box; /* content-box for the image to avoid edge issues */
border-radius: 50%;
padding: 2px; /* This padding is used with the content-box for the edge issue*/
box-sizing: border-box;
display: inline-block;
}
body {
background: pink;
}
<div class="avatar" style="--im:url(https://picsum.photos/id/1074/800/800)"></div>
<div class="avatar" style="--im:url(https://picsum.photos/id/1069/800/800);--r:20px;"></div>
<div class="avatar" style="--im:url(https://picsum.photos/id/237/800/800);--r:60px;--d:18px;"></div>
You can also adjust the size of the image to cover only the transparent part:
.avatar {
--r: 50px; /* The inner radius */
--d: 10px; /* The length of borders */
width: calc(2*(var(--r) + 4*var(--d) + 1px));
height: calc(2*(var(--r) + 4*var(--d) + 1px));
background:
radial-gradient(
transparent var(--r),
#eee calc(var(--r) + 0*var(--d) + 1px), #eee calc(var(--r) + 1*var(--d)),
#ffffd calc(var(--r) + 1*var(--d) + 1px), #ffffd calc(var(--r) + 2*var(--d)),
#ccc calc(var(--r) + 2*var(--d) + 1px), #ccc calc(var(--r) + 3*var(--d)),
#bbb calc(var(--r) + 3*var(--d) + 1px), #bbb calc(var(--r) + 4*var(--d)),
transparent calc(var(--r) + 4*var(--d) + 1px)),
var(--im) center/calc(2*var(--r) + 2px) calc(2*var(--r) + 2px) no-repeat;
border-radius: 50%;
display: inline-block;
}
body {
background: pink;
}
<div class="avatar" style="--im:url(https://picsum.photos/id/1074/800/800)"></div>
<div class="avatar" style="--im:url(https://picsum.photos/id/1069/800/800);--r:20px;"></div>
<div class="avatar" style="--im:url(https://picsum.photos/id/237/800/800);--r:60px;--d:18px;"></div>
In case you will always have the same color that will fade, here is an idea using hsl()
coloration where it will be easy to adjust the color without manually changing each one:
.avatar {
--r: 50px; /* The inner radius */
--d: 10px; /* The length of borders */
--c: 230,80%; /* The base color*/
width: calc(2*(var(--r) + 4*var(--d) + 1px));
height: calc(2*(var(--r) + 4*var(--d) + 1px));
background:
radial-gradient(
transparent var(--r),
hsl(var(--c), 20%) calc(var(--r) + 0*var(--d) + 1px), hsl(var(--c), 20%) calc(var(--r) + 1*var(--d)),
hsl(var(--c), 40%) calc(var(--r) + 1*var(--d) + 1px), hsl(var(--c), 40%) calc(var(--r) + 2*var(--d)),
hsl(var(--c), 60%) calc(var(--r) + 2*var(--d) + 1px), hsl(var(--c), 60%) calc(var(--r) + 3*var(--d)),
hsl(var(--c), 80%) calc(var(--r) + 3*var(--d) + 1px), hsl(var(--c), 80%) calc(var(--r) + 4*var(--d)),
transparent calc(var(--r) + 4*var(--d) + 1px)),
var(--im) center/calc(2*var(--r) + 2px) calc(2*var(--r) + 2px) no-repeat;
border-radius: 50%;
display: inline-block;
}
body {
background: pink;
}
<div class="avatar" style="--im:url(https://picsum.photos/id/1074/800/800)"></div>
<div class="avatar" style="--im:url(https://picsum.photos/id/1069/800/800);--r:20px;--c: 20,50%;"></div>
<div class="avatar" style="--im:url(https://picsum.photos/id/237/800/800);--r:60px;--d:18px;--c: 130,80%;"></div>
I am using +1px
/+2px
to avoid bad effect due to aliasing