need to create pure CSS3 Shape [duplicate] - html
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>
Related
How to make this specific shadow for a box : before?
How can i achieve the top left part of this box like the image below with css? I can't make the shadow below the yellow triangle. some suggestions would be helpfull. Below is my CSS + HTML so far: :root { --jaune: #FFF701; --bleu: #212D55; } .book{ margin-bottom: 0px; font-size: x-small; color: #364165; text-align: center; } .box { border: 1px solid var(--bleu); background-color: #fff; position: relative; margin-left: 10px; margin-right: 10px; margin-bottom: 16px; } .box::before { content: ' '; border-top: 32px solid #d3d5dd; border-right: 30px solid var(--jaune); width: 0; position: absolute; } .btn_book{ background-color: #212d55; width: 128px; margin-right:79px; margin-left:79px; border: 1px solid #212d55; position: absolute; color: white; text-transform: uppercase; cursor: pointer; } .btn_book:hover{ background-color: var(--jaune); color:#212d55; } .btn_book:hover::before { border-top: 10px solid #212d55; } .btn_book:before { content: ""; height: 0; width: 0; border-top: 10px solid #fffa0a; border-left: 10px solid transparent; border-right: 10px solid transparent; position: absolute; z-index: 1; top:0; left: 0; transform-origin: left; transform: translate(60%) translateY(-71%) rotate(135deg) } <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/> <div class="box" style="width: 18rem; height: 19rem;"> <img src="https://b2btolink.com/leboudoir/wp-content/themes/leboudoir/images/logo.png" style="width: 100px; margin-left:80px;"> <p style="text-align:center;color: #212d55;"> <b>NEW CANAAN</b> </p> <hr class="dashed"> <p class="book"> 160 Main Street</p> <p class="book"> New Canaan CT 06840</p> <p class="book"> 203-957-8600</p> <hr class="dashed"> <button type="button" class="btn_book">BOOK NOW</button> </div> How can this be possible with shadow property
Here is an idea using multiple background with gradient and skew transformation: .box { border: 1px solid #212D55; background-color: #fff; position: relative; margin: 10px; background: linear-gradient(to top left,transparent 50%,#d3d5dd 50%) top left/32px 32px no-repeat; } .box::before { content: ' '; position: absolute; top:-1px; left:-1px; width:34px; height:34px; background: linear-gradient(to bottom right,transparent 45%,grey 50%) bottom/100% 5px, linear-gradient(to bottom right,transparent 45%,grey 50%) right/5px 100%, linear-gradient(to bottom right,transparent 50%,yellow 50%); background-repeat: no-repeat; transform: skew(5deg,5deg); } <div class="box" style="width: 18rem; height: 19rem;"> </div>
You will need to adjust this a little, but you should be able to use clip-pathto create a triangle on another div, then change the z-index on your ::before to bring it in front of the triangle. :root { --jaune: #FFF701; --bleu: #212D55; } .book{ margin-bottom: 0px; font-size: x-small; color: #364165; text-align: center; } .box { border: 1px solid var(--bleu); background-color: #fff; position: relative; margin-left: 10px; margin-right: 10px; margin-bottom: 16px; } .box::before { content: ' '; border-top: 32px solid #d3d5dd; border-right: 30px solid var(--jaune); width: 0; position: absolute; z-index: 100; } .shadow{ position: absolute; top: 5px; height: 41px; left: 0px; width: 37px; background: #A0A0A0; clip-path: polygon(83% 0%, 4% 63%, 100% 91%); z-index: 1; } .btn_book{ background-color: #212d55; width: 128px; margin-right:79px; margin-left:79px; border: 1px solid #212d55; position: absolute; color: white; text-transform: uppercase; cursor: pointer; } .btn_book:hover{ background-color: var(--jaune); color:#212d55; } .btn_book:hover::before { border-top: 10px solid #212d55; } .btn_book:before { content: ""; height: 0; width: 0; border-top: 10px solid #fffa0a; border-left: 10px solid transparent; border-right: 10px solid transparent; position: absolute; z-index: 1; top:0; left: 0; transform-origin: left; transform: translate(60%) translateY(-71%) rotate(135deg) } <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/> <div class="box" style="width: 18rem; height: 19rem;"> <div class="shadow"></div> <img src="https://b2btolink.com/leboudoir/wp-content/themes/leboudoir/images/logo.png" style="width: 100px; margin-left:80px;"> <p style="text-align:center;color: #212d55;"> <b>NEW CANAAN</b> </p> <hr class="dashed"> <p class="book"> 160 Main Street</p> <p class="book"> New Canaan CT 06840</p> <p class="book"> 203-957-8600</p> <hr class="dashed"> <button type="button" class="btn_book">BOOK NOW</button> </div>
Fixing opacity of content inside div
I have a div that has a background image but has 50% opacity. Now I have a div that is child and I want what every the content it has to have 100% opacity. You can see in the snipplet headings and textbox and button has less opacity. Can anyone help how to fix this thing? I tried to apply opacity 100% to child but it didn't work. /* CSS to be fixed*/ #home_div { background-image: url("https://upload.wikimedia.org/wikipedia/commons/thumb/1/1e/Shoppers_on_Dundas%2C_near_Yonge.jpg/1200px-Shoppers_on_Dundas%2C_near_Yonge.jpg"); opacity: 0.5; filter: alpha(opacity=50); /*background-color: #0050A0;*/ background-color: lightgrey; padding-top: 200px; color: white; padding-bottom: 200px; height: 100%; } #home_div_content { opacity: 1.0; filter: alpha(opacity=100); text-align: center; } #header { height: 70px; border-bottom: 4px solid lightgrey; } #header_content { margin-top: 10px; margin-left: 80px; } .brandmark { margin-top: -20px; } .link_to a { color: #0050A0 !important; } .featured_div { display: none; } .featured_close_anchor, .featured_anchor_close { text-align: center; } #heading, #tag_line { top: -300px; position:relative; color: #0050A0; } #search { border-radius: 0 !important; border-color: #0050A0 !important; width: 60%; height: 35px; padding: 8px 15px; color: #0050A0; /* change color of text to be typed inside search box */ font-size: 13px; line-height: 20px; background-color: transparent; border: 1px solid #ccc; -webkit-box-shadow: none; box-shadow: none; } .btn-custom { color: #FFFFFF; background-color: #0050A0; /* change button color */ border-radius: 0!important; /* button border radius */ padding: 5px 11px; /* Button size change*/ margin-top: -3.5px; border-top: 2px solid #0050A0; border-bottom: 3px solid #0050A0; margin-left: -3px; } .btn-custom:hover{ background-color:#9AC94B; /* change button color on hover */ border-radius: 0!important; } .left_categories { padding-top: 5px; padding-bottom: 5px; margin-bottom: 1px; border-left: 4px solid #0050A0; } .left_categories:hover { border-top: 1px solid lightgrey; border-bottom: 1px solid lightgrey; border-left: 4px solid #E5002B; } .active_category { background-color: #0050A0; color: white !important; border-left: 4px solid #E5002B; } .search_section { margin-top: 30px; } a { text-decoration: none !important; } .flash_nav { height: 90px; border: 0 !important; background-color: #283442; } .gradient { background: -moz-linear-gradient(left, white 0%, white 45%, #12A8E0 85%, #0050A0 100%); } .flash_navbar a { color: black !important; } .search_form { width: 70%; } .nav_form { border-radius: 0; margin-top: 27px; } #searchBar { border-color: #0050A0; } #searchButton { background-color: #0050A0; color: white; border: none; } <div id="home_div"> <div class="container" id="home_div_content"> <h1 id="heading">Find your product!</h1> <h4 id="tag_line">Search what you are looking for.</h4> <form method="GET" action="/product/search"> <input type="text" name="product" id="search" placeholder="Enter product name" class="searchTextBox" /> <button type="submit" id="quick-search" class="btn btn-custom"><span class="glyphicon glyphicon-search custom-glyph-color"></span></button> </form> <br /> view <i class="fa fa-chevron-down"></i> featuring </div> </div> FIDDLE
An opacity rule will always affect child/descendant elements since they are part of the parent, and the rule says the parent should be 50% opacity. To get round this, use a pseudo element and give that reduced opacity rather than the parent. HTML <div id='outer'> <div id='inner'></div> </div> CSS #outer { width: 200px; height: 200px; position: relative; padding: 2em; } #outer::before { content: ''; position: absolute; left: 0; top: 0; width: 100%; height: 100%; background: red; opacity: .5; z-index: -1; } #inner { width: 100%; height: 100%; background: blue; } Fiddle.
CSS transform rotation on :after not working
I've styled a checkbox and wanted to make a checkmark with the :after element. However, I can not turn it around. The same style attached to a div works fine. Used style: content: ''; position: absolute; width:.5em; height:.2em; transition: all .2s; border-left: 2px solid red; border-bottom: 2px solid red; top: 0.4em; left: 0.3em; transform: rotate(-45deg); See a Codepen here: Codepen
Multiple transform overrides the previous transform. Better to write them as shorthand transform: rotate(-45deg) scale(1);
Try this code .wb_checkbox { position: relative; } .wb_checkbox>input[type="checkbox"] { cursor: pointer; position: absolute; left: 3px; top: 0; z-index: 2; width: 26px; height: 26px; opacity: 0; vertical-align: middle; } .wb_checkbox>input[type="checkbox"]+label { vertical-align: middle; border: 2px solid #ccc; background-color: #fff; height: 26px; width: 26px; margin-right: 16px; display: inline-block; z-index: 1; position: relative; } .wb_checkbox>input[type="checkbox"]:checked+label { background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #65a416), color-stop(1, #6ca43d)); /*background: -moz-linear-gradient(center bottom, #65a416 0%, #6ca43d 100%);*/ box-shadow: 0 2px 7px rgba(0, 0, 0, 0.6); border: 2px solid #fff; } .wb_checkbox>input[type="checkbox"]:checked+label:after { content: '\2714'; text-indent: 0; font-size: 15px; color: #fff; position: absolute; top: 2px; left: 7px; width: 13px; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.7); } <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" /> <div class="col-md-12"> <div class="form-group"> <h5>Choose Option *</h5> <p class="wb_checkbox"> <input type="checkbox" name="checkbox-1" id="checkbox-1" checked> <label for="checkbox-1"></label> <strong>I have not car !</strong> </p> <p class="wb_checkbox"> <input type="checkbox" name="checkbox-2" id="checkbox-2"> <label for="checkbox-2"></label> <strong>I have car</strong> </p> </div> </div>
Creating a transparent CSS triangle over a background image
I'm making a divider over a background image that features a line with a pointer in the middle signifying to look below it. It's all just one line so the divider is not solid. When I made my divider the border of the parent goes through the triangle because the background is transparent. Just take a look at what I'm trying to explain: I would like the triangle to hide that line in the middle. This is how I create the divider: <div class="splash"> <div class="splash-divider"> </div> </div> .splash { background: url("https://unsplash.imgix.net/photo-1416339442236-8ceb164046f8?q=75&fm=jpg&s=8eb83df8a744544977722717b1ea4d09"); height: 200px; } .splash-divider { position: relative; margin: 20px auto 0 auto; width: 50%; height: 30px; border-bottom: 1px solid #ffffff; box-shadow: 0px 2px 0px rgba(0, 0, 0, 0.15); } .splash-divider:after { content: ""; position: absolute; top: 15px; left: 50%; width: 30px; height: 30px; border-left: 1px solid #ffffff; border-bottom: 1px solid #ffffff; box-shadow: -2px 2px 0 rgba(0, 0, 0, 0.15); transform: rotate(-45deg) translate(-50%, -50%); -webkit-transform: rotate(-45deg) translate(-50%, -50%); -ms-transform: rotate(-45deg) translate(-50%, -50%); -moz-transform: rotate(-45deg) translate(-50%, -50%); -o-transform: rotate(-45deg) translate(-50%, -50%); } As you can see, the parent contains a background image. This would be super simple if it was just a color. Here's the fiddle. Edit Resolved! Here's the working fiddle: http://jsfiddle.net/a9fkh0tp/1/
It is possible, see live demo: http://jsfiddle.net/a9fkh0tp/1/ .splash { background: url("https://unsplash.imgix.net/photo-1416339442236-8ceb164046f8?q=75&fm=jpg&s=8eb83df8a744544977722717b1ea4d09"); height: 200px; } .splash-divider { position: relative; margin: 20px auto 0 auto; width: 50%; height: 30px; border-bottom: 1px solid transparent; } .splash-divider:after { content: ""; position: absolute; top: 15px; left: 50%; width: 30px; height: 30px; border-left: 1px solid #ffffff; border-bottom: 1px solid #ffffff; box-shadow: -2px 2px 0 rgba(0, 0, 0, 0.15); transform: rotate(-45deg) translate(-50%, -50%); } .splash-divider span:before, .splash-divider span:after { position: absolute; top: 0; display: inline-block; content: ""; width: 50%; height: 30px; border-bottom: 1px solid #fff; box-shadow: 0px 2px 0px rgba(0, 0, 0, 0.15); } .splash-divider span:before { left: -28px; } .splash-divider span:after { right: -16px; } <div class="splash"> <div class="splash-divider"><span></span></div> </div> The idea is to divide the single line to 2 parts (left + right). In order to do that, add a <span> into the <div>, so <div class="splash-divider"><span></span></div> we can then play more with it.
You could as well use a method with pseudo elements. .divider { padding:1em; transform:rotate(45deg); width:0; margin:auto; border:2px white solid; border-top:none; border-left:none; position:relative; box-shadow:1px 1px 1px white; } .divider:before, div:after { content:''; width:2000px; border-bottom:2px solid white; position:absolute; } .divider:before { transform-origin:top left; bottom:1.9em; left:2em; transform:rotate(-45deg); box-shadow:1px 1px 1px white; } .divider:after { transform-origin:top left; left:0.05em; top:2.1em; transform:rotate(135deg); box-shadow:1px -1px 1px white; } html { min-height:100%; background:gray; background:linear-gradient(to bottom left, gray, yellow,purple, gray, yellow,purple, gray, yellow,purple); } <div class="divider"></div> You can play with it in http://codepen.io/gc-nomade/pen/raYGyO ... add radius, transform, whatever :)
HTML: <div class="line-separator"> <div class="side-line"> </div> <div class="triangle"> </div> <div class="side-line"> </div> </div> CSS: .side-line { display: inline-block; border-top: 1px solid black; width: 20%; } .triangle { display: inline-block; height: 7px; width: 7px; transform: rotate(45deg); transform-origin: center center; border-top: 1px solid black; border-left: 1px solid black; margin: 0 -3px -3px; } Live demo: http://jsfiddle.net/85saaphw/ If you want the triangle to be upside-down just change the transform: rotate(45deg) arg to 225deg.
How to make this arrow in CSS only?
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>