35

I want to give circular opacity to an image using CSS.

I know I can achieve opacity on images like this:

.circle img {
    opacity: 0.4;
    filter: alpha(opacity=40);
}

I know I can achieve circular images like this:

.circle {
    border-radius: 50%;
    display: inline-block;
}
.circle img {
    border-radius: 50%;
    display: block;
}

I want somehow to merge the two things above and apply the opacity only for the edges of the image, so the center of the image gets almost nothing from the opacity tag. I have searched for hours but found nothing.

Without opacity: http://jsfiddle.net/8w6szf84/47

With opacity: http://jsfiddle.net/8w6szf84/48/ -> bad opacity, want only the edges to fade...

Do I need to use Javascript on this? Any suggestions?

balintpekker
  • 1,804
  • 4
  • 28
  • 42

6 Answers6

43

Ok, so what we can do is create a :after element that will be equal to the size of the parent. Using this we can set a background gradient that will make it appear as the image is fading into the solid colour background.

Note: In this example I have made the gradient element a little bigger and moved it over 1px to stop a border from appearing around it. From here you can mess around to get the perfect effect that you want.

.circle {
    border-radius: 50%;
    display: inline-block;
    position: relative;
}
.circle img {
    border-radius: 50%;
    display: block;
    border:1px solid #fff;
}
.circle:after {
    content: "";
    display: block;
    width: 100%;
    height: 100%;
    background: radial-gradient(ellipse at center, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 70%,rgba(255,255,255,1) 100%);
    border-radius: 50%;
    position: absolute;
    top: 0; left: 0;
}
<div class="circle">
    <img src="http://placekitten.com/200/200?image=2" />
</div>

Edit: Here is another version without setting a height or width and getting rid of the border that gets caused if using 100% of parent. As Vucko pointed out we don't need the negative values for the position but can use a border around the img instead.

JsFiddle Here

Gugalcrom123
  • 101
  • 1
  • 9
Ruddy
  • 9,795
  • 5
  • 45
  • 66
  • I don't know this is what OP required or not, but I like this :) – Bharadwaj Dec 24 '14 at 09:01
  • 1
    Nice one - but I'd change it a little, just to remove the negative values, so check the [fiddle](http://jsfiddle.net/on79umkw/). – Vucko Dec 24 '14 at 09:11
  • @Vucko Ah excellent! Using the border instead, not sure why I didn't think to do that. Have updated the answer to include this. – Ruddy Dec 24 '14 at 09:15
  • @Ruddy yes, `border` removes the "glitch". But also, you don't have to have a fixed `width/height` on the pseudo element (202px) - just use `100%`. – Vucko Dec 24 '14 at 09:20
  • @Vucko Yeah sorry, I was more concentrating on the edit I did as that answer is better (no width or height needed). I just forgot to change the width and height. Thanks for your help, nice work! – Ruddy Dec 24 '14 at 09:22
  • Is there any way to handle relative `width`/`height` arguments in the `` tag? i.e. go to the [JsFiddle](http://jsfiddle.net/8w6szf84/49/) and add `` to the html. – James Owers Apr 17 '17 at 16:59
  • This doesn't answer the question – mrg95 Sep 23 '19 at 23:02
  • @mrg95 Hows that? This answer was accepted. I feel like the OP would know what does and doesn't answer the question. – Ruddy Sep 25 '19 at 14:31
  • @Ruddy This answer solved their problem, but didn't answer the question. This answer doesn't add fading opacity to the image, it only created the illusion of such an effect by creating a background gradient of the same color as a solid background. This technique wont work for a gradient background, or another image background, for example. This is because this DOESNT add any gradient to the image itself. It doesn't answer the question. The correct method would be to use css mask. https://stackoverflow.com/questions/58071243/radial-gradient-opacity-on-background-image/58071275 – mrg95 Sep 26 '19 at 10:23
7

you can also use a box-shadow

.shadow {
  border-radius: 50%;
  display: inline-block;
  position: relative;
}
.shadow img {
  border-radius: 50%;
  display: block;
  border: 1px solid #fff;
}
.shadow:after {
  content: "";
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  position: absolute;
  top: 0;
  left: 0;
  box-shadow: inset 10px 24px 40px 0px white, 
    inset -10px -24px 40px 0px white, 
    inset 20px -10px 40px 0px white, 
    inset -20px 10px 40px 0px white;
}
<div class="shadow">
  <img src="http://placeimg.com/200/200/any" />
</div>
Vitorino fernandes
  • 15,794
  • 3
  • 20
  • 39
6

You could use two (of the same) images and have the top one smaller and transparent.

.circle-opaque {
    border-radius: 50%;          /* Make it a circle */
    display: inline-block;       
    position: absolute;          /* Able to position it, overlaying the other image */
    left:0px;                    /* Customise the position, but make sure it */
    top:0px;                     /* is the same as .circle-transparent */
    z-index: -1;                 /* Makes the image sit *behind* .circle-transparent */
}
.circle-opaque img {
    border-radius: 50%;          /* Make it a circle */
    z-index: -1;
}
.circle-transparent {
    border-radius: 50%;          /* Make it a circle */
    display: inline-block;       
    position: absolute;          /* Able to position it, overlaying the other image */
    left: 0px;                   /* Customise the position, but make sure it */
    top: 0px;                    /* is the same as .circle-transparent */
    z-index: 1;                  /* Makes the image sit *on top of* .circle-transparent */
}
.circle-transparent img {
    width: 200px;
    opacity: 0.4;                /* Make the second image transparent */
    filter: alpha(opacity=40);   /* For IE8 and earlier; optional */
    z-index: 1;                  /* And on top of the first */
}
<div class="circle-opaque">
    <img src="http://www.catchannel.com/images/articles/0805/orange-kitten-200px.jpg" />
</div>
<div class="circle-transparent">
    <img src="http://www.catchannel.com/images/articles/0805/orange-kitten-200px.jpg" />
</div>

http://jsfiddle.net/joe_young/20y832r7/

joe_young
  • 4,107
  • 2
  • 27
  • 38
3

Although this approach isn't as clean as others (possibly due to lack of time), I believe it could be cleaned up. However, it's using just box shadows to achieve the look you're thinking of. (Radial gradients would possibly be preferred, although if you need a fallback, this could be an option)

div {
  height: 300px;
  width: 300px;
  background: url(http://placekitten.com/g/300/400);
  border-radius: 50%;
  box-shadow: 
    inset -5px -5px 100px white, 
    inset 0 0 90px white, 
    inset 0 0 80px white, 
    inset 0 0 70px white, 
    inset 0 0 60px white, 
    inset 0 0 50px white, 
    inset 0 0 40px white, 
    inset 0 0 30px white, 
    inset 0 0 20px white, 
    inset 0 0 10px red; 
}
<div></div>
jbutler483
  • 24,074
  • 9
  • 92
  • 145
  • Well it's kinda same like Vitorino's answer but this is nice too. – balintpekker Jan 09 '15 at 10:21
  • 1
    I can actually say I didn't see theirs. Although, upon looking I can see that theirs involves a few too many elements for my liking. I try to keep markup to a minimum IMHO :P – jbutler483 Jan 09 '15 at 10:25
2

Here is a modified version of Ruddy's answer except that the diameter of gradient matches the width (or height) of the image instead of diagonal. Border radius is not required. 80% of the image displays as-is, the remaining 20% fades from transparent to white.

.circle {
  display: inline-block;
  position: relative;
}
.circle img {
  display: block;
}
.circle:after {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background-image: radial-gradient(circle closest-side at center,
    rgba(255, 255, 255, 0) 0,
    rgba(255, 255, 255, 0) 80%, 
    rgba(255, 255, 255, 1) 100%
  );
}
<div class="circle">
  <img src="http://www.catchannel.com/images/articles/0805/orange-kitten-200px.jpg">
</div>

Note that radial gradients are drawn from the specified center; while box shadows are drawn from the edges; therefore both produce different results.

Community
  • 1
  • 1
Salman A
  • 262,204
  • 82
  • 430
  • 521
0

I like simple, so the following might suffice:

.circle {
  background-image: radial-gradient(ellipse at center center, rgba(0, 0, 0, 0) 0%, rgba(255, 255, 255, 1) 70%, rgba(255, 255, 255, 1) 100%);
  display: inline-block;
}
.circle img {
  border-radius: 50%;
  mix-blend-mode: lighten;
}
<div class="circle">
  <img src="http://www.catchannel.com/images/articles/0805/orange-kitten-200px.jpg" />
</div>
Robert McKee
  • 21,305
  • 1
  • 43
  • 57