9

How can I achieve such a thing in CSS?

Target

I've tried so many ways but the dark background is still in the way and can't be clipped so the background image under it's invisible...

.item {
  position: relative;
}
    
.item:before {
  content: '';
  size(100%);
  top: 0;
  left: 0;
  z-index: 1;
  background: rgba(0, 0, 0,0 0.1);
}
<div class="item">
   <img>
   <span class="rate">
     <span class="amount">10</span> امتیاز
   </span>
</div>  

I'm looking for a way to be able to make parts of the dark background transparent, so the image can be seen.

Abolfazl Panbehkar
  • 700
  • 2
  • 7
  • 21
Amin
  • 1,637
  • 1
  • 22
  • 40
  • One alternative: Use a radial gradient to create the overlay effect, that way you get the same effect without having to rely on any new and questionably-supported browser features. – DBS Jul 22 '20 at 13:51
  • Radial gradient for the circle or the background? – Amin Jul 22 '20 at 13:53
  • For the dark overlay, I'll put together an example in an answer. – DBS Jul 22 '20 at 13:54
  • you want to reward an existing answer or you are not satisfied with any of the current answers? – Temani Afif Oct 26 '20 at 21:30

4 Answers4

9

This can be achieved using a radial gradient, (Example split onto separate lines to make it easier to read)

background-image: radial-gradient(
   /* Position the circle at the center, 40px from the top */
  circle at center 40px,
  /* The center of the radius should be dark */
  rgba(0,0,0,0.4) 0%,
  /* This is the inner edge of the circle, we transition from dark-transparent between pixels 30 and 31 */
  rgba(0,0,0,0.4) 30px, rgba(0,0,0,0) 31px, 
  /* This is the outer edge of the circle, we transition back from transprent-dark between pixels 34 and 35*/
  rgba(0,0,0,0) 34px, rgba(0,0,0,0.4) 35px,  
  /* Everything outside of the circle should be dark */
  rgba(0,0,0,0.4) 100%
);

Where circle at center 40px defines the position of the circle relative to the parent element (Horizontally centred, an 40px down from the top) bare in mind this is the position for the centre of the circle so you do need to account for it's radius.

And we use very small steps between the gradient to make it look like a solid line rather than a blurred gradient (I find that a 1px difference helps prevent aliasing on the line and makes everything look much smoother)

You can adjust the size of the circle or the thickness of the line by changing the 30px, 31px, 34px and 35px values in the gradient.

Working example:

.item {
  position: relative;
  width: 200px;
  height: 200px;
  background: url(https://picsum.photos/seed/picsum/200/200);
}

.item:before {
  position: absolute;
  content: '';
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  z-index: 1;
  /* This is the ring itself, you can adjust it's size using the pixel values, leaving 1px differnce usually leaves the best result for smooth edges */
  background-image: radial-gradient(circle at center 40px, rgba(0, 0, 0, 0.4) 0%, rgba(0, 0, 0, 0.4) 30px, rgba(0, 0, 0, 0) 31px, rgba(0, 0, 0, 0) 34px, rgba(0, 0, 0, 0.4) 35px, rgba(0, 0, 0, 0.4) 100%);
}
<div class="item"></div>

(This method is browser compatible with pretty much every browser released since 2010)

DBS
  • 9,110
  • 4
  • 35
  • 53
5

Infinite box-shadow with overflow: hidden; I don't know if it would work for you, I just tried-

<style>
  .item img {
    max-width: 100%;
    vertical-align: top;
  }

  .item {
    font-family: 'Amiri', serif;
    width: 300px;
    margin: 20px auto;
    overflow: hidden; /* STEP-1 */
    position: relative;
  }

  .rate {
    position: absolute;
    width: 100px;
    height: 100px;

    border-radius: 100%;
    background: rgba(0,0,0,.7);
    top: 80px;
    left: 50%;
    transform: translatex(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    font-size: 22px;
    color: #fff;
  }

  .rate::before {
    position: absolute;
    content: '';
    width: calc(100% + 10px);
    height: calc(100% + 10px);
    top: -5px;
    left: 50%;
    transform: translatex(-50%);
    border-radius: 100%;
    box-shadow: 0 0 0 100vh rgba(0,0,0,.7); /* STEP-2 */
  }

  .amount {
    font-size: 20px;
    font-weight: 700;
    display: block;
  }
</style>



<link href="https://fonts.googleapis.com/css2?family=Amiri:wght@400;700&display=swap" rel="stylesheet">

<div class="item">
   <img src="https://images.pexels.com/photos/4888690/pexels-photo-4888690.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940" alt="Card title">
   <span class="rate">
     <span class="amount">١٠</span> امتیاز
   </span>
</div>
Tanim
  • 1,256
  • 8
  • 14
  • [Just found](https://stackoverflow.com/questions/14061104/css3-box-shadow-size-percent-units) out that the value of spread in `box-shadow` can have `vw` and `vh` units, so I updated my demo, it means the trick in this demo is more dynamic than before. – Tanim Nov 28 '20 at 15:19
2

You could use a few divs with position: absolute:

body {
  margin: 0;
}

.container {
  display: flex;
  justify-content: center;
  align-items: center;
}

.bg {
  height: 100vh;
  width: 100%;
  background-image: url('https://i.ytimg.com/vi/fqumdSlyLxg/maxresdefault.jpg');
  filter: brightness(0.4);
}

.circle {
  position: absolute;
  height: 150px;
  width: 150px;
  border-radius: 50%;
  backdrop-filter: brightness(5);
  -webkit-backdrop-filter: brightness(5);
  z-index: 0;
}

.inner-circle {
  position: absolute;
  height: 142px;
  width: 142px;
  border-radius: 50%;
  backdrop-filter: brightness(0.2);
  -webkit-backdrop-filter: brightness(0.2);
  z-index: 1;
}

.rate {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-evenly;
  position: absolute;
  height: 142px;
  color: white;
  z-index: 2;
}

.amount {
  font-size: 30px;
  border-radius: 50%;
  text-shadow: 0px 0px 5px #fff;
}
<div class="container">
  <div class="bg"></div>
  <div class="circle"></div>
  <div class="inner-circle"></div>
  <div class="rate">
    <span class="amount">10</span>
    <span class="amount">امتیاز</span>
  </div>
</div>

Use the backdrop-filter property to set the brightness and display: flex on the container to center everything, then for the text use text-shadow to make it luminous.

Daniel_Knights
  • 7,940
  • 4
  • 21
  • 49
  • 2
    Looks nice, unfortunately only about 50% global support for `backdrop-filter`. Know an alternative to get the same effect? – Rene van der Lende Jul 22 '20 at 14:36
  • Added the `-webkit-` prefix which means it works in Safari, Edge, Chrome and Opera. Just Firefox and IE that don't seem to like it. – Daniel_Knights Jul 22 '20 at 15:23
  • 1
    Good thing you did, but I guess it'll be some while for the property to kick in. Have a look at my alternative...and shoot at it ;-)... Uses `background-blend-mode` and transparent colors. – Rene van der Lende Jul 22 '20 at 15:39
0

As an alternative, I made .item and its child elements Flexbox containers for easy positioning.

The circle is simply a circular element with a border.

All you have to do now is fiddle with sizes, colors and tranparency.

For the fun of it I added some :hover effects...

snippet with comments

/* All are FBL containers, for easy positioning */
.item, .item>*, .rate {
    display: flex;
    justify-content: center; align-items: center;
}
.rate { flex-direction: column }

/* item content */
.item {
    position: relative; /* position child elements to this parent */
    width: 400px;
    height: 600px;

    /* set image to background of item */
    background-image: url("https://i.ytimg.com/vi/fqumdSlyLxg/maxresdefault.jpg");
    background-repeat: no-repeat;
    background-size: cover;             /* clip/stretch when too large/small */

    background-color: rgba(0,0,0,0.3);  /* some tranparent black */
    background-blend-mode: overlay;     /* mix bg-color with image */

    /* eye-candy */
    margin: 5rem auto; /* center */

    font-size: 1.5em;
    font-weight: bold;
    color: rgba(255,255,255,.6);
    border-radius: 12px;
}

.item>* {
    position: absolute; /* position child inside parent */
    width : 100px; height: 100px;
    
    opacity: 0.7;
}

.rate { text-shadow: 0px 0px 7px rgba(255,255,255,.8) }

.circle { 
    border: 5px solid rgba(255,255,255,.3);
    border-radius: 50%;

    filter: blur(1px);
}

/******************************/
/* HOVER eye-candy, demo only */
/******************************/
.item:hover {
    background-blend-mode: normal;
    color: rgba(255,255,255,1);
}

.item:hover>* {
    opacity: 1;
}
.item:hover .circle {
    border-color: rgba(255,255,255,.8);
}


/* demo eye-candy */
.item {
    /* GMC elevation 1dp */
    box-shadow: 0px 2px 1px -1px rgba(0,0,0,.20),
                0px 1px 1px  0px rgba(0,0,0,.14),
                0px 1px 3px  0px rgba(0,0,0,.12);
}
.item:hover {
    transform: scale(1.01);
    /* GMC elevation 3dp */
    box-shadow: 0px 3px 3px -2px rgba(0,0,0,.20),
                0px 3px 4px  0px rgba(0,0,0,.14),
                0px 1px 8px  0px rgba(0,0,0,.12);
}
/*.item:active:not(:focus) { transform: scale(1) }/* enable for some animation */
<div class="item">
    <div class="circle"></div>
    <div class="rate">
        <span class="amount">10</span>
        <span>text</span>
    </div>
</div>
Rene van der Lende
  • 4,992
  • 2
  • 14
  • 25
  • nice but it's not transparent you can't visibily see the backgound image – Amin Aug 13 '20 at 10:47
  • Not sure what you mean, but this works fine in FF, Chrome and Edge [so63035636-1.jpg](https://i.postimg.cc/W1GqBn9n/so63035636-1.jpg) – Rene van der Lende Aug 13 '20 at 10:56
  • See the screenshot in first post, the point here is that the circle must cut the dark backgound, it's like we searate a circle from dark bg – Amin Aug 13 '20 at 11:04
  • With all the blur and opacity eye-candy I made, it is hard to see that the circle and text *do* get cut out as you meant. I'll adjust the snippet and make the effect more clear. With `background-blend-mode` and `mix-blend-mode` you can use colors *black* (with overlay,multiply) and *white* (with screen,hard-light,soft-light) to enhance/degrade the darkness and lightness of an element (or image), comparable with *layer-mask* in Photoshop or *Dodge&Burn* in ol'skool photo development. The blend modes are very powerfull, but many people don't know how to use them. I'll get back, with a mini tut. – Rene van der Lende Aug 13 '20 at 13:41