CSS donut chart with borders only adds border to top - css

I have this fiddle https://jsfiddle.net/kywetbeL/19/ and in only CSS and HTML. I wanted to make a donut chart that had 5 chunks and a border and a small gap between each part.
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.donut-chart {
position: relative;
width: 200px;
height: 200px;
margin: 0 auto 2rem;
border-radius: 100%
}
p.center {
background: #ffffff;
position: absolute;
text-align: center;
font-size: 28px;
top: 0;
left: 0;
bottom: 0;
right: 0;
width: 130px;
height: 130px;
margin: auto;
border-radius: 50%;
line-height: 35px;
padding: 15% 0 0;
}
.portion-block {
border-radius: 50%;
clip: rect(0px, 200px, 200px, 100px);
height: 100%;
position: absolute;
width: 100%;
}
.circle {
border-radius: 50%;
clip: rect(0px, 100px, 200px, 0px);
height: 100%;
position: absolute;
width: 100%;
font-family: monospace;
font-size: 1.5rem;
}
#part1 {
transform: rotate(326deg);
}
#part1 .circle {
background-color: #E64C65;
border-top: 1px solid black;
border-left: 1px solid black;
border-right: 1px solid black;
border-bottom: 1px solid black;
animation: first 1s 1 forwards;
}
#part2 {
transform: rotate(38deg);
}
#part2 .circle {
background-color: #11A8AB;
border-top: 1px solid black;
border-left: 1px solid black;
border-right: 1px solid black;
border-bottom: 1px solid black;
animation: second 1s 1 forwards 1s;
}
#part3 {
transform: rotate(110deg);
}
#part3 .circle {
background-color: #4FC4F6;
border-top: 1px solid black;
border-left: 1px solid black;
border-right: 1px solid black;
border-bottom: 1px solid black;
animation: third 0.5s 1 forwards 2s;
}
#part4 {
transform: rotate(182deg);
}
#part4 .circle {
background-color: #4FC433;
border-top: 1px solid black;
border-left: 1px solid black;
border-right: 1px solid black;
border-bottom: 1px solid black;
animation: fourth 0.5s 1 forwards 3s;
}
#part5 {
transform: rotate(254deg);
}
#part5 .circle {
background-color: #4FC888;
border-top: 1px solid black;
border-left: 1px solid black;
border-right: 1px solid black;
border-bottom: 1px solid black;
animation: fifth 0.5s 1 forwards 4s;
}
/* Animation */
#keyframes first {
from {
transform: rotate(0deg);
}
to {
transform: rotate(68deg);
}
}
#keyframes second {
from {
transform: rotate(0deg);
}
to {
transform: rotate(68deg);
}
}
#keyframes third {
from {
transform: rotate(0deg);
}
to {
transform: rotate(68deg);
}
}
#keyframes fourth {
from {
transform: rotate(0deg);
}
to {
transform: rotate(68deg);
}
}
#keyframes fifth {
from {
transform: rotate(0deg);
}
to {
transform: rotate(68deg);
}
}
<div class="container">
<div class="donut-chart-block block">
<div class="donut-chart">
<div id="part1" class="portion-block">
<div class="circle"></div>
</div>
<div id="part2" class="portion-block">
<div class="circle"></div>
</div>
<div id="part3" class="portion-block">
<div class="circle"></div>
</div>
<div id="part4" class="portion-block">
<div class="circle"></div>
</div>
<div id="part5" class="portion-block">
<div class="circle"></div>
</div>
<p class="center"></p>
</div>
</div>
</div>
I can't seem to get the border around the entire element, only the top.

I would first update your code using my previous answer and then consider a filter to create a border:
.palette {
--g: 10px; /* The gap between shapes*/
--s: 50px; /* the size*/
width: 250px;
aspect-ratio: 1;
display: inline-grid;
filter: drop-shadow(0 0 1px #000) drop-shadow(0 0 0 #000) drop-shadow(0 0 0 #000) drop-shadow(0 0 0 #000)
}
.palette > * {
grid-area: 1/1;
position: relative;
clip-path:polygon(
calc(50% + var(--g)/2) 50%,
calc(50% + var(--g)/2) 0%,
100% 0%,
100% calc(33.745% - var(--g)/2),
50% calc(50% - var(--g)/2));
}
.palette > *:before {
content:"";
position: absolute;
inset: 0;
border-radius: 50%;
border: var(--s) solid #0000;
border-left-color: var(--c);
animation:m 1s linear both var(--d,0s);
}
#keyframes m {
from{transform:rotate(45deg)}
to {transform:rotate(135deg)}
}
.color1 {
transform: rotate(0deg);
--c: red;
}
.color2 {
transform: rotate(72deg);
--c:blue;
--d:1s;
}
.color3 {
transform: rotate(144deg);
--c:orange;
--d:2s;
}
.color4 {
transform: rotate(216deg);
--c:green;
--d:3s;
}
.color5 {
transform: rotate(288deg);
--c:purple;
--d:4s;
}
<div class="palette">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
</div>

Related

CSS/SCSS Custom tooltip effect

Hello guys I'm trying to create a custom tooltip, with a cool hovering effect. I found a code on the internet which does almost what I want. Below is the code
.tooltip {
position: relative;
&__item {
position: absolute;
min-width: 100px;
padding: 20px;
visibility: hidden;
opacity: 0;
background: white;
transition: all .250s cubic-bezier(0, 0, 0.2, 1);
color: #484848;
border: 1px solid #cecece;
border-radius: 3px;
font-weight: 500;
box-shadow: 0 2px 1px #bcbcbc;
z-index: 4;
&:after {
content: "";
display: block;
position: absolute;
width: 0;
height: 0;
border-style: solid;
}
}
&__initiator {
cursor: pointer;
z-index: 5;
}
&[data-direction="bottom"] {
.tooltip__initiator:hover ~ .tooltip__item {
transform: translate3d(-50%, 0, 0);
visibility: visible;
opacity: 1;
}
.tooltip__item {
top: calc(100% + 1em);
left: 50%;
transform: translate3d(-50%, -15px, 0);
&:after {
top: -0.5em;
left: 50%;
transform: translate3d(-50%, 0, 0);
border-width: 0 0.5em 0.5em 0.5em;
border-color: transparent transparent white transparent;
-webkit-filter: drop-shadow(1px 2px 1px #bcbcbc);
filter: drop-shadow(1px -1px 1px #bcbcbc);
}
}
}
}
and here is the result
What I want is that the custom tooltip should be displayed above the component NOT below. I'm new to css/scss, so can a kind person edit the code for me so as to obtain this effect?
UPDATE
This link is where I got the code from. It has a working example.
.tooltip {
position: relative;
}
.tooltip__item {
position: absolute;
min-width: 100px;
padding: 20px;
visibility: hidden;
opacity: 0;
background: white;
transition: all 0.25s cubic-bezier(0, 0, 0.2, 1);
color: #484848;
border: 1px solid #cecece;
border-radius: 3px;
font-weight: 500;
box-shadow: 0 2px 1px #bcbcbc;
z-index: 4;
}
.tooltip__item:after {
content: "";
display: block;
position: absolute;
width: 0;
height: 0;
border-style: solid;
}
.tooltip__initiator {
cursor: pointer;
z-index: 5;
}
.tooltip[data-direction="left"] .tooltip__initiator:hover ~ .tooltip__item {
transform: translate3d(0, -50%, 0);
visibility: visible;
opacity: 1;
}
.tooltip[data-direction="left"] .tooltip__item {
top: 50%;
right: calc(100% + 1em);
transform: translate3d(15px, -50%, 0);
}
.tooltip[data-direction="left"] .tooltip__item:after {
top: 50%;
right: -0.5em;
transform: translate3d(0, -50%, 0);
border-width: 0.5em 0 0.5em 0.5em;
border-color: transparent transparent transparent white;
-webkit-filter: drop-shadow(0px 2px 1px #bcbcbc);
filter: drop-shadow(0px 2px 1px #bcbcbc);
}
.tooltip[data-direction="top"] .tooltip__initiator:hover ~ .tooltip__item, .tooltip[data-direction="bottom"] .tooltip__initiator:hover ~ .tooltip__item {
transform: translate3d(-50%, 0, 0);
visibility: visible;
opacity: 1;
}
.tooltip[data-direction="top"] .tooltip__item, .tooltip[data-direction="bottom"] .tooltip__item {
left: 50%;
transform: translate3d(-50%, -15px, 0);
}
.tooltip[data-direction="top"] .tooltip__item:after, .tooltip[data-direction="bottom"] .tooltip__item:after {
left: 50%;
transform: translate3d(-50%, 0, 0);
}
.tooltip[data-direction="top"] .tooltip__item {
bottom: calc(100% + 1em);
}
.tooltip[data-direction="top"] .tooltip__item:after {
bottom: -0.5em;
border-width: 0.5em 0.5em 0 0.5em;
border-color: white transparent transparent transparent;
filter: drop-shadow(0px 2px 1px #bcbcbc);
-webkit-filter: drop-shadow(0px 2px 1px #bcbcbc);
}
.tooltip[data-direction="bottom"] .tooltip__item {
top: calc(100% + 1em);
}
.tooltip[data-direction="bottom"] .tooltip__item:after {
top: -0.5em;
border-width: 0 0.5em 0.5em 0.5em;
border-color: transparent transparent white transparent;
filter: drop-shadow(0px -1px 1px #bcbcbc);
-webkit-filter: drop-shadow(0px -1px 1px #bcbcbc);
}
.fa.fa-info-circle {
font-size: 38px;
color: #21606b;
}
body {
margin: 0;
min-height: 100vh;
display: flex;
flex-direction: column;
font-family: sans-serif;
background: #dadada;
font-family: 'Roboto', sans-serif;
}
main {
flex: 1 1 100vh;
min-height: 100vh;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-around;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet">
<main>
<!-- tooltip block -->
<div class="tooltip" data-direction="top">
<div class="tooltip__initiator">
<!-- element with tooltip hover call -->
<i class="fa fa-info-circle"></i>
</div>
<div class="tooltip__item">
Hello! I'm a pure css tooltip going up
</div>
</div>
<!-- tooltip block -->
<div class="tooltip" data-direction="bottom">
<div class="tooltip__initiator">
<!-- element with tooltip hover call -->
<i class="fa fa-info-circle"></i>
</div>
<div class="tooltip__item">
Hello! I'm a pure css tooltip going down
</div>
</div>
</main>
Done.
Copy and paste this CSS
&[data-direction="bottom"] {
.tooltip__initiator:hover ~ .tooltip__item {
transform: translate3d(-50%, 0, 0);
visibility: visible;
opacity: 1;
}
.tooltip__item {
bottom: 50px;
left: 50%;
transform: translate3d(-50%, -15px, 0);
&:after {
top: 100%;
left: 45%;
transform: translate3d(-40%, 0, 0);
border-width: 0 0.5em 0.5em 0.5em;
border-color: transparent transparent white transparent;
transform:rotate(180deg);
-webkit-filter: drop-shadow(1px 2px 1px #bcbcbc);
filter: drop-shadow(1px -1px 1px #bcbcbc);
}
}
}
I would add "top" data-directio. You need to change to location of the tooltip by altering the top value. Also you need to change the direction and location of the small arrow by changing the :after
top -> bottom
and the border colors
border-color: white transparent white transparent;
and shadow:
filter: drop-shadow(-1px 1px 1px #bcbcbc);
Here's the full code:
&[data-direction="top"] {
.tooltip__initiator:hover ~ .tooltip__item {
transform: translate3d(-50%, 0, 0);
visibility: visible;
opacity: 1;
}
.tooltip__item {
top: calc(-200% - 2em);
left: 50%;
transform: translate3d(-50%, -15px, 0);
&:after {
bottom: -0.5em;
left: 50%;
transform: translate3d(-50%, 0, 0);
border-width: 0.5em 0.5em 0 0.5em;
border-color: white transparent white transparent;
-webkit-filter: drop-shadow(1px 2px 1px #bcbcbc);
filter: drop-shadow(-1px 1px 1px #bcbcbc);
}
}
}
And the example is here

Product Customization for E-Commerce website

I am planning to create a online furniture e-commerce website.
I currently having some product customization page option such as color, types of woods and the height and width as well as some add-on such as mirror and some logo.
Is it possible I code the way which when the user select certain customization option such as the color, and the images showed in the product customization page will update accordingly.
For example, the images showed in the page is a cupboard which is brown color, but when the user choose blue color, the cupboard color will be updated into blue cupboard. Then, if user want to add another mirror into cupboard, then the images will be updated become blue cupboard with mirror.
Any article or tutorial related to these fields can i refer to?
Roxas, I've created you a code snippet you can click on the run snippet button below to see the code performing what you are trying to achieve
$(document).ready(function(){
$(".red-circle").click(function(){
$(".color").addClass("red");
$(".color").removeClass("blue");
$(".color").removeClass("green");
});
$(".blue-circle").click(function(){
$(".color").addClass("blue");
$(".color").removeClass("red");
$(".color").removeClass("green");
});
$(".green-circle").click(function(){
$(".color").addClass("green");
$(".color").removeClass("red");
$(".color").removeClass("blue");
});
$(".circle-pick").click(function(){
$(".color").addClass("circle");
$(".color").removeClass("star");
$(".color").removeClass("square");
});
$(".square-pick").click(function(){
$(".color").addClass("square");
$(".color").removeClass("star");
$(".color").removeClass("circle");
});
$(".star-pick").click(function(){
$(".color").addClass("star");
$(".color").removeClass("square");
$(".color").removeClass("circle");
});
});
.red-circle
{
background: red;
border-radius: 100px;
height: 20px;
width: 20px;
float: left;
margin-right: 5px;
}
.blue-circle
{
background: blue;
border-radius: 100px;
height: 20px;
width: 20px;
float: left;
margin-right: 5px;
}
.green-circle
{
background: green;
border-radius: 100px;
height: 20px;
width: 20px;
float: left;
margin-right: 5px;
}
.color
{
background: black;
}
.red
{
background: red;
}
.blue
{
background: blue;
}
.green
{
background: green;
}
.color
{
width: 100px;
height: 100px;
border-radius: 0;
display: block;
margin: 0 auto;
}
h2
{
text-align: center;
}
.square-pick, .circle-pick
{
background:black;
height: 20px;
width: 20px;
margin-right: 5px;
float: left;
}
.square, .square-pick
{
border-radius: 0;
}
.circle, .circle-pick
{
border-radius: 100px;
}
.color.star, .color.star:after, .color.star:before
{
border-bottom-color: black;
background: transparent;
}
.red.star, .red.star:after, .red.star:before
{
border-bottom-color: red;
background: transparent;
}
.blue.star, .blue.star:after, .blue.star:before
{
border-bottom-color: blue;
background: transparent;
}
.green.star, .green.star:after, .green.star:before
{
border-bottom-color: green;
background: transparent;
}
.star {
// margin: 50px 0;
position: relative;
text-align: center;
display: block;
color: black;
width: 0px;
height: 0px;
border-right: 50px solid transparent;
border-bottom: 35px solid;
border-left: 50px solid transparent;
-moz-transform: rotate(35deg);
-webkit-transform: rotate(35deg);
-ms-transform: rotate(35deg);
-o-transform: rotate(35deg);
}
.star:before {
border-bottom: 40px solid;
border-left: 15px solid transparent;
border-right: 15px solid transparent;
position: absolute;
height: 0;
width: 0;
top: -23px;
left: -33px;
display: block;
content: '';
-webkit-transform: rotate(-35deg);
-moz-transform: rotate(-35deg);
-ms-transform: rotate(-35deg);
-o-transform: rotate(-35deg);
}
.star:after {
position: absolute;
display: block;
color: red;
top: 3px;
left: -53px;
width: 0px;
height: 0px;
border-right: 50px solid transparent;
border-bottom: 35px solid;
border-left: 50px solid transparent;
-webkit-transform: rotate(-70deg);
-moz-transform: rotate(-70deg);
-ms-transform: rotate(-70deg);
-o-transform: rotate(-70deg);
content: '';
}
.star-pick {
float: left;
margin: 10px 0;
position: relative;
display: block;
color: red;
width: 0px;
height: 0px;
border-right: 20px solid transparent;
border-bottom: 14px solid black;
border-left: 20px solid transparent;
-moz-transform: rotate(35deg);
-webkit-transform: rotate(35deg);
-ms-transform: rotate(35deg);
-o-transform: rotate(35deg);
}
.star-pick:before {
border-bottom: 16px solid black;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
position: absolute;
height: 0;
width: 0;
top: -9px;
left: -13px;
display: block;
content: '';
-webkit-transform: rotate(-35deg);
-moz-transform: rotate(-35deg);
-ms-transform: rotate(-35deg);
-o-transform: rotate(-35deg);
}
.star-pick:after {
position: absolute;
display: block;
color: black;
top: 3px;
left: -21px;
width: 0px;
height: 0px;
border-right: 20px solid transparent;
border-bottom: 14px solid black;
border-left: 20px solid transparent;
-webkit-transform: rotate(-70deg);
-moz-transform: rotate(-70deg);
-ms-transform: rotate(-70deg);
-o-transform: rotate(-70deg);
content: '';
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h2>Color Box</h2>
<div class="color" ></div>
<br/>
<p>Click a color</p>
<div class="red-circle"></div>
<div class="blue-circle"></div>
<div class="green-circle"></div>
<br/>
<p>Click a shape</p>
<div class="circle-pick"></div>
<div class="square-pick"></div>
<div class="star-pick"></div>

CSS loader spinner to add white divider between the donut parts

I am trying to add some white dividers between blue and black. Please see the GIF animation below. Please edit my CSS in jsbin to mimic the same animation in the image. I only need CSS version of this animation without SVG or JS.
.spinner {
height:60px;
width:60px;
animation: rotation 10s infinite linear;
border-left:7px solid rgba(0,0,0,1);
border-right:7px solid rgba(0,0,0,1);
border-bottom:7px solid rgba(0,174,239,1);
border-top:7px solid rgba(0,174,239,1);
border-radius: 100%;
}
#keyframes rotation {
from {transform: rotate(0deg);}
to {transform: rotate(359deg);}
}
http://jsbin.com/ziniwexuwi/edit?html,css,output
Please check the updated code. I hope it works well for you.
.spinner {
height:62px;
width:62px;
border-left:7px solid rgba(0,0,0,1);
border-right:7px solid rgba(0,0,0,1);
border-bottom:7px solid rgba(0,174,239,1);
border-top:7px solid rgba(0,174,239,1);
border-radius: 100%;
border-spacing: 1px;
position: relative;
animation: rotation 1s infinite linear;
}
.spinner span {
height: 7px;
width: 2px;
background: #fff;
position: absolute;
z-index: 1;
}
.spinner .a {
left: 6px;
top:3px;
transform: rotate(-47deg);
}
.spinner .b {
right: 6px;
top:3px;
transform: rotate(47deg);
}
.spinner .c {
left: 6px;
bottom: 3px;
transform: rotate(47deg);
}
.spinner .d {
right: 6px;
bottom: 3px;
transform: rotate(-47deg);
}
#keyframes rotation {
from {transform: rotate(0deg);}
to {transform: rotate(359deg);}
}
<div class="spinner">
<span class="a"></span>
<span class="b"></span>
<span class="c"></span>
<span class="d"></span>
</div>
Check this for your perfect requirement:
.loaderborder {
position: relative;
display: inline-block;
border: 16px solid #87ceeb;
border-radius: 50%;
border-top: 16px solid #000;
border-right: 16px solid #87ceeb;
border-bottom: 16px solid #000;
width: 100px;
height: 100px;
-webkit-animation: loaderborder 2.5s linear infinite;
animation: loaderborder 2.5s linear infinite;
}
.loaderborder:before{
content: '';
border-left: 16px solid #fff;
width: 0;
height: 9px;
border-radius: 0%;
display: inline-block;
transform: rotate(50deg);
}
.loaderborder:after{
content: '';
border-right: 16px solid #fff;
width: 0;
height: 9px;
border-radius: 0;
display: inline-block;
transform: rotate(-52deg);
position: absolute;
right: 0;
top: 5px;
}
.loaderborder span{
display: inline-block;
}
.loaderborder span:before{
content: '';
border-top: 16px solid #fff;
width: 10px;
height: 9px;
border-radius: 0%;
display: inline-block;
transform: rotate(50deg);
position: absolute;
z-index: 999;
top: 78px;
left: -2px;
}
.loaderborder span:after{
content: '';
border-bottom: 16px solid #fff;
width: 9px;
height: 9px;
border-radius: 0;
display: inline-block;
transform: rotate(-52deg);
position: absolute;
z-index: 9999;
top: 73px;
left: 85px;
}
#-webkit-keyframes loaderborder {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
#keyframes loaderborder {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
<div class="loaderborder"><span></span></div>
You can also check this Fiddle

How to make angled div with css only [duplicate]

I'm building a wizard-like ordering process where I have this menu:
The active page is colored green (in this case, Model).
How does one make this arrow using only CSS?:
At the moment i'm achieving my goal by using several divs and images:
<div class="menuItem">
<div></div> <!-- The left image -->
<div>Varianten</div>
<div></div> <!-- The right image -->
</div>
The left image:
The right image:
I found a SO answer which does part of this:
Arrow Box with CSS, however i'm having trouble with the indent at the left.
If you have a better idea about how to do this, please let me know!
If the space between the arrows does not need to be transparent (it is solid color) you can use the :before and :after to create the edges (without new elements in DOM)
Basically, it creates rotated squares with the borders we want and places them accordingly
#flowBoxes {
margin:auto;
padding:20px;
min-width:700px;
}
#flowBoxes div {
display:inline-block;
position:relative;
height:25px;
line-height:25px;
padding:0 20px;
border:1px solid #ccc;
margin-right:2px;
background-color:white;
}
#flowBoxes div.right:after{
content:'';
border-top:1px solid #ccc;
border-right:1px solid #ccc;
width:18px;
height:18px;
position:absolute;
right:0;
top:-1px;
background-color:white;
z-index:150;
-webkit-transform: translate(10px,4px) rotate(45deg);
-moz-transform: translate(10px,4px) rotate(45deg);
-ms-transform: translate(10px,4px) rotate(45deg);
-o-transform: translate(10px,4px) rotate(20deg);
transform: translate(10px,4px) rotate(45deg);
}
#flowBoxes div.left:before{
content:'';
border-top:1px solid #ccc;
border-right:1px solid #ccc;
width:18px;
height:18px;
position:absolute;
left:0;
top:-1px;
background-color:white;
z-index:50;
-webkit-transform: translate(-10px,4px) rotate(45deg);
-moz-transform: translate(-10px,4px) rotate(45deg);
-ms-transform: translate(-10px,4px) rotate(45deg);
-o-transform: translate(-10px,4px) rotate(20deg);
transform: translate(-10px,4px) rotate(45deg);
}
#flowBoxes .active{
background-color:green;
color:white;
}
#flowBoxes div.active:after{
background-color:green;
}
<div id="flowBoxes">
<div class="right">Diersoort / I&R</div>
<div class="left right active">Model</div>
<div class="left right">Varianten</div>
<div class="left right">Bedrukkingen</div>
<div class="left">Bevestiging</div>
</div>
Here is an alternate approach to the whole thing using CSS3 features. One advantage of using this method (and one of the main reasons for adding a separate answer) is that the space in between the arrows can be transparent.
Basically the implementation is as follows:
There is one div for each step/item and it contains the text that needs to be displayed. Let us say the height of this div is x (50px in this example).
Two pseudo-elements (:before and :after) are created with their width the same as the parent div and height as half (x/2) of the parent. The :before element has no border-bottom whereas the :after element has no border-top to avoid a line appearing in the middle of the shape (parallel to x-axis).
These two pseudo-elements are then skew transformed in opposite directions and are positioned in such a way that they are directly below each other and thus ends up forming the required shape.
The pseudo-elements are assigned a negative z-index to push them to be behind the parent div (and therefore its text).
The first-child and the last-child elements are modified slightly (left position, border of pseudo-elements, background and border of parent div) to achieve the straight sides.
We can add an active class for active elements and hover effects also to the shapes like in the below sample.
.steps {
height: 50px;
width: 150px;
text-align: center;
line-height: 50px;
position: relative;
margin: 10px 0px 10px 20px;
display: inline-block;
}
.steps:before,
.steps:after {
content: '';
position: absolute;
left: 0px;
width: 150px;
height: 25px;
z-index: -1;
}
.steps:before {
top: -2px;
border-top: 2px solid blue;
border-right: 2px solid blue;
border-left: 2px solid blue;
background: lightblue;
-moz-transform: skew(30deg);
-webkit-transform: skew(30deg);
transform: skew(30deg);
}
.steps:after {
bottom: -2px;
border-left: 2px solid blue;
border-right: 2px solid blue;
border-bottom: 2px solid blue;
background: lightblue;
-moz-transform: skew(-30deg);
-webkit-transform: skew(-30deg);
transform: skew(-30deg);
}
.steps:last-child {
background: lightblue;
border-right: 2px solid blue;
border-top: 2px solid blue;
border-bottom: 2px solid blue;
margin-left: 38px;
}
.steps:first-child {
background: lightblue;
border-left: 2px solid blue;
border-top: 2px solid blue;
border-bottom: 2px solid blue;
margin-right: 18px;
}
.steps:first-child:before,
.steps:first-child:after {
left: 18px;
}
.steps:last-child:before,
.steps:last-child:after {
left: -18px;
}
/* Hover Styles */
.steps:first-child:hover,
.steps:last-child:hover,
.steps:hover:before,
.steps:hover:after {
background: lightgreen;
}
.steps:first-child:hover {
border-left: 2px solid green;
}
.steps:last-child:hover {
border-right: 2px solid green;
}
.steps:hover:before {
border-top: 2px solid green;
border-right: 2px solid green;
border-left: 2px solid green;
}
.steps:hover:after {
border-left: 2px solid green;
border-right: 2px solid green;
border-bottom: 2px solid green;
}
.steps:first-child:hover,
.steps:last-child:hover {
border-top: 2px solid green;
border-bottom: 2px solid green;
}
/* Active Styles */
.active:first-child,
.active:last-child,
.active:before,
.active:after{
background: bisque;
}
.active:first-child{
border-left: 2px solid red;
}
.active:last-child{
border-right: 2px solid red;
}
.active:before{
border-top: 2px solid red;
border-right: 2px solid red;
border-left: 2px solid red;
}
.active:after{
border-left: 2px solid red;
border-right: 2px solid red;
border-bottom: 2px solid red;
}
.active:first-child, .active:last-child{
border-top: 2px solid red;
border-bottom: 2px solid red;
}
/* Just for creating a non solid color background */
body{
height: 200px;
background: -webkit-radial-gradient(center, ellipse, #400, #100);
background: -moz-radial-gradient(center, ellipse, #400, #100);
background: radial-gradient(center, ellipse, #400, #100);
}
<div class='steps-container'>
<div class='steps'>1. Step 1</div>
<div class='steps active'>2. Step 2</div>
<div class='steps'>3. Step 3</div>
</div>
Note: The hover in the above snippet doesn't work when hovering on the right tip of the first-child or the left tip of the last-child because of z-index issues. If you need seamless hover functionality then using a span inside the .steps element like in the below snippet would solve it. (Thanks to The Pragmatick for pointing this out).
.steps {
height: 50px;
width: 150px;
text-align: center;
line-height: 50px;
position: relative;
margin: 10px 0px 10px 20px;
display: inline-block;
}
.steps span {
position: relative;
z-index: 2;
}
.steps:before,
.steps:after {
content: '';
position: absolute;
left: 0px;
width: 150px;
height: 25px;
}
.steps:before {
top: -2px;
border-top: 2px solid blue;
border-right: 2px solid blue;
border-left: 2px solid blue;
background: lightblue;
-moz-transform: skew(30deg);
-webkit-transform: skew(30deg);
transform: skew(30deg);
}
.steps:after {
bottom: -2px;
border-left: 2px solid blue;
border-right: 2px solid blue;
border-bottom: 2px solid blue;
background: lightblue;
-moz-transform: skew(-30deg);
-webkit-transform: skew(-30deg);
transform: skew(-30deg);
}
.steps:first-child:before,
.steps:first-child:after {
border-left: none;
}
.steps:last-child:before,
.steps:last-child:after {
border-right: none;
}
.steps:last-child {
background: lightblue;
border-right: 2px solid blue;
border-top: 2px solid blue;
border-bottom: 2px solid blue;
margin-left: 38px;
}
.steps:first-child {
background: lightblue;
border-left: 2px solid blue;
border-top: 2px solid blue;
border-bottom: 2px solid blue;
margin-right: 18px;
}
.steps:first-child:before,
.steps:first-child:after {
left: 18px;
}
.steps:last-child:before,
.steps:last-child:after {
left: -18px;
}
/* Hover Styles */
.steps:first-child:hover,
.steps:last-child:hover,
.steps:hover:before,
.steps:hover:after {
background: lightgreen;
}
.steps:first-child:hover {
border-left: 2px solid green;
}
.steps:last-child:hover {
border-right: 2px solid green;
}
.steps:hover:before {
border-top: 2px solid green;
border-right: 2px solid green;
border-left: 2px solid green;
}
.steps:hover:after {
border-left: 2px solid green;
border-right: 2px solid green;
border-bottom: 2px solid green;
}
.steps:first-child:hover,
.steps:last-child:hover {
border-top: 2px solid green;
border-bottom: 2px solid green;
}
.steps:first-child:hover:before,
.steps:first-child:hover:after {
border-left: none;
}
.steps:last-child:hover:before,
.steps:last-child:hover:after {
border-right: none;
}
/* Active Styles */
.active:first-child,
.active:last-child,
.active:before,
.active:after {
background: bisque;
}
.active:first-child {
border-left: 2px solid red;
}
.active:last-child {
border-right: 2px solid red;
}
.active:before {
border-top: 2px solid red;
border-right: 2px solid red;
border-left: 2px solid red;
}
.active:after {
border-left: 2px solid red;
border-right: 2px solid red;
border-bottom: 2px solid red;
}
.active:first-child,
.active:last-child {
border-top: 2px solid red;
border-bottom: 2px solid red;
}
/* Just for creating a non solid color background */
body {
height: 200px;
background: -webkit-radial-gradient(center, ellipse, #400, #100);
background: -moz-radial-gradient(center, ellipse, #400, #100);
background: radial-gradient(center, ellipse, #400, #100);
}
<div class='steps-container'>
<div class='steps'>
<span>1. Step 1</span>
</div>
<div class='steps active'>
<span>2. Step 2</span>
</div>
<div class='steps'>
<span>3. Step 3</span>
</div>
</div>
Screenshot: (with the hover on second item)
Responsive Implementation with Transparent Background:
For a responsive version of the progress tracker bar with semi-transparent boxes, visit this pen. The width of each step/item is assigned in such a way that their sum is always 100% of the available width and each itemis always of the same size as the others.
JavaScript is used for the following features: (All these features are value-add and can be removed depending on the needs. Note that when the JS is removed, the corresponding CSS properties should be put into the CSS file.)
Automatically adjust the width of each item depending on the no. of items that are present in the bar
Automatically adjust the width of each item when the window is resized
Automatically adjust the appearance of the items when the height of the bar is increased or decreased by using the slider.
Here's some great arrows for you
html{
background-color:red;
}
div#page {
padding-bottom: 40px;
padding-top: 40px;
text-align: center;
z-index: 1;
position: relative;
}
div.diamond, div.ribbon, div.right-arrow, div.left-arrow {
display: inline-block;
color: #FFFFFF;
font-size: 22px;
line-height: 38px;
margin: 15px 0;
position: relative;
width: 200px;
}
div.diamond:before, div.diamond:after, div.ribbon:before, div.ribbon:after, div.right-arrow:before, div.right-arrow:after, div.left-arrow:before, div.left-arrow:after {
content:"";
border-style: solid;
border-width: 0;
height: 0;
position: absolute;
width: 0;
}
div.diamond {
background-color: #CCCCCC;
}
div.diamond:after, div.diamond:before {
border-color: transparent #CCCCCC;
}
div.diamond:before {
left: -19px;
border-width: 19px 19px 19px 0;
}
div.diamond:after {
right: -19px;
border-width: 19px 0 19px 19px;
}
div.ribbon {
background-color: #CCCCCC;
}
div.ribbon:before, div.ribbon:after {
top: 6px;
z-index: -15;
}
div.ribbon:before {
border-color: #B2B2B2 #B2B2B2 #B2B2B2 transparent;
border-width: 19px;
left: -25px;
}
div.ribbon:after {
border-color: #B2B2B2 transparent #B2B2B2 #B2B2B2;
border-width: 19px;
right: -25px;
}
div.right-arrow {
background-color: #CCCCCC;
}
div.right-arrow:after, div.right-arrow:before {
border-width: 19px 0 19px 19px;
}
div.right-arrow:before {
border-color: #CCCCCC transparent;
left: -19px;
}
div.right-arrow:after {
border-color: transparent #CCCCCC;
right: -19px;
}
div.left-arrow {
background-color: #CCCCCC;
}
div.left-arrow:after, div.left-arrow:before {
border-width: 19px 19px 19px 0;
}
div.left-arrow:before {
border-color: transparent #CCCCCC;
left: -19px;
}
div.left-arrow:after {
border-color: #CCCCCC transparent;
right: -19px;
}
<div id="page">
<div class="diamond">Diamond</div>
<br>
<div class="ribbon">Ribbon</div>
<br>
<div class="right-arrow">Right arrow</div>
<br>
<div class="left-arrow">Left arrow</div>
</div>
SOURCE
Note
this also allows gradient backgrounds/etc
For other shapes, I saw this codepen the other day, too
If you want transparent spaces between tabs, Harry's current answer is they way to go.
But if you want to remove hover issues, you can try the following. It uses box-shadow for pseudo-elements instead of background with solid colour.
The same effect is achievable using border: _px inset #___ ;
.li {
height: 50px;
width: 120px;
background: #F5FBF1;
display: inline-block;
position: relative;
margin-left: 30px;
line-height: 50px;
color: black;
font-family: sans-serif;
text-align: center;
}
.li:before, .li:after {
content: '';
left: -15px;
position: absolute;
height: 23px;
width: 132px;
border-left: 2px solid black;
border-right: 2px solid black;
}
.li:before {
border-top: 2px solid black;
-webkit-transform-origin: 0% 0%;
-moz-transform-origin: 0% 0%;
-ms-transform-origin: 0% 0%;
transform-origin: 0% 0%;
-webkit-transform: skewX(30deg);
-moz-transform: skewX(30deg);
-ms-transform: skewX(30deg);
transform: skewX(30deg);
top: 0;
box-shadow: inset 0 8px 0 8px #F5FBF1, inset -6px 8px 0 8px #F5FBF1;
}
.li:after {
border-bottom: 2px solid black;
-webkit-transform-origin: 0% 100%;
-moz-transform-origin: 0% 100%;
-ms-transform-origin: 0% 100%;
transform-origin: 0% 100%;
-webkit-transform: skewX(-30deg);
-moz-transform: skewX(-30deg);
-ms-transform: skewX(-30deg);
transform: skewX(-30deg);
bottom: 0;
box-shadow: inset 0 -8px 0 8px #F5FBF1, inset -6px -8px 0 8px #F5FBF1;
}
.li:hover {
background: #C0EBA4;
}
.li:hover:before {
box-shadow: inset 0 8px 0 8px #C0EBA4, inset -6px 8px 0 8px #C0EBA4;
}
.li:hover:after {
box-shadow: inset 0 -8px 0 8px #C0EBA4, inset -6px -8px 0 8px #C0EBA4;
}
<div class="li">ONE</div>
<div class="li">TWO</div>
<div class="li">THREE</div>
<div class="li">FOUR</div>
<div class="li">FIVE</div>
FIDDLE
Final version
You can hover it seamlessly. It includes flat edges of first and last tabs.
.li {
height: 50px;
width: 100px;
padding-left: 20px;
background: #F5FBF1;
display: inline-block;
position: relative;
margin-left: 20px;
line-height: 50px;
font-family: sans-serif;
font-size: 15px;
}
.li:before, .li:after {
content: '';
left: -15px;
position: absolute;
height: 23px;
width: 132px;
border-left: 2px solid black;
border-right: 2px solid black;
}
.li:before {
border-top: 2px solid black;
-webkit-transform-origin: 0% 0%;
-moz-transform-origin: 0% 0%;
-ms-transform-origin: 0% 0%;
transform-origin: 0% 0%;
-webkit-transform: skewX(30deg);
-moz-transform: skewX(30deg);
-ms-transform: skewX(30deg);
transform: skewX(30deg);
top: 0;
box-shadow: inset 0 8px 0 8px #F5FBF1, inset -6px 8px 0 8px #F5FBF1;
}
.li:after {
border-bottom: 2px solid black;
-webkit-transform-origin: 0% 100%;
-moz-transform-origin: 0% 100%;
-ms-transform-origin: 0% 100%;
transform-origin: 0% 100%;
-webkit-transform: skewX(-30deg);
-moz-transform: skewX(-30deg);
-ms-transform: skewX(-30deg);
transform: skewX(-30deg);
bottom: 0;
box-shadow: inset 0 -8px 0 8px #F5FBF1, inset -6px -8px 0 8px #F5FBF1;
}
.li:hover {
background: #C0EBA4;
}
.li:hover:before { box-shadow: inset 0 8px 0 8px #C0EBA4, inset -6px 8px 0 8px #C0EBA4;}
.li:hover:after { box-shadow: inset 0 -8px 0 8px #C0EBA4, inset -6px -8px 0 8px #C0EBA4;}
/*First and Last styles*/
.li:first-of-type {
left: -15px;
box-shadow: 15px 0 0 0 #F5FBF1;
border-left: 2px solid black;
}
.li:first-of-type:before, .li:first-of-type:after {
left: -1px;
width: 135px;
border-left: 0;
}
.li:first-of-type:hover {box-shadow: 15px 0 0 0 #C0EBA4;}
.li:last-of-type {
left: 0px;
width: 115px;
box-shadow: inset -2px 0 0 0 black, inset 0 -2px 0 0 black, inset 0 2px 0 0 black;
border: 0;
}
.li:last-of-type:before, .li:last-of-type:after {
left: -15px;
border-right: 0;
}
.li:last-of-type:hover {background: #C0EBA4;}
<div class="li">Tab one</div>
<div class="li">Tab two</div>
<div class="li">Tab three</div>
<div class="li">Tab four</div>
<div class="li">Tab five</div>
FIDDLE (final)
Output:
Update
See this repl for added top-down support.
Screenshot (top-down)
Initial answer
I set up a repl with an highly customizable example using CSS's clip-path.
See here.
Screenshot
<script>
let arrowWidth = 25;
let stepPaddingX = 25;
let stepPaddingY = 0;
let stepGap = 5;
let height = 50;
$: cssVariables = `--height: ${height}px;--step-gap: ${stepGap}px;--arrow-width: ${arrowWidth}px; --step-padding-x: ${stepPaddingX}px; --step-padding-y: ${stepPaddingY}px`;
let wrap = false;
let wrapWords = true;
let pillStyle = true;
let limitHeight = false;
let autoHeight = true;
const steps = ["Test", "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam", "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam", "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam", "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam"]
</script>
<div class="settings">
<div class="setting">
<label for="setting__height">Height</label>
<input id="setting__height" min="50" max="200" bind:value={height} type="range"/>
</div>
<div class="setting">
<label for="setting__limit-height">Limit height</label>
<input id="setting__limit-height" bind:checked={limitHeight} type="checkbox"/>
</div>
<div class="setting">
<label for="setting__auto-height">Auto-height</label>
<input id="setting__auto-height" bind:checked={autoHeight} type="checkbox"/>
</div>
<div class="setting">
<label for="setting__arrow-width">Arrow width</label>
<input id="setting__arrow-width" bind:value={arrowWidth} type="range"/>
</div>
<div class="setting">
<label for="setting__step-padding-y">Step Padding Y</label>
<input id="setting__step-padding-y" bind:value={stepPaddingY} type="range"/>
</div>
<div class="setting">
<label for="setting__step-padding-x">Step Padding X</label>
<input id="setting__step-padding-x" bind:value={stepPaddingX} type="range"/>
</div>
<div class="setting">
<label for="setting__step-gap">Step Gap</label>
<input id="setting__step-gap" bind:value={stepGap} type="range"/>
</div>
<div class="setting">
<label for="setting__wrap-steps">Wrap steps</label>
<input id="setting__wrap-steps" bind:checked={wrap} type="checkbox"/>
</div>
<div class="setting">
<label for="setting__wrap-words">Wrap words</label>
<input id="setting__wrap-words" bind:checked={wrapWords} type="checkbox"/>
</div>
<div class="setting">
<label for="setting__pill-style">Pill style</label>
<input id="setting__pill-style" bind:checked={pillStyle} type="checkbox"/>
</div>
</div>
<div class="steps" class:wrap class:pillStyle class:limitHeight class:autoHeight style={cssVariables}>
{#each steps as step}
<div class="step" class:wrapWords>
{step}
</div>
{/each}
</div>
<style>
:global(body){
--arrow-width: 25px;
--step-gap: 5px;
--step-padding-x: 10px;
--height: 50px;
}
.settings {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
}
.setting {
display: flex;
align-items: center;
gap: 0.5rem;
border: 1px solid #333;
border-radius: 5px;
padding: 0.25rem;
width: max-content;
}
input {
margin: 0;
}
.steps.pillStyle .step:first-of-type {
border-top-left-radius: 99999px;
border-bottom-left-radius: 99999px;
}
.steps.pillStyle .step:last-of-type {
border-top-right-radius: 99999px;
border-bottom-right-radius: 99999px;
}
.steps {
display: flex;
gap: var(--step-gap);
overflow-x: scroll;
/*scrollbar-width: none;*/
padding: 1rem 0;
}
.steps.wrap {
flex-wrap: wrap;
}
.steps.limitHeight .step{
max-height: 50px;
}
.steps.autoHeight .step{
height: unset;
}
.step:not(.wrapWords) {
white-space: nowrap;
}
.step {
background: #756bea;
width: auto;
height: var(--height);
color: #fff;
transform-style: preserve-3d;
position: relative;
display: flex;
justify-content: center;
align-items: center;
padding: var(--step-padding-y) var(--step-padding-x);
box-sizing: border-box;
}
.step:hover{
background: #4b3fe4;
}
.step:first-child {
/*padding-right: var(--arrow-width);*/
/*padding-left: var(--step-padding-x);*/
}
.step:first-child::after {
content: "";
background: inherit;
position: absolute;
left: 100%;
width: var(--arrow-width);
height: 100%;
clip-path: polygon(calc(100% - var(--arrow-width)) 0%, 100% 50%, calc(100% - var(--arrow-width)) 100%, 0% 100%, 0% 0%);
}
.step:not(:is(:first-child, :last-child))::before{
content: "";
background: inherit;
position: absolute;
right: 100%;
width: var(--arrow-width);
height: 100%;
clip-path: polygon(100% 0%, 100% 100%, 0% 100%, var(--arrow-width) 50%, 0% 0%);
}
.step:not(:is(:first-child, :last-child))::after {
content: "";
background: inherit;
position: absolute;
left: 100%;
width: var(--arrow-width);
height: 100%;
clip-path: polygon(calc(100% - var(--arrow-width)) 0%, 100% 50%, calc(100% - var(--arrow-width)) 100%, 0% 100%, 0% 0%);
}
.step:not(:last-child) {
margin-right: var(--arrow-width);
padding-left: var(--step-padding-x);
}
.step:last-child {
padding-left: var(--step-padding-x);
padding-right: var(--step-padding-x);
}
.step:last-child::before {
content: "";
background: inherit;
position: absolute;
right: 100%;
width: var(--arrow-width);
height: 100%;
clip-path: polygon(100% 0, 100% 100%, 0% 100%, var(--arrow-width) 50%, 0% 0%);
}
</style>
If you want a border for the steps look at this repl
<script>
let wrap = false;
let wrapWords = true;
let pillStyle = true;
let limitHeight = false;
let autoHeight = true;
let lockBorderToGap = false;
let arrowWidth = 25;
let stepPaddingX = 25;
let stepPaddingY = 0;
let stepGap = 5;
let height = 50;
let stepBorderWidth = 5;
$: cssVariables = `--height: ${height}px;--step-gap: ${stepGap}px;--arrow-width: ${arrowWidth}px; --step-padding-x: ${stepPaddingX}px; --step-padding-y: ${stepPaddingY}px; --step-border-width: ${stepBorderWidth}px`;
const steps = ["Test", "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam", "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam", "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam", "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam"]
</script>
<div class="settings">
<div class="setting">
<label for="setting__height">Height</label>
<input id="setting__height" min="50" max="200" bind:value={height} type="range"/>
</div>
<div class="setting">
<label for="setting__limit-height">Limit height</label>
<input id="setting__limit-height" bind:checked={limitHeight} type="checkbox"/>
</div>
<div class="setting">
<label for="setting__auto-height">Auto-height</label>
<input id="setting__auto-height" bind:checked={autoHeight} type="checkbox"/>
</div>
<div class="setting">
<label for="setting__arrow-width">Arrow width</label>
<input id="setting__arrow-width" bind:value={arrowWidth} type="range"/>
</div>
<div class="setting">
<label for="setting__step-padding-y">Step Padding Y</label>
<input id="setting__step-padding-y" bind:value={stepPaddingY} type="range"/>
</div>
<div class="setting">
<label for="setting__step-padding-x">Step Padding X</label>
<input id="setting__step-padding-x" bind:value={stepPaddingX} type="range"/>
</div>
<div class="setting">
<label for="setting__step-gap">Step Gap</label>
<input id="setting__step-gap" bind:value={stepGap} type="range"/>
</div>
<div class="setting">
<label for="setting__lock-border">Lock border to gap</label>
<input id="setting__lock-border" bind:checked={lockBorderToGap} type="checkbox"/>
</div>
<div class="setting">
<label for="setting__wrap-steps">Wrap steps</label>
<input id="setting__wrap-steps" bind:checked={wrap} type="checkbox"/>
</div>
<div class="setting">
<label for="setting__wrap-words">Wrap words</label>
<input id="setting__wrap-words" bind:checked={wrapWords} type="checkbox"/>
</div>
<div class="setting">
<label for="setting__pill-style">Pill style</label>
<input id="setting__pill-style" bind:checked={pillStyle} type="checkbox"/>
</div>
</div>
<div id="example" style={cssVariables}>
<div class="steps-wrapper" class:lockBorderToGap>
<div class="steps" class:wrap class:pillStyle class:limitHeight class:autoHeight>
{#each steps as step}
<div class="step" class:wrapWords>
{step}
</div>
{/each}
</div>
</div>
</div>
<style>
:global(body){
--arrow-width: 25px;
--step-gap: 5px;
--step-padding-x: 10px;
--height: 50px;
--step-border-width: 5px;
}
.settings {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
margin-bottom: 2rem;
}
.setting {
display: flex;
align-items: center;
gap: 0.5rem;
border: 1px solid #333;
border-radius: 5px;
padding: 0.25rem;
width: max-content;
}
input {
margin: 0;
}
.steps.pillStyle .step:first-of-type {
border-top-left-radius: 99999px;
border-bottom-left-radius: 99999px;
}
.steps.pillStyle .step:last-of-type {
border-top-right-radius: 99999px;
border-bottom-right-radius: 99999px;
}
.steps-wrapper {
/*padding: 0.5rem;*/
box-sizing: border-box;
background: black;
border-radius: 99999px;
overflow: hidden;
border: var(--step-border-width) solid transparent;
}
.steps-wrapper.lockBorderToGap {
border-width: var(--step-gap);
}
.steps {
display: flex;
gap: var(--step-gap);
overflow-x: scroll;
scrollbar-width: none;
/*padding: 1rem 0;*/
}
.steps.wrap {
flex-wrap: wrap;
}
.steps.limitHeight .step{
max-height: 50px;
}
.steps.autoHeight .step{
height: unset;
}
.step:not(.wrapWords) {
white-space: nowrap;
}
.step {
background: #756bea;
width: auto;
height: var(--height);
color: #fff;
transform-style: preserve-3d;
position: relative;
display: flex;
justify-content: center;
align-items: center;
padding: var(--step-padding-y) var(--step-padding-x);
box-sizing: border-box;
}
.step:hover{
background: #4b3fe4;
}
.step:first-child {
/*padding-right: var(--arrow-width);*/
/*padding-left: var(--step-padding-x);*/
}
.step:first-child::after {
content: "";
background: inherit;
position: absolute;
left: 100%;
width: var(--arrow-width);
height: 100%;
clip-path: polygon(calc(100% - var(--arrow-width)) 0%, 100% 50%, calc(100% - var(--arrow-width)) 100%, 0% 100%, 0% 0%);
}
.step:not(:is(:first-child, :last-child))::before{
content: "";
background: inherit;
position: absolute;
right: 100%;
width: var(--arrow-width);
height: 100%;
clip-path: polygon(100% 0%, 100% 100%, 0% 100%, var(--arrow-width) 50%, 0% 0%);
}
.step:not(:is(:first-child, :last-child))::after {
content: "";
background: inherit;
position: absolute;
left: 100%;
width: var(--arrow-width);
height: 100%;
clip-path: polygon(calc(100% - var(--arrow-width)) 0%, 100% 50%, calc(100% - var(--arrow-width)) 100%, 0% 100%, 0% 0%);
}
.step:not(:last-child) {
margin-right: var(--arrow-width);
padding-left: var(--step-padding-x);
}
.step:last-child {
padding-left: var(--step-padding-x);
padding-right: var(--step-padding-x);
}
.step:last-child::before {
content: "";
background: inherit;
position: absolute;
right: 100%;
width: var(--arrow-width);
height: 100%;
clip-path: polygon(100% 0, 100% 100%, 0% 100%, var(--arrow-width) 50%, 0% 0%);
}
</style>

Segments in a circle using CSS3

I know you can make a circle in CSS3 using the border radius hack. But is there any way to make them have segments like this picture? Is there a way of doing this through HTML and CSS but not JS?
Yes, you can get such slices of custom angles using either one of the following two methods:
If you don't need the slices to be elements themselves, the you can simply do it with one element and linear gradients - see this rainbow wheel I did last month.
If you need the slices to be elements themselves, then you can do it by chaining rotate and skew transforms - see this circular menu I did a while ago.
For #2, see also this very much simplified example I did right now.
.pie {
overflow:hidden;
position: relative;
margin: 1em auto;
border: dashed 1px;
padding: 0;
width: 32em; height: 32em;
border-radius: 50%;
list-style: none;
}
.slice {
overflow: hidden;
position: absolute;
top: 0; right: 0;
width: 50%; height: 50%;
transform-origin: 0% 100%;
}
.slice:first-child {
transform: rotate(15deg) skewY(-22.5deg);
}
.slice-contents {
position: absolute;
left: -100%;
width: 200%; height: 200%;
border-radius: 50%;
background: lightblue;
}
.slice:first-child .slice-contents {
transform: skewY(22.5deg); /* unskew slice contents */
}
.slice:hover .slice-contents { background: violet; } /* highlight on hover */
<ul class='pie'>
<li class='slice'>
<div class='slice-contents'></div>
</li>
<!-- you can add more slices here -->
</ul>
Yes you can: http://jsfiddle.net/elias94xx/3rx7w/, http://jsfiddle.net/elias94xx/3rx7w/2/
#chart {
width: 0;
height: 0;
border-right: 60px solid purple;
border-top: 60px solid transparent;
border-left: 60px solid transparent;
border-bottom: 60px solid transparent;
border-radius: 60px;
-moz-border-radius: 60px;
-webkit-border-radius: 60px;
}
<div id="chart"></div>
.chart {
position: absolute;
width: 0;
height: 0;
border-radius: 60px;
-moz-border-radius: 60px;
-webkit-border-radius: 60px;
}
#chart1 {
border-right: 60px solid red;
border-top: 60px solid transparent;
border-left: 60px solid transparent;
border-bottom: 60px solid transparent;
}
#chart2 {
border-right: 60px solid transparent;
border-top: 60px solid green;
border-left: 60px solid transparent;
border-bottom: 60px solid transparent;
}
#chart3 {
border-right: 60px solid transparent;
border-top: 60px solid transparent;
border-left: 60px solid blue;
border-bottom: 60px solid transparent;
}
#chart4 {
border-right: 60px solid transparent;
border-top: 60px solid transparent;
border-left: 60px solid transparent;
border-bottom: 60px solid yellow;
}
<div id="chart1" class="chart"></div>
<div id="chart2" class="chart"></div>
<div id="chart3" class="chart"></div>
<div id="chart4" class="chart"></div>
Source: http://www.paulund.co.uk/how-to-create-different-shapes-in-css
You can use html li element and some css transform to represent each slice of the circle.
The tricky part is the transform. In this case I've divided the circle into 5 slices.
The calculation is the following.
360/5=72 -> rotate
72+90=162 -> skewY
.sliceWrapper {
position: relative;
border: 1px solid black;
padding: 0;
width: 200px;
height: 200px;
border-radius: 50%;
list-style: none;
overflow: hidden;
}
.slice {
position: absolute;
left: -100%;
width: 200%;
height: 200%;
}
li {
overflow: hidden;
position: absolute;
top: -50%;
right: -50%;
width: 100%;
height: 100%;
transform-origin: 0% 100%;
}
li:first-child {
transform: rotate(0deg) skewY(162deg);
}
li:nth-child(2) {
transform: rotate(72deg) skewY(162deg);
}
li:nth-child(3) {
transform: rotate(144deg) skewY(162deg);
}
li:nth-child(4) {
transform: rotate(216deg) skewY(162deg);
}
li:nth-child(5) {
transform: rotate(288deg) skewY(162deg);
}
li:first-child .slice {
background: green;
}
li:nth-child(2) .slice {
background: tomato;
}
li:nth-child(3) .slice {
background: aqua;
}
li:nth-child(4) .slice {
background: yellow;
}
li:nth-child(5) .slice {
background: blue;
}
<ul class="sliceWrapper">
<li>
<div class="slice"></div>
</li>
<li>
<div class="slice"></div>
</li>
<li>
<div class="slice"></div>
</li>
<li>
<div class="slice"></div>
</li>
<li>
<div class="slice"></div>
</li>
</ul>
You can use a conic gradient
Conic gradients basically go around the shape, like a circle, from 0° to 360°.
Here is a basic conic gradient, with a circle:
div {
width: 500px;
height: 500px;
border-radius: 9999px;
background: red; /* fallback */
background: conic-gradient(red, orange, yellow, green, blue, purple);
}
<div></div>
Using color stops, we can then, magically, turn it into segments:
div {
width: 500px;
height: 500px;
border-radius: 9999px;
background: red; /* fallback */
background: conic-gradient(red 10%, orange 10%, orange 30%, yellow 30%, yellow 50%, green 50%, green 60%, blue 60%, blue 70%, purple 70%);
}
<div></div>
Optionally, if we only want one slice, we can now change this so we only have one colour, and now we're good to go :)
div {
width: 500px;
height: 500px;
border-radius: 9999px;
background: red; /* fallback */
background: conic-gradient(#0000 40%, red 40%, red 70%, #0000 70%);
}
<div></div>

Resources