I am making a progress bar with a checkmark after 30% of the progress bar with flexbox.
I divided the bar into 3 parts, one with an orange background, then the checkmark then the red background.
The problem is that the dot (checkmark) doesn't come exactly after 30%, I need to align it in the center between the orange and red background.
.progress-container {
display: flex;
background: gray;
height: 20px;
width: 500px;
border-radius: 20px;
position: relative;
}
.threshold {
background: orange;
width: 30%;
border-top-left-radius: 20px;
border-bottom-left-radius: 20px;
}
.dot {
position: absolute;
left: 30%;
margin-top: -5px;
width: 24px;
height: 24px;
text-align: center;
border: 4px solid green;
background: #f8f8f8;
border-radius: 50%;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3);
}
.dot:after {
content: "✔";
color: green;
font-weight: bold;
font-size: 18px;
}
.completed {
flex: 1;
background: red;
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
}
<div class="progress-container">
<div class="threshold">
</div>
<div class="dot">
</div>
<div class="completed">
</div>
</div>
you need to push your div.dot 50% to the left to make the starting point of div as a center of a checkmark.
transform: translateX(-50%)
.progress-container {
display: flex;
background: gray;
height: 20px;
width: 500px;
border-radius: 20px;
position: relative;
}
.threshold {
background: orange;
width: 30%;
border-top-left-radius: 20px;
border-bottom-left-radius: 20px;
}
.dot {
position: absolute;
left: 30%;
margin-top: -5px;
width: 24px;
height: 24px;
text-align: center;
border: 4px solid green;
background: #f8f8f8;
border-radius: 50%;
transform: translateX(-50%);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3);
}
.dot:after {
content: "✔";
color: green;
font-weight: bold;
font-size: 18px;
}
.completed {
flex: 1;
background: red;
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
}
<div class="progress-container">
<div class="threshold">
</div>
<div class="dot">
</div>
<div class="completed">
</div>
</div>
Use transform: translate(-50%).
Essentially, the problem is that (because you use the 'left' property), your .dot div is being positioned by its left edge, while you want it to be positioned according to its center. One way to solve this is to simply shift your div to the left by half its width, thereby placing its center where its left edge used to be. This can be done by passing '-50%' to translate, shifting the element to the left by 50% of the element's width.
Your example, modified:
.progress-container {
display: flex;
background: gray;
height: 20px;
width: 500px;
border-radius: 20px;
position: relative;
}
.threshold {
background: orange;
width: 30%;
border-top-left-radius: 20px;
border-bottom-left-radius: 20px;
}
.dot {
transform: translate(-50%); /* Add this to offset the checkmark */
position: absolute;
left: 30%;
margin-top: -5px;
width: 24px;
height: 24px;
text-align: center;
border: 4px solid green;
background: #f8f8f8;
border-radius: 50%;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3);
}
.dot:after {
content: "✔";
color: green;
font-weight: bold;
font-size: 18px;
}
.completed {
flex: 1;
background: red;
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
}
<div class="progress-container">
<div class="threshold">
</div>
<div class="dot">
</div>
<div class="completed">
</div>
</div>
Related
working on React with StyledComponents, each <div> in the below represents a different Styled Component.
Trying to achieve something like this:
But I ideally want to add the "dashed line" styles in the progress-indicator so that it it sits vertically below the indicator and spans the full height of wrapping-container. I've tried using ::before & ::after but with no success.
.wrapping-container {
display: flex;
align-items: center;
margin-bottom: 20px;
}
.progress-indicator {
height: 22px;
width: 22px;
margin-right: 16px;
border-radius: 50%;
border: 1px solid rgb(255, 255, 255);
background: rgb(39, 40, 42);
color: rgb(255, 255, 255);
font-size: 13px;
text-align: center;
}
.input {
border: 1px solid #ced4da;
border-radius: 2px;
overflow-y: hidden;
padding: 0.375rem 1.75rem 0.375rem 0.75rem;
}
<div class="wrapping-container">
<div class="progress-indicator">2</div>
<div class="input">Input</div>
</div>
<div class="wrapping-container">
<div class="progress-indicator">3</div>
<div class="input">Input</div>
</div>
The way I would do it is the following:
.wrapping-container {
position: relative;
display: flex;
}
.progress-indicator {
position: relative;
display: inline-block;
margin-bottom: 40px;
color: #fff;
}
.progress-indicator::after {
content: "";
width: 30px;
height: 30px;
background: #000;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 50%;
z-index: -1;
}
.progress-indicator::before {
content: "";
height: 40px;
border: 1px dashed #000;
position: absolute;
left: 50%;
top: -50px;
transform: translateX(-50%);
z-index: -1;
}
.input {
margin-left: 30px;
}
<div class="wrapping-container">
<div class="progress-indicator">2</div>
<div class="input">Input</div>
</div>
<div class="wrapping-container">
<div class="progress-indicator">3</div>
<div class="input">Input</div>
</div>
A simple (if crude) way to achieve this:
.dasher {
border: 1px dashed #ced4da;
max-width: 0px;
min-height: 10px;
margin-left: 10px;
margin-top: -20px;
}
DEMO
.wrapping-container {
display: flex;
align-items: center;
margin-bottom: 20px;
}
.progress-indicator {
height: 22px;
width: 22px;
margin-right: 16px;
border-radius: 50%;
border: 1px solid rgb(255, 255, 255);
background: rgb(39, 40, 42);
color: rgb(255, 255, 255);
font-size: 13px;
text-align: center;
}
.input {
border: 1px solid #ced4da;
border-radius: 2px;
overflow-y: hidden;
padding: 0.375rem 1.75rem 0.375rem 0.75rem;
}
.dasher {
border: 1px dashed #ced4da;
max-width: 0px;
min-height: 10px;
margin-left: 10px;
margin-top: -20px;
}
<div class="wrapping-container">
<div class="progress-indicator">2</div>
<div class="input">Input</div>
</div>
<div class="dasher"></div>
<div class="wrapping-container">
<div class="progress-indicator">3</div>
<div class="input">Input</div>
</div>
Should give you this:
I added a container and a single dashed block that will go directly through all the height wrapping-container:
.container{
position:relative;
}
.border-dash{
position: absolute;
top: 15px;
left: 11px;
border-left: 1px dashed black;
height:calc(100% - 25px);
width: 1px;
display: block;
z-index: -1;
}
DEMO
.wrapping-container {
display: flex;
align-items: center;
margin-bottom: 20px;
}
.progress-indicator {
height: 22px;
width: 22px;
margin-right: 16px;
border-radius: 50%;
border: 1px solid rgb(255, 255, 255);
background: rgb(39, 40, 42);
color: rgb(255, 255, 255);
font-size: 13px;
text-align: center;
}
.input {
border: 1px solid #ced4da;
border-radius: 2px;
overflow-y: hidden;
padding: 0.375rem 1.75rem 0.375rem 0.75rem;
}
.container{
position:relative;
}
.border-dash{
position: absolute;
top: 15px;
left: 11px;
border-left: 1px dashed black;
height:calc(100% - 25px);
width: 1px;
display: block;
z-index: -1;
}
<div class="container">
<span class="border-dash"></span>
<div class="wrapping-container">
<div class="progress-indicator">2</div>
<div class="input">Input</div>
</div>
<div class="wrapping-container">
<div class="progress-indicator">3</div>
<div class="input">Input</div>
</div>
<div class="wrapping-container">
<div class="progress-indicator">4</div>
<div class="input">Input</div>
</div>
</div>
I want to create a shape using CSS. The only problem I am facing is the alignment of semicircle with the border of rectangle which is not working out properly.
I am attaching the image of what I have done till now. Can anybody help me out to fix these alignment problem. Thank you.
body {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-color: white;
}
#talkbubble {
width: 120px;
height: 80px;
border: 4px solid #4C4C4C;
position: relative;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
}
#talkbubble:before {
content: "";
position: absolute;
top: 42%;
left: -11.6px;
width: 30px;
height: 15px;
border: 4px solid #4C4C4C;
border-bottom: none;
border-top-left-radius: 30px;
border-top-right-radius: 30px;
background-color: white;
transform: rotate(90deg);
box-sizing: border-box;
}
#talkbubble:after {
content: "";
position: absolute;
top: 42%;
right: -12px;
width: 30px;
height: 15px;
border: 4px solid #4C4C4C;
border-bottom: none;
border-top-left-radius: 30px;
border-top-right-radius: 30px;
background-color: white;
transform: rotate(270deg);
box-sizing: border-box;
}
<div id="talkbubble"></div>
I would do it differently with one element:
.ticket {
width:300px;
height:200px;
border-radius:20px;
border:8px solid;
background:
radial-gradient(circle 38px at right,#000 95%,#0000),
radial-gradient(circle 38px at left ,#000 95%,#0000);
background-origin:border-box;
-webkit-mask:
radial-gradient(circle 30px at right,#0000 95%,#000) right,
radial-gradient(circle 30px at left ,#0000 95%,#000) left;
-webkit-mask-size:51% 100%;
-webkit-mask-repeat:no-repeat;
}
<div class="ticket"></div>
You could add overflow hidden in case, and a full circle?
.ticket-outer {
overflow: hidden;
height: 150px;
width: 300px;
margin: 50px auto;
}
.ticket {
border: 5px solid #000;
border-radius: 20px;
height: 150px;
width: 300px;
position: relative;
box-sizing: border-box;
}
.ticket::before,
.ticket::after {
content: '';
width: 50px;
height: 50px;
border: 5px solid #000;
background: #fff;
border-radius: 50%;
position: absolute;
top: 50%;
left: -30px;
transform: translateY(-50%);
z-index: 2;
}
.ticket::after {
left: auto;
right: -30px;
}
<div class="ticket-outer">
<div class="ticket"></div>
</div>
I want to create a shape using CSS. The only problem I am facing is the alignment of semicircle with the border of rectangle which is not working out properly.
I am attaching the image of what I have done till now. Can anybody help me out to fix these alignment problem. Thank you.
body {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-color: white;
}
#talkbubble {
width: 120px;
height: 80px;
border: 4px solid #4C4C4C;
position: relative;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
}
#talkbubble:before {
content: "";
position: absolute;
top: 42%;
left: -11.6px;
width: 30px;
height: 15px;
border: 4px solid #4C4C4C;
border-bottom: none;
border-top-left-radius: 30px;
border-top-right-radius: 30px;
background-color: white;
transform: rotate(90deg);
box-sizing: border-box;
}
#talkbubble:after {
content: "";
position: absolute;
top: 42%;
right: -12px;
width: 30px;
height: 15px;
border: 4px solid #4C4C4C;
border-bottom: none;
border-top-left-radius: 30px;
border-top-right-radius: 30px;
background-color: white;
transform: rotate(270deg);
box-sizing: border-box;
}
<div id="talkbubble"></div>
I would do it differently with one element:
.ticket {
width:300px;
height:200px;
border-radius:20px;
border:8px solid;
background:
radial-gradient(circle 38px at right,#000 95%,#0000),
radial-gradient(circle 38px at left ,#000 95%,#0000);
background-origin:border-box;
-webkit-mask:
radial-gradient(circle 30px at right,#0000 95%,#000) right,
radial-gradient(circle 30px at left ,#0000 95%,#000) left;
-webkit-mask-size:51% 100%;
-webkit-mask-repeat:no-repeat;
}
<div class="ticket"></div>
You could add overflow hidden in case, and a full circle?
.ticket-outer {
overflow: hidden;
height: 150px;
width: 300px;
margin: 50px auto;
}
.ticket {
border: 5px solid #000;
border-radius: 20px;
height: 150px;
width: 300px;
position: relative;
box-sizing: border-box;
}
.ticket::before,
.ticket::after {
content: '';
width: 50px;
height: 50px;
border: 5px solid #000;
background: #fff;
border-radius: 50%;
position: absolute;
top: 50%;
left: -30px;
transform: translateY(-50%);
z-index: 2;
}
.ticket::after {
left: auto;
right: -30px;
}
<div class="ticket-outer">
<div class="ticket"></div>
</div>
I wanna achieve the following result by using CSS:
So basically I want the circle to be on top of the button background but behind its border, with the button on top of the background
With the following code I am able to draw a similar button:
.container {
margin-top: 30px;
}
button {
font-size: 20px;
border: 2px solid black;
padding: 8px 20px;
position: relative;
}
.container .circle {
position: absolute;
top: -21px;
right: -21px;
width: 40px;
height: 40px;
-webkit-border-radius: 25px;
-moz-border-radius: 25px;
border-radius: 25px;
background: #4da6ff;
}
<div class="container">
<button>Test Button
<span class="circle"></span>
</button>
</div>
RESULT:
The problem here is that the circle is on top of the button, but also on top of its border.
One idea is to integrate the missing borders inside the circle
.container {
margin-top: 30px;
}
button {
font-size: 20px;
border: 2px solid black;
padding: 8px 20px;
position: relative;
}
button:before {
content: "";
position: absolute;
top: -1px;
right: -1px;
transform:translate(50%,-50%);
width: 40px;
height: 40px;
border-radius: 50%;
background:
linear-gradient(black,black) left /50% 2px,
linear-gradient(black,black) bottom/2px 50%,
#4da6ff;
background-repeat:no-repeat;
}
<div class="container">
<button>Test Button</button>
</div>
Or you can simply consider mix-blend-mode. You have to pay attention to the value used as it will depend on the combination of the colors. In this case, the suitable one is darken
.container {
margin-top: 30px;
}
button {
font-size: 20px;
border: 2px solid black;
padding: 8px 20px;
position: relative;
}
button:before {
content: "";
position: absolute;
top: -1px;
right: -1px;
transform:translate(50%,-50%);
width: 40px;
height: 40px;
border-radius: 50%;
background: #4da6ff;
mix-blend-mode:darken;
}
<div class="container">
<button>Test Button</button>
</div>
A third way more fancy with only backgrounds:
button {
font-size: 20px;
border:0 solid transparent;
border-top-width:24px;
border-right-width:24px;
padding: 8px 20px;
background:
linear-gradient(black,black) top /100% 2px,
linear-gradient(black,black) bottom/100% 2px,
linear-gradient(black,black) left /2px 100%,
linear-gradient(black,black) right /2px 100%,
radial-gradient(circle, #4da6ff 19px,transparent 20px) left bottom/200% 200% padding-box border-box,
#e2e2e6 padding-box;
background-repeat:no-repeat;
}
<div class="container">
<button>Test Button</button>
</div>
Another idea is to place the circle behind the element and cut the background:
.container {
margin-top: 30px;
position:relative;
z-index:0;
}
button {
font-size: 20px;
border: 2px solid black;
padding: 8px 20px;
position: relative;
background:radial-gradient(circle at top right,transparent 19px,#e2e2e6 20px);
}
button:before {
content: "";
position: absolute;
z-index:-1;
top: -1px;
right: -1px;
transform:translate(50%,-50%);
width: 40px;
height: 40px;
border-radius: 50%;
background:#4da6ff;
}
<div class="container">
<button>Test Button</button>
</div>
Use a pseudo element (::after) to draw the border above the circle:
.container {
margin-top: 30px;
}
button {
position: relative;
font-size: 20px;
border: none;
padding: 8px 20px;
}
button::before {
position: absolute;
top: -20px;
right: -20px;
width: 40px;
height: 40px;
border-radius: 25px;
background: #4da6ff;
content: '';
}
button::after {
position: absolute;
top: -2px;
right: -2px;
bottom: -2px;
left: -2px;
border: 2px solid black;
content: '';
}
<div class="container">
<button>Test Button</button>
</div>
I wanna achieve the following result by using CSS:
So basically I want the circle to be on top of the button background but behind its border, with the button on top of the background
With the following code I am able to draw a similar button:
.container {
margin-top: 30px;
}
button {
font-size: 20px;
border: 2px solid black;
padding: 8px 20px;
position: relative;
}
.container .circle {
position: absolute;
top: -21px;
right: -21px;
width: 40px;
height: 40px;
-webkit-border-radius: 25px;
-moz-border-radius: 25px;
border-radius: 25px;
background: #4da6ff;
}
<div class="container">
<button>Test Button
<span class="circle"></span>
</button>
</div>
RESULT:
The problem here is that the circle is on top of the button, but also on top of its border.
One idea is to integrate the missing borders inside the circle
.container {
margin-top: 30px;
}
button {
font-size: 20px;
border: 2px solid black;
padding: 8px 20px;
position: relative;
}
button:before {
content: "";
position: absolute;
top: -1px;
right: -1px;
transform:translate(50%,-50%);
width: 40px;
height: 40px;
border-radius: 50%;
background:
linear-gradient(black,black) left /50% 2px,
linear-gradient(black,black) bottom/2px 50%,
#4da6ff;
background-repeat:no-repeat;
}
<div class="container">
<button>Test Button</button>
</div>
Or you can simply consider mix-blend-mode. You have to pay attention to the value used as it will depend on the combination of the colors. In this case, the suitable one is darken
.container {
margin-top: 30px;
}
button {
font-size: 20px;
border: 2px solid black;
padding: 8px 20px;
position: relative;
}
button:before {
content: "";
position: absolute;
top: -1px;
right: -1px;
transform:translate(50%,-50%);
width: 40px;
height: 40px;
border-radius: 50%;
background: #4da6ff;
mix-blend-mode:darken;
}
<div class="container">
<button>Test Button</button>
</div>
A third way more fancy with only backgrounds:
button {
font-size: 20px;
border:0 solid transparent;
border-top-width:24px;
border-right-width:24px;
padding: 8px 20px;
background:
linear-gradient(black,black) top /100% 2px,
linear-gradient(black,black) bottom/100% 2px,
linear-gradient(black,black) left /2px 100%,
linear-gradient(black,black) right /2px 100%,
radial-gradient(circle, #4da6ff 19px,transparent 20px) left bottom/200% 200% padding-box border-box,
#e2e2e6 padding-box;
background-repeat:no-repeat;
}
<div class="container">
<button>Test Button</button>
</div>
Another idea is to place the circle behind the element and cut the background:
.container {
margin-top: 30px;
position:relative;
z-index:0;
}
button {
font-size: 20px;
border: 2px solid black;
padding: 8px 20px;
position: relative;
background:radial-gradient(circle at top right,transparent 19px,#e2e2e6 20px);
}
button:before {
content: "";
position: absolute;
z-index:-1;
top: -1px;
right: -1px;
transform:translate(50%,-50%);
width: 40px;
height: 40px;
border-radius: 50%;
background:#4da6ff;
}
<div class="container">
<button>Test Button</button>
</div>
Use a pseudo element (::after) to draw the border above the circle:
.container {
margin-top: 30px;
}
button {
position: relative;
font-size: 20px;
border: none;
padding: 8px 20px;
}
button::before {
position: absolute;
top: -20px;
right: -20px;
width: 40px;
height: 40px;
border-radius: 25px;
background: #4da6ff;
content: '';
}
button::after {
position: absolute;
top: -2px;
right: -2px;
bottom: -2px;
left: -2px;
border: 2px solid black;
content: '';
}
<div class="container">
<button>Test Button</button>
</div>