Amin Abdolrezapoor
Amin Abdolrezapoor

Reputation: 1847

Circle with transparent borders over background

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.

Upvotes: 9

Views: 1312

Answers (4)

Tanim
Tanim

Reputation: 1249

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>

Upvotes: 5

DBS
DBS

Reputation: 9984

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)

Upvotes: 9

Rene van der Lende
Rene van der Lende

Reputation: 5281

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>

Upvotes: 0

Dan Knights
Dan Knights

Reputation: 8368

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.

Upvotes: 2

Related Questions