CSS transparent curved shape with two rounded sides

Here is an idea using radial-gradient

.box {
  margin-top:120px;
  width:200px;
  height:100px;
  background:white;
}
.box .top {
  height:100px;
  width:150px;
  transform:translateY(-100%);
  position:relative;
  background:#fff;
}

.top:before,
.top:after{
  content:"";
  position:absolute;
  top:0;
  width:50px;
  left:100%;
  bottom:50%;
  background:
    radial-gradient(100% 50% at top left, #fff 98%,transparent 100%) right,
    radial-gradient(100% 50% at bottom right, transparent 98%,#fff 100%) left;
  background-size:50% 100%;
  background-repeat:no-repeat;
}
.top:after {
  transform-origin:bottom;
  transform:scaleY(-1);
}
body {
  background:pink;
}
<div class="box">
<div class="top"></div>
</div>

To better understand the trick here is the curved shape alone with different colors:

.top {
  height:100px;
  width:100px;
  position:relative;
}

.top:before,
.top:after{
  content:"";
  position:absolute;
  top:0;
  width:50px;
  left:100%;
  bottom:50%;
  background:
    radial-gradient(100% 50% at top left, red 98%,blue 100%) right,
    radial-gradient(100% 50% at bottom right, purple 98%,green 100%) left;
  background-size:50% 100%;
  background-repeat:no-repeat;
  outline:2px solid;
}
.top:after {
  transform-origin:bottom;
  transform:scaleY(-1);
}
body {
  background:pink;
}
<div class="top"></div>

And here is an SVG solution where I will simply replace the gradient with an SVG

.box {
  margin-top:120px;
  width:200px;
  height:100px;
  background:white;
}
.box .top {
  height:100px;
  width:150px;
  transform:translateY(-100%);
  position:relative;
  background:#fff;
}

.top:before{
  content:"";
  position:absolute;
  top:0;
  width:50px;
  left:100%;
  bottom:0;
  background:url("data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version='1.1' viewBox='0 0 64 64' width="64" height="64" preserveAspectRatio='none' fill="white"><path d='M0 0 L0 64 L64 64 C64 40 0 56 0 32 C0 8 64 24 64 0 Z' /></svg>");
  background-size:100% 100%;
}
body {
  background:pink;
}
<div class="box">
<div class="top"></div>
</div>

You can optimize the code and use only one element:

.box {
  width:200px;
  height:200px;
  background:
    radial-gradient(100% 50% at top     left, #fff 98%,transparent 100%) top 0    right 0   /30px 50px,
    radial-gradient(100% 50% at bottom right, transparent 98%,#fff 100%) top 0    right 30px/30px 50px,
    radial-gradient(100% 50% at bottom  left, #fff 98%,transparent 100%) top 50px right 0   /30px 50px,
    radial-gradient(100% 50% at top    right, transparent 98%,#fff 100%) top 50px right 30px/30px 50px,
    linear-gradient(#fff,#fff) bottom/100% calc(100% - 100px),
    linear-gradient(#fff,#fff) left  /calc(100% - 60px) 100%;
  background-repeat:no-repeat;
}

body {
  background:pink;
}
<div class="box">
</div>

And with the SVG:

.box {
  width:200px;
  height:200px;
  background:
    url("data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version='1.1' viewBox='0 0 64 64' width="64" height="64" preserveAspectRatio='none' fill="white"><path d='M0 0 L0 64 L64 64 C64 40 0 56 0 32 C0 8 64 24 64 0 Z' /></svg>") top right/60px 100px,
    linear-gradient(#fff,#fff) bottom/100% calc(100% - 100px),
    linear-gradient(#fff,#fff) left  /calc(100% - 60px) 100%;
  background-repeat:no-repeat;
}

body {
  background:pink;
}
<div class="box">
</div>

You can add some CSS variable to control everything easily:

.box {
  --w:60px;  /*width of the curve */
  --h:100px; /*height of the curve */
  --t:0px;   /*offset from top */

  width:150px;
  height:150px;
  display:inline-block;
  background:
    url("data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version='1.1' viewBox='0 0 64 64' width="64" height="64" preserveAspectRatio='none' fill="white"><path d='M0 0 L0 64 L64 64 C64 40 0 56 0 32 C0 8 64 24 64 0 Z' /></svg>") top var(--t) right 0/var(--w) var(--h),
    
    linear-gradient(#fff,#fff) top   /100% var(--t),
    linear-gradient(#fff,#fff) bottom/100% calc(100% - var(--h) - var(--t)),
    linear-gradient(#fff,#fff) left  /calc(100% - var(--w)) 100%;
  background-repeat:no-repeat;
}

body {
  background:pink;
}
<div class="box"></div>

<div class="box" style="--t:20px;--w:50px;--h:80px"></div>

<div class="box" style="--t:20px;--w:80px;--h:130px"></div>

CSS inner curved transparent shape


Another idea using mask in case you want to conside a random background. Simply place the background inside the mask definition:

.box {
  width:200px;
  height:200px;
  -webkit-mask:
    radial-gradient(100% 50% at top     left, transparent 98%,#fff 100%) top 0    right 0   /30px 50px,
    radial-gradient(100% 50% at bottom right, #fff 98%,transparent 100%) top 0    right 30px/30px 50px,
    radial-gradient(100% 50% at bottom  left, transparent 98%,#fff 100%) top 50px right 0   /30px 50px,
    radial-gradient(100% 50% at top    right, #fff 98%,transparent 100%) top 50px right 30px/30px 50px,
    linear-gradient(#fff,#fff);
  -webkit-mask-composite:destination-out;
  mask-composite:exclude;
  -webkit-mask-repeat:no-repeat;
  background:linear-gradient(red,blue);
}

body {
  background:pink;
}
<div class="box">
</div>

With the SVG syntax

.box {
  --w:60px;  /*width of the curve */
  --h:100px; /*height of the curve */
  --t:0px;   /*offset from top */

  width:150px;
  height:150px;
  display:inline-block;
  -webkit-mask:
    url("data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version='1.1' viewBox='0 0 64 64' width="64" height="64" preserveAspectRatio='none' fill="white"><path d='M0 0 L0 64 L64 64 C64 40 0 56 0 32 C0 8 64 24 64 0 Z' /></svg>") top var(--t) right 0/var(--w) var(--h),
    
    linear-gradient(#fff,#fff) top   /100% var(--t),
    linear-gradient(#fff,#fff) bottom/100% calc(100% - var(--h) - var(--t)),
    linear-gradient(#fff,#fff) left  /calc(100% - var(--w)) 100%;
  mask:
    url("data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version='1.1' viewBox='0 0 64 64' width="64" height="64" preserveAspectRatio='none' fill="white"><path d='M0 0 L0 64 L64 64 C64 40 0 56 0 32 C0 8 64 24 64 0 Z' /></svg>") top var(--t) right 0/var(--w) var(--h),
    
    linear-gradient(#fff,#fff) top   /100% var(--t),
    linear-gradient(#fff,#fff) bottom/100% calc(100% - var(--h) - var(--t)),
    linear-gradient(#fff,#fff) left  /calc(100% - var(--w)) 100%;
  -webkit-mask-repeat:no-repeat;
  mask-repeat:no-repeat;
  background:linear-gradient(red,blue);
}

body {
  background:pink;
}
<div class="box"></div>

<div class="box" style="--t:20px;--w:50px;--h:80px"></div>

<div class="box" style="--t:20px;--w:80px;--h:130px"></div>

CSS inner curver gradient shape

Leave a Comment