Clip a circular path of a div with precision (curve path) [duplicate] - html

I would like to curve the bottom side of this rectangle div/background with CSS, so the result is something like this:
Does someone have an idea perhaps how it could be achieved?
.curved {
margin: 0 auto;
height: 400px;
background: lightblue;
border-radius:0 0 200px 200px;
}
<div class="container">
<div class="curved"></div>
</div>

Simply use border-radius and rely on some overflow. You can also consider pseudo element to avoid extra markup:
.container {
margin: 0 auto;
width: 500px;
height: 200px;
background: lightblue;
position: relative;
overflow: hidden;
}
.container:after {
content: "";
position: absolute;
height: 80px;
left: -10%;
right: -10%;
border-radius: 50%;
bottom: -25px;
background: #fff;
}
<div class="container">
</div>
You can also use radial-gradient if you want a transparent shape:
body {
background: pink;
}
.container {
margin: 0 auto;
width: 500px;
height: 200px;
background: radial-gradient(110% 50% at bottom, transparent 50%, lightblue 51%);
}
<div class="container">
</div>
And here is another way using clip-path
.container {
margin: 0 auto;
width: 500px;
height: 200px;
background-color: lightblue;
position: relative;
overflow: hidden;
}
.container:after {
content: "";
position: absolute;
bottom: 0;
right: -5%;
left: -5%;
height: 120px;
background: #fff;
-webkit-clip-path: ellipse(50% 60% at 50% 100%);
clip-path: ellipse(50% 60% at 50% 100%);
}
<div class="container">
</div>
You can also consider SVG:
.container {
margin: 0 auto;
width: 500px;
height: 200px;
background: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64' width='64' height='48' fill='lightblue'><path d='M0 0 L0 16 C16 6 48 6 64 16 L64 0 Z' /></svg>") top center/auto 700px no-repeat;
}
<div class="container">
</div>
Here is an example if you want also to add border around your shape:
.container {
margin: 0 auto;
width: 500px;
height: 200px;
border: 2px solid #000;
border-bottom: 0;
background: lightblue;
position: relative;
overflow: hidden;
}
.container:after {
content: "";
position: absolute;
height: 80px;
left: -10%;
right: -10%;
border-radius: 50%;
bottom: -62px;
background: #fff;
z-index: 2;
}
.container:before {
content: "";
position: absolute;
height: 82px;
left: -10%;
right: -10%;
border-radius: 50%;
bottom: -62px;
background: #000;
z-index: 1;
}
<div class="container">
</div>
If you want to have an image or gradient as background with the transparency, use mask-image:
body {
background: pink;
}
.container {
margin: 0 auto;
width: 500px;
height: 200px;
-webkit-mask-image: radial-gradient(110% 50% at bottom, transparent 50%, #fff 51%);
mask-image: radial-gradient(110% 50% at bottom, transparent 50%, #fff 51%);
background: linear-gradient(45deg,red,yellow,blue);
}
<div class="container">
</div>

Check this. I created this with :after pseudo element. It can be helpful if the background is solid color.
.curved {
margin: 0 auto;
width: 300px;
height: 300px;
background: lightblue;
position: relative;
}
.curved:after{
background: white;
position: absolute;
content: "";
left:0;
right:0;
bottom: -25px;
height: 50px;
border-radius: 50% 50% 0 0;
}
<div class="container">
<div class="curved"></div>
</div>

Related

CSS clip path rounded bottom edge and next site top edge following same curve [duplicate]

I would like to curve the bottom side of this rectangle div/background with CSS, so the result is something like this:
Does someone have an idea perhaps how it could be achieved?
.curved {
margin: 0 auto;
height: 400px;
background: lightblue;
border-radius:0 0 200px 200px;
}
<div class="container">
<div class="curved"></div>
</div>
Simply use border-radius and rely on some overflow. You can also consider pseudo element to avoid extra markup:
.container {
margin: 0 auto;
width: 500px;
height: 200px;
background: lightblue;
position: relative;
overflow: hidden;
}
.container:after {
content: "";
position: absolute;
height: 80px;
left: -10%;
right: -10%;
border-radius: 50%;
bottom: -25px;
background: #fff;
}
<div class="container">
</div>
You can also use radial-gradient if you want a transparent shape:
body {
background: pink;
}
.container {
margin: 0 auto;
width: 500px;
height: 200px;
background: radial-gradient(110% 50% at bottom, transparent 50%, lightblue 51%);
}
<div class="container">
</div>
And here is another way using clip-path
.container {
margin: 0 auto;
width: 500px;
height: 200px;
background-color: lightblue;
position: relative;
overflow: hidden;
}
.container:after {
content: "";
position: absolute;
bottom: 0;
right: -5%;
left: -5%;
height: 120px;
background: #fff;
-webkit-clip-path: ellipse(50% 60% at 50% 100%);
clip-path: ellipse(50% 60% at 50% 100%);
}
<div class="container">
</div>
You can also consider SVG:
.container {
margin: 0 auto;
width: 500px;
height: 200px;
background: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64' width='64' height='48' fill='lightblue'><path d='M0 0 L0 16 C16 6 48 6 64 16 L64 0 Z' /></svg>") top center/auto 700px no-repeat;
}
<div class="container">
</div>
Here is an example if you want also to add border around your shape:
.container {
margin: 0 auto;
width: 500px;
height: 200px;
border: 2px solid #000;
border-bottom: 0;
background: lightblue;
position: relative;
overflow: hidden;
}
.container:after {
content: "";
position: absolute;
height: 80px;
left: -10%;
right: -10%;
border-radius: 50%;
bottom: -62px;
background: #fff;
z-index: 2;
}
.container:before {
content: "";
position: absolute;
height: 82px;
left: -10%;
right: -10%;
border-radius: 50%;
bottom: -62px;
background: #000;
z-index: 1;
}
<div class="container">
</div>
If you want to have an image or gradient as background with the transparency, use mask-image:
body {
background: pink;
}
.container {
margin: 0 auto;
width: 500px;
height: 200px;
-webkit-mask-image: radial-gradient(110% 50% at bottom, transparent 50%, #fff 51%);
mask-image: radial-gradient(110% 50% at bottom, transparent 50%, #fff 51%);
background: linear-gradient(45deg,red,yellow,blue);
}
<div class="container">
</div>
Check this. I created this with :after pseudo element. It can be helpful if the background is solid color.
.curved {
margin: 0 auto;
width: 300px;
height: 300px;
background: lightblue;
position: relative;
}
.curved:after{
background: white;
position: absolute;
content: "";
left:0;
right:0;
bottom: -25px;
height: 50px;
border-radius: 50% 50% 0 0;
}
<div class="container">
<div class="curved"></div>
</div>

Add semi circle curve for a div at left and right using background color - CSS [duplicate]

This question already has answers here:
CSS Cut out circle from a rectangular shape
(3 answers)
Closed 1 year ago.
Can anyone help me with how to get the style like in the image attached below using background colour for a div? I tried adding using pseudo-classes before and after but doesn't seem to be coming through.
.card {
height: 190px;
background: #070B32;
width: 360px;
position: relative;
}
.card:before {
background: #070B32;
position: absolute;
content: "";
left: 0;
height: 50px;
border-radius: 50% 50% 0 0;
}
.card:after {
background: #070B32;
position: absolute;
content: "";
right: 0;
height: 50px;
border-radius: 50% 50% 0 0;
}
<div class="card">
</div>
Use width top values too to have semi-circles with a change in color
.card {
height: 190px;
background: #070B32;
width: 360px;
position: relative;
}
.card:before {
background: white;
position: absolute;
content: "";
left: 0;
top:35%;
width: 25px;
height: 50px;
border-radius: 0 150px 150px 0;
}
.card:after {
background: white;
position: absolute;
content: "";
right: 0;
top:35%;
width: 25px;
height: 50px;
border-radius: 150px 0 0 150px;
}
<div class="card">
</div>
Update:
div {
height: 150px;
margin: 5em 2em;
background: radial-gradient(circle at left center, transparent, transparent 30px, #070B32 30px, transparent), radial-gradient(circle at right center, transparent, transparent 30px, #070B32 30px, transparent);
border-radius: 8px;
position: relative;
width: 360px;
margin: auto;
}
body {
background-image: url(http://www.fillmurray.com/1000/1000);
background-size: cover;
}
<div>
</div>
you should use width: 50px, background-color: white;
and responsive vertical alignment:
top: 50%; transform: translateY(-50%);
.card {
height: 190px;
background: #070B32;
width: 360px;
position: relative;
}
.card:before {
background: #ffffff;
position: absolute;
content: "";
left: -25px;
top: 50%;
transform: translateY(-50%);
height: 50px;
width: 50px;
border-radius: 50%;
}
.card:after {
background: #ffffff;
position: absolute;
content: "";
right: -25px;
top: 50%;
transform: translateY(-50%);
height: 50px;
width: 50px;
border-radius: 50%;
}
<div class="card">
</div>
Or just use a background.
.card {
--circle-color: #fff;
--circle-size: 50px;
background: radial-gradient(farthest-side circle, var(--circle-color) 97%, transparent) calc(100% + (var(--circle-size) / 2)) 50% / var(--circle-size) var(--circle-size),
radial-gradient(farthest-side circle, var(--circle-color) 97%, transparent) calc(var(--circle-size) / -2) 50% / var(--circle-size) var(--circle-size),
#070B32;
background-repeat: no-repeat;
height: 190px;
width: 360px;
}
<div class="card">
</div>

How to create a curved semi-opaque background without using an image? [duplicate]

I would like to curve the bottom side of this rectangle div/background with CSS, so the result is something like this:
Does someone have an idea perhaps how it could be achieved?
.curved {
margin: 0 auto;
height: 400px;
background: lightblue;
border-radius:0 0 200px 200px;
}
<div class="container">
<div class="curved"></div>
</div>
Simply use border-radius and rely on some overflow. You can also consider pseudo element to avoid extra markup:
.container {
margin: 0 auto;
width: 500px;
height: 200px;
background: lightblue;
position: relative;
overflow: hidden;
}
.container:after {
content: "";
position: absolute;
height: 80px;
left: -10%;
right: -10%;
border-radius: 50%;
bottom: -25px;
background: #fff;
}
<div class="container">
</div>
You can also use radial-gradient if you want a transparent shape:
body {
background: pink;
}
.container {
margin: 0 auto;
width: 500px;
height: 200px;
background: radial-gradient(110% 50% at bottom, transparent 50%, lightblue 51%);
}
<div class="container">
</div>
And here is another way using clip-path
.container {
margin: 0 auto;
width: 500px;
height: 200px;
background-color: lightblue;
position: relative;
overflow: hidden;
}
.container:after {
content: "";
position: absolute;
bottom: 0;
right: -5%;
left: -5%;
height: 120px;
background: #fff;
-webkit-clip-path: ellipse(50% 60% at 50% 100%);
clip-path: ellipse(50% 60% at 50% 100%);
}
<div class="container">
</div>
You can also consider SVG:
.container {
margin: 0 auto;
width: 500px;
height: 200px;
background: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64' width='64' height='48' fill='lightblue'><path d='M0 0 L0 16 C16 6 48 6 64 16 L64 0 Z' /></svg>") top center/auto 700px no-repeat;
}
<div class="container">
</div>
Here is an example if you want also to add border around your shape:
.container {
margin: 0 auto;
width: 500px;
height: 200px;
border: 2px solid #000;
border-bottom: 0;
background: lightblue;
position: relative;
overflow: hidden;
}
.container:after {
content: "";
position: absolute;
height: 80px;
left: -10%;
right: -10%;
border-radius: 50%;
bottom: -62px;
background: #fff;
z-index: 2;
}
.container:before {
content: "";
position: absolute;
height: 82px;
left: -10%;
right: -10%;
border-radius: 50%;
bottom: -62px;
background: #000;
z-index: 1;
}
<div class="container">
</div>
If you want to have an image or gradient as background with the transparency, use mask-image:
body {
background: pink;
}
.container {
margin: 0 auto;
width: 500px;
height: 200px;
-webkit-mask-image: radial-gradient(110% 50% at bottom, transparent 50%, #fff 51%);
mask-image: radial-gradient(110% 50% at bottom, transparent 50%, #fff 51%);
background: linear-gradient(45deg,red,yellow,blue);
}
<div class="container">
</div>
Check this. I created this with :after pseudo element. It can be helpful if the background is solid color.
.curved {
margin: 0 auto;
width: 300px;
height: 300px;
background: lightblue;
position: relative;
}
.curved:after{
background: white;
position: absolute;
content: "";
left:0;
right:0;
bottom: -25px;
height: 50px;
border-radius: 50% 50% 0 0;
}
<div class="container">
<div class="curved"></div>
</div>

Create right responsive arrow [duplicate]

I am trying to create an arrow label, using css :after
.one-line {
font-size: 2em;
width: 150px;
min-height: 50px;
height: auto;
background: blue;
margin: 5px;
position: relative;
color: #fff;
}
.one-line:after {
content: '';
display: block;
position: absolute;
top: 0;
left: 100%;
width: 0;
height: 0;
border-top: 25px solid transparent;
border-bottom: 25px solid transparent;
border-left: 25px solid red;
}
<div class="one-line">text<br>text<br></div>
I want the after element to take the same height which is of parent, how can I do this by either css or js?
Note: The text inside the label is dynamically populating. [Max length of text: 2 lines]
It might not be possible, as I am thinking, to adjust it any height of parent. Currently I am trying it to adjust for both one and two lines of text.
Here is a solution using clip-path. The idea is to use % values in the polygon to only show the needed shape and it will always work whatever the height is:
.one-line {
font-size: 2em;
width: 150px;
min-height: 50px;
height: auto;
background: blue;
margin: 5px;
position: relative;
color: #fff;
}
.one-line:after {
content: '';
display: block;
position: absolute;
top: 0;
bottom: 0;
width: 25px;
right: -25px;
background: red;
-webkit-clip-path: polygon(100% 50%, 0 0, 0 100%);
clip-path: polygon(100% 50%, 0 0, 0 100%);
}
<div class="one-line">text<br>text<br></div>
<div class="one-line">text<br>text<br>text<br></div>
<div class="one-line">text</div>
<div class="one-line">text<br>text<br>text<br>text<br>text<br>text<br>text<br></div>
Here is another solution that rely on both pseudo elements and some skew transformation to create the arrow. You will notice that this one will keep ratio of the arrow.
.one-line {
font-size: 2em;
width: 150px;
min-height: 50px;
height: auto;
background: blue;
margin: 5px;
position: relative;
color: #fff;
}
.one-line:after {
content: '';
display: block;
position: absolute;
top: 0;
height: 50%;
width: 50%;
right: -25px;
background: red;
transform: skewX(20deg) translateX(-33%);
transform-origin: top;
z-index: -1;
}
.one-line:before {
content: '';
display: block;
position: absolute;
bottom: 0;
height: 50%;
width: 50%;
right: -25px;
background: red;
transform: skewX(-20deg) translateX(-33%);
transform-origin: bottom;
z-index: -1;
}
<div class="one-line">text<br>text<br></div>
<div class="one-line">text<br>text<br>text<br></div>
<div class="one-line">text</div>
<div class="one-line">text<br>text<br>text<br>text<br>text<br>text<br>text<br></div>
Another way with only one pseudo element and linear-gradient.
.one-line {
font-size: 2em;
width: 150px;
min-height: 50px;
height: auto;
background: blue;
margin: 5px;
position: relative;
color: #fff;
}
.one-line:after {
content: '';
display: block;
position: absolute;
top: 0;
height: 100%;
width: 50px;
right: -50px;
background:
linear-gradient(to bottom left, transparent 49.4%, red 50%) top,
linear-gradient(to top left, transparent 49.4%, red 50%) bottom;
background-size:100% 50.2%;
background-repeat:no-repeat;
}
<div class="one-line">text<br>text<br></div>
<div class="one-line">text<br>text<br>text<br></div>
<div class="one-line">text</div>
<div class="one-line">text<br>text<br>text<br>text<br>text<br>text<br>text<br></div>
And finally without any pseudo element and only background on the main element:
.one-line {
font-size: 2em;
width: 200px;
padding-left:50px;
min-height: 50px;
height: auto;
background:
linear-gradient(blue,blue) left/calc(100% - 50px) 100%,
linear-gradient(to bottom left, transparent 49.4%, red 50%) top right/50px 50.2%,
linear-gradient(to top left, transparent 49.4%, red 50%) bottom right/50px 50.2%;
background-repeat:no-repeat;
margin: 5px;
position: relative;
color: #fff;
}
<div class="one-line">text<br>text<br></div>
<div class="one-line">text<br>text<br>text<br></div>
<div class="one-line">text</div>
<div class="one-line">text<br>text<br>text<br>text<br>text<br>text<br>text<br></div>
Well, you could opt to keep the arrow the same size and align it in the middle by changing top to top: 50%; and adding transform: translateY(-50%);
.one-line{
width: 150px;
min-height: 50px;
height: auto;
background: blue;
margin: 5px;
position: relative;
color: #fff;
}
.one-line:after{
content: '';
display: block;
position: absolute;
left: 100%;
width: 0;
height: 0;
border-top: 25px solid transparent;
border-bottom: 25px solid transparent;
border-left: 25px solid red;
top: 50%;
transform: translateY(-50%);
}
<div class="one-line">text<br>text<br>text<br>text</div>
<div class="one-line">text<br>text<br>text<br>text<br>text<br>text<br>text<br>text<br>text<br>text<br>text</div>
using an svg path as a background-image, you could stretch the background-size property to 100% 100%. Just make sure the svg has preserveAspectRatio="none"
.one-line:after {
background-image: url('data:image/svg+xml;charset=UTF-8,<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" preserveAspectRatio="none" viewBox="0 0 25.1 50" style="enable-background:new 0 0 25.1 50;" xml:space="preserve"><polygon class="st0" points="0,50 0,50 25,25 0,0" fill="#ff0000"/></svg>');
position: absolute;
top: 0;
left:100%;
height: 100%;
width: 25px;
background-size: 100% 100%;
background-repeat:no-repeat;
display: block;
content:'';
}
https://jsfiddle.net/7jm54u6L/

Dynamically aligning pseudo element according to parent height

I am trying to create an arrow label, using css :after
.one-line {
font-size: 2em;
width: 150px;
min-height: 50px;
height: auto;
background: blue;
margin: 5px;
position: relative;
color: #fff;
}
.one-line:after {
content: '';
display: block;
position: absolute;
top: 0;
left: 100%;
width: 0;
height: 0;
border-top: 25px solid transparent;
border-bottom: 25px solid transparent;
border-left: 25px solid red;
}
<div class="one-line">text<br>text<br></div>
I want the after element to take the same height which is of parent, how can I do this by either css or js?
Note: The text inside the label is dynamically populating. [Max length of text: 2 lines]
It might not be possible, as I am thinking, to adjust it any height of parent. Currently I am trying it to adjust for both one and two lines of text.
Here is a solution using clip-path. The idea is to use % values in the polygon to only show the needed shape and it will always work whatever the height is:
.one-line {
font-size: 2em;
width: 150px;
min-height: 50px;
height: auto;
background: blue;
margin: 5px;
position: relative;
color: #fff;
}
.one-line:after {
content: '';
display: block;
position: absolute;
top: 0;
bottom: 0;
width: 25px;
right: -25px;
background: red;
-webkit-clip-path: polygon(100% 50%, 0 0, 0 100%);
clip-path: polygon(100% 50%, 0 0, 0 100%);
}
<div class="one-line">text<br>text<br></div>
<div class="one-line">text<br>text<br>text<br></div>
<div class="one-line">text</div>
<div class="one-line">text<br>text<br>text<br>text<br>text<br>text<br>text<br></div>
Here is another solution that rely on both pseudo elements and some skew transformation to create the arrow. You will notice that this one will keep ratio of the arrow.
.one-line {
font-size: 2em;
width: 150px;
min-height: 50px;
height: auto;
background: blue;
margin: 5px;
position: relative;
color: #fff;
}
.one-line:after {
content: '';
display: block;
position: absolute;
top: 0;
height: 50%;
width: 50%;
right: -25px;
background: red;
transform: skewX(20deg) translateX(-33%);
transform-origin: top;
z-index: -1;
}
.one-line:before {
content: '';
display: block;
position: absolute;
bottom: 0;
height: 50%;
width: 50%;
right: -25px;
background: red;
transform: skewX(-20deg) translateX(-33%);
transform-origin: bottom;
z-index: -1;
}
<div class="one-line">text<br>text<br></div>
<div class="one-line">text<br>text<br>text<br></div>
<div class="one-line">text</div>
<div class="one-line">text<br>text<br>text<br>text<br>text<br>text<br>text<br></div>
Another way with only one pseudo element and linear-gradient.
.one-line {
font-size: 2em;
width: 150px;
min-height: 50px;
height: auto;
background: blue;
margin: 5px;
position: relative;
color: #fff;
}
.one-line:after {
content: '';
display: block;
position: absolute;
top: 0;
height: 100%;
width: 50px;
right: -50px;
background:
linear-gradient(to bottom left, transparent 49.4%, red 50%) top,
linear-gradient(to top left, transparent 49.4%, red 50%) bottom;
background-size:100% 50.2%;
background-repeat:no-repeat;
}
<div class="one-line">text<br>text<br></div>
<div class="one-line">text<br>text<br>text<br></div>
<div class="one-line">text</div>
<div class="one-line">text<br>text<br>text<br>text<br>text<br>text<br>text<br></div>
And finally without any pseudo element and only background on the main element:
.one-line {
font-size: 2em;
width: 200px;
padding-left:50px;
min-height: 50px;
height: auto;
background:
linear-gradient(blue,blue) left/calc(100% - 50px) 100%,
linear-gradient(to bottom left, transparent 49.4%, red 50%) top right/50px 50.2%,
linear-gradient(to top left, transparent 49.4%, red 50%) bottom right/50px 50.2%;
background-repeat:no-repeat;
margin: 5px;
position: relative;
color: #fff;
}
<div class="one-line">text<br>text<br></div>
<div class="one-line">text<br>text<br>text<br></div>
<div class="one-line">text</div>
<div class="one-line">text<br>text<br>text<br>text<br>text<br>text<br>text<br></div>
Well, you could opt to keep the arrow the same size and align it in the middle by changing top to top: 50%; and adding transform: translateY(-50%);
.one-line{
width: 150px;
min-height: 50px;
height: auto;
background: blue;
margin: 5px;
position: relative;
color: #fff;
}
.one-line:after{
content: '';
display: block;
position: absolute;
left: 100%;
width: 0;
height: 0;
border-top: 25px solid transparent;
border-bottom: 25px solid transparent;
border-left: 25px solid red;
top: 50%;
transform: translateY(-50%);
}
<div class="one-line">text<br>text<br>text<br>text</div>
<div class="one-line">text<br>text<br>text<br>text<br>text<br>text<br>text<br>text<br>text<br>text<br>text</div>
using an svg path as a background-image, you could stretch the background-size property to 100% 100%. Just make sure the svg has preserveAspectRatio="none"
.one-line:after {
background-image: url('data:image/svg+xml;charset=UTF-8,<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" preserveAspectRatio="none" viewBox="0 0 25.1 50" style="enable-background:new 0 0 25.1 50;" xml:space="preserve"><polygon class="st0" points="0,50 0,50 25,25 0,0" fill="#ff0000"/></svg>');
position: absolute;
top: 0;
left:100%;
height: 100%;
width: 25px;
background-size: 100% 100%;
background-repeat:no-repeat;
display: block;
content:'';
}
https://jsfiddle.net/7jm54u6L/