4

I managed to achieve this effect: http://jsfiddle.net/6z3msdwf/1/ but I am not really happy with the markup. Also, there is an weird bug in IE 10/11 where a 1px gap is shown when you resize the window.

Is there any other way to do this? Or maybe fix this one in IE.

EDIT The circle must not use a border, it should be transparent.

body,
html {
  font-size: 18px;
}
body {
  background-color: #fff
}
.avatar {
  width: 90px;
  height: 90px;
  position: absolute;
  background-color: red;
  top: -115px;
  left: 5px;
  border-radius: 80px;
}
.wrap {
  display: block;
  margin: 100px auto 0 auto;
  width: 90%;
  position: relative;
}
.rect-left,
.rect-right {
  position: relative;
  width: 50%;
  height: 150px;
  float: left;
}
.rect-left {
  margin-left: -50px;
}
.rect-right {
  margin-right: -50px;
}
.inner {
  position: absolute;
  top: 0;
  left: 50px;
  right: 0;
  bottom: 0;
  height: 100%;
  background: rgba(0, 0, 0, 0.8);
}
.rect-left .inner {
  left: 50px;
  right: 0;
  -webkit-border-top-left-radius: 6px;
  -webkit-border-bottom-left-radius: 6px;
  -moz-border-radius-topleft: 6px;
  -moz-border-radius-bottomleft: 6px;
  border-top-left-radius: 6px;
  border-bottom-left-radius: 6px;
}
.rect-right .inner {
  left: 0;
  right: 50px;
  -webkit-border-top-right-radius: 6px;
  -webkit-border-bottom-right-radius: 6px;
  -moz-border-radius-topright: 6px;
  -moz-border-radius-bottomright: 6px;
  border-top-right-radius: 6px;
  border-bottom-right-radius: 6px;
}
.rect {
  float: left;
  height: 100px;
  width: 100px;
  background: rgba(0, 0, 0, 0.8);
  position: relative;
  top: 50px;
}
.circle {
  display: block;
  width: 100px;
  height: 50px;
  top: -50px;
  left: 0;
  overflow: hidden;
  position: absolute;
}
.circle:after {
  content: '';
  width: 100px;
  height: 100px;
  -moz-border-radius: 100px;
  -webkit-border-radius: 100px;
  border-radius: 100px;
  background: rgba(0, 0, 0, 0);
  position: absolute;
  top: -110px;
  left: -40px;
  border: 40px solid rgba(0, 0, 0, 0.8);
}
<div class="wrap">
  <div class="rect-left">
    <div class="inner"></div>
  </div>
  <div class="rect">&nbsp;<span class="circle"></span>
    <div class="avatar"></div>
  </div>
  <div class="rect-right">
    <div class="inner"></div>
  </div>
</div>
web-tiki
  • 99,765
  • 32
  • 217
  • 249
superwinner
  • 95
  • 1
  • 7
  • Sure...use SVG. Simple – Paulie_D Apr 28 '16 at 11:50
  • why black element is in 3 parts while this could be 1 single object.. – Ganesh Yadav Apr 28 '16 at 11:56
  • How do you make it with 1 single object and make that circle cut out effect (without using a border, it should be transparent because I am using a background image)? – superwinner Apr 28 '16 at 12:01
  • People need to start realizing CSS is not a graphics generating tool. While some of these things can be done, whether they should be done using CSS is a different story. The SVG suggestion and answer is a good one (though the question asks for CSS). – Rob Apr 28 '16 at 12:06
  • @Rob although svg is clearly more powerfull to make graphical elements, I can understand OP prefers CSS as adding content in the shapes (images, text with unknown length...) might be easier without SVG. – web-tiki Apr 28 '16 at 12:44
  • @web-tiki My point is that it's the wrong tool. – Rob Apr 28 '16 at 12:45

3 Answers3

9

You can do this using a single element (plus a pseudo element) using radial-gradient background for the parent element while the pseudo-element creates the circle.

div:before {  /* creates the red circle */
  position: absolute;
  content: '';
  width: 90px;
  height: 90px;
  top: -75px;  /* top = -75px, radius = 45px, so circle's center point is at -30px */
  left: calc(50% - 45px);
  background-color: red;
  border-radius: 50%;
}
div {
  position: relative;
  margin: 100px auto 0 auto;
  width: 90%;
  height: 150px;
  border-radius: 6px;  
  
  /* only the below creates the transparent gap and the fill */
  background: radial-gradient(50px 50px at 50% -30px, rgba(0, 0, 0, 0) 49.5px, rgba(0, 0, 0, .8) 50.5px);  /* use same center point as with concentric circles but larger radius */
}

/* just for demo */

body,
html {
  font-size: 18px;
}
body {
  background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<div></div>
Harry
  • 87,580
  • 25
  • 202
  • 214
6

With an inline svg it is very simple :

body{background:url('http://i.imgur.com/5NK0H1e.jpg');background-size:cover;
svg{display:block;}
<svg viewbox="0 0 10 3.5">
  <path d="M4.2 1 A0.85 0.85 0 0 0 5.8 1 H10 V3.5 H0 V1z" fill="#333" />
  <circle cx="5" cy="0.7" r="0.7" fill="red" /> 
</svg>

Or if you really want to use CSS, you can achieve the shape with the approach described in: Transparent half circle cut out of a div.
Note that the code is much longer than the svg approach:

.container{
  position:relative;
  height:250px;
  text-align:center;
}
.circle{
  position:relative;
  display:inline-block;
  width:100px; height:100px;
  background:red;
  border-radius:50%;
  z-index:2;
}
.rect{
  position:absolute;
  top:50px; left:0;
  width:100%; height:200px;
  border-radius:10px;
  overflow:hidden;
  z-index:1;
}
.rect:before{
  content:'';
  position:absolute;
  top:-60px; left:50%;
  margin-left:-60px;
  width:120px; height:120px;
  border-radius:50%;
  box-shadow:0 0 0 99999px #333;  
}

body{background:url('http://i.imgur.com/5NK0H1e.jpg');background-size:cover;
<div class="container">
  <div class="circle"></div>
  <div class="rect"></div>
</div>
Community
  • 1
  • 1
web-tiki
  • 99,765
  • 32
  • 217
  • 249
6

You could use a circular gradient

div {
  height: 150px;
  margin: 5em 2em;
  background: radial-gradient(circle at top center, transparent, transparent 70px, black 70px, black);
  border-radius: 8px;
  position: relative;
}
.circle {
  width: 120px;
  height: 120px;
  background: red;
  border-radius: 50%;
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate(-50%, -50%);
}
body {
  background-image: url(http://www.fillmurray.com/1000/1000);
  background-size: cover;
}
<div>
  <span class="circle"></span>
</div>
Paulie_D
  • 107,962
  • 13
  • 142
  • 161