Modify the position of the second gradient and, most importantly, assign a radius to both gradients to prevent any automatic value discrepancies due to different positions. The default value for size is farthest-corner
, which may vary based on the position.
.top-semi-circle, .bottom-semi-circle {
width: 10em;
height: 5em;
}
.top-semi-circle {
border-radius: 10em 10em 0 0;
background: radial-gradient(circle 10em at 100px 100px, red, #000);
}
.bottom-semi-circle {
border-radius: 0 0 10em 10em;
background: radial-gradient(circle 10em at 100px 20px, red, #000);
}
.bottom-semi-circle:hover {
transform:translateY(10px);
}
<div class="top-semi-circle"></div>
<div class="bottom-semi-circle"></div>
The radial gradient syntax is:
radial-gradient() = radial-gradient(
[ <ending-shape> || <size> ]? [ at <position> ]? ,
<color-stop-list>
<size>
Determines the size of the gradient’s ending shape. If omitted it defaults to farthest-corner. ref
You can also adjust background-size
/background-position
to maintain the gradient's definition. Simply set the size equal to the overall shape (top half + bottom half).
.top-semi-circle, .bottom-semi-circle {
width: 10em;
height: 5em;
background-image: radial-gradient(circle at 100px 100px, red, #000);
background-size:10em 10em;
}
.top-semi-circle {
border-radius: 10em 10em 0 0;
background-position:top;
}
.bottom-semi-circle {
border-radius: 0 0 10em 10em;
background-position:bottom;
}
.bottom-semi-circle:hover {
transform:translateY(10px);
}
<div class="top-semi-circle"></div>
<div class="bottom-semi-circle"></div>
An alternative approach is overlapping with clip-path:
.top-semi-circle, .bottom-semi-circle {
width: 10em;
height: 10em;
border-radius: 10em;
background: radial-gradient(circle at 100px 100px, red, #000);
}
.top-semi-circle {
clip-path:polygon(0 0,100% 0,100% 50%,0 50%);
}
.bottom-semi-circle {
margin-top:-10em;
clip-path:polygon(0 100%,100% 100%,100% 50%,0 50%);
}
.bottom-semi-circle:hover {
transform:translateY(10px);
}
<div class="top-semi-circle"></div>
<div class="bottom-semi-circle"></div>
Similarly, you can achieve the same effect using mask
:
.top-semi-circle, .bottom-semi-circle {
width: 10em;
height: 10em;
border-radius: 10em;
background: radial-gradient(circle at 100px 100px, red, #000);
}
.top-semi-circle {
-webkit-mask:linear-gradient(to bottom,white 50%,transparent 0);
mask:linear-gradient(to bottom,white 50%,transparent 0);
}
.bottom-semi-circle {
margin-top:-10em;
-webkit-mask:linear-gradient(to top,white 50%,transparent 0);
mask:linear-gradient(to top,white 50%,transparent 0);
}
.bottom-semi-circle:hover {
transform:translateY(10px);
}
<div class="top-semi-circle"></div>
<div class="bottom-semi-circle"></div>