
We will use CSS filter and backgrounds made with linear gradients.
Setting up HTML
<div class="container"> <div class="conical-grad"></div> </div>
Giving dimensions
.conical-grad{ width:200px; height:200px; background:#000; }
Background color is set for visibility, we will remove it later.
Make circle
.container{ border-radius:50%; overflow:hidden; }
It’s not look like a circle as container is a block element which means its width spreads throughout the page. You can check it by setting the background of container :
.container{ /*..*/ background:red; }
Fix it by using fixed positioning :
.container{ border-radius:50%; overflow:hidden; position:fixed;/*Add this*/ }
Now its width is independent of the width of the page but it grows as much as to cover its children.
Centering inside the page
Add the well known code for centering :
.container{ /*..*/ position:fixed; top:50%; left:50%; transform:translate(-50%,-50%); }
Setting up pseudo elements
We will use pseudo elements (:before and :after elements). First set up :before such that it covers the parent element and set its background for its visibility :
.conical-grad{ /*..*/ position:relative; } .conical-grad:before{ position:absolute; content:""; top:0; bottom:0; left:0; right:0; background:red; }
position:relative; is important in parent element if you want to use position:absolute; in children elements. We will set two sets of backgrounds (one in :before and one in :after). :before will cover the upper half portion and :after will cover the lower half. Change the bottom property of :before such that it covers upper half :
.conical-grad:before{ /*..*/ bottom:50%; /*..*/ }
Set a set of backgrounds to :before
Set the first linear gradient :
.conical-grad:before{ position:absolute; content:""; top:0; bottom:50%; left:0; right:0; background: linear-gradient(red,transparent);/*Add this*/ }
Set the red color using hsl() function :
.conical-grad:before{ /*..*/ background: linear-gradient(hsl(0,100%,50%),transparent); }
Make the gradient hard-edged :
.conical-grad:before{ /*..*/ background: linear-gradient(hsl(0,100%,50%) 50%,transparent 50%); }
Rotate that gradient by 45 degrees :
.conical-grad:before{ /*..*/ background: linear-gradient(45deg,hsl(0,100%,50%) 50%,transparent 50%); }
As you can see the line of separation of colors not passing through the center. Change the value of bottom to the prevous value again :
.conical-grad:before{ position:absolute; content:""; top:0; bottom:0;/*change back to 0*/ left:0; right:0; background: linear-gradient(45deg,hsl(0,100%,50%) 50%,transparent 50%); }
So here it is passing through center. It is passing through the center when the child element (:before) has dimensions same as that of its parent (div with class conical-grad). So what we are gonna do now is that we will set background size same as that of that parent with bottom:50%;
.conical-grad:before{ position:absolute; content:""; top:0; bottom:50%; left:0; right:0; background: linear-gradient(45deg,hsl(0,100%,50%) 50%,transparent 50%); background-size:200px 200px;/*Add this*/ }
Similarly add the second background, but now with 90 degree rotation :
.conical-grad:before{ /*..*/ background: linear-gradient(45deg,hsl(0,100%,50%) 50%,transparent 50%), linear-gradient(90deg,hsl(0,100%,50%) 50%,transparent 50%); /*..*/ }
Change the hue of previously added gradient by 45 degrees :
.conical-grad:before{ /*..*/ background: linear-gradient(45deg,hsl(0,100%,50%) 50%,transparent 50%), linear-gradient(90deg,hsl(45,100%,50%) 50%,transparent 50%);/*Note this*/ /*..*/ }
Similarly add two more backgrounds by shifting each one sequentially by 45 degrees (both gradient rotation and hue rotation) :
.conical-grad:before{ /*..*/ background: linear-gradient(45deg,hsl(0,100%,50%) 50%,transparent 50%), linear-gradient(90deg,hsl(45,100%,50%) 50%,transparent 50%), linear-gradient(135deg,hsl(90,100%,50%) 50%,transparent 50%), linear-gradient(180deg,hsl(135,100%,50%) 50%,transparent 50%); /*..*/ }
Remove the background from conical-grad :
.conical-grad{ width:200px; height:200px; /*background:#000;*/ /*Remove this*/ position:relative; }
Set a set of backgrounds to :after
First set the same properties of :before to :after
.conical-grad:before,.conical-grad:after{/*Note this*/ position:absolute; content:""; top:0; bottom:50%; left:0; right:0; background: linear-gradient(45deg,hsl(0,100%,50%) 50%,transparent 50%), linear-gradient(90deg,hsl(45,100%,50%) 50%,transparent 50%), linear-gradient(135deg,hsl(90,100%,50%) 50%,transparent 50%), linear-gradient(180deg,hsl(135,100%,50%) 50%,transparent 50%); background-size:200px 200px; }
Set its bottom to zero :
.conical-grad:after{ bottom:0; }
Rotate whole :after element by 180 degrees
.conical-grad:after{ /*..*/ transform:rotate(180deg); }
Actually it’s drawn over the :before, we have to lower its stack order :
.conical-grad:after{ /*..*/ z-index:-1; }
As the backgrounds are same as in :before, but still copy those backgrounds to :after and shift each one’s hue by 180 degrees :
.conical-grad:after{ /*..*/ background: linear-gradient(45deg,hsl(180,100%,50%) 50%,transparent 50%), linear-gradient(90deg,hsl(225,100%,50%) 50%,transparent 50%), linear-gradient(135deg,hsl(270,100%,50%) 50%,transparent 50%), linear-gradient(180deg,hsl(315,100%,50%) 50%,transparent 50%); }
Why we aren’t using “filter:hue-rotate(180deg)” ?
Actually I have tried that but that is producing dull colors and I don’t know why.
Now the magic
.conical-grad{ /*..*/ filter:blur(25px); }
Add border and shadows (optional)
.container{ border:2px solid #000; box-shadow:0 0 32px #000,0 0 32px #000 inset; }
Whole code :
.conical-grad{ width:200px; height:200px; position:relative; filter:blur(25px); } .container{ border-radius:50%; overflow:hidden; position:fixed; top:50%; left:50%; transform:translate(-50%,-50%); border:2px solid #000; box-shadow:0 0 32px #000,0 0 32px #000 inset; } .conical-grad:before,.conical-grad:after{ position:absolute; content:""; top:0; bottom:50%; left:0; right:0; background: linear-gradient(45deg,hsl(0,100%,50%) 50%,transparent 50%), linear-gradient(90deg,hsl(45,100%,50%) 50%,transparent 50%), linear-gradient(135deg,hsl(90,100%,50%) 50%,transparent 50%), linear-gradient(180deg,hsl(135,100%,50%) 50%,transparent 50%); background-size:200px 200px; } .conical-grad:after{ bottom:0; transform:rotate(180deg); z-index:-1; background: linear-gradient(45deg,hsl(180,100%,50%) 50%,transparent 50%), linear-gradient(90deg,hsl(225,100%,50%) 50%,transparent 50%), linear-gradient(135deg,hsl(270,100%,50%) 50%,transparent 50%), linear-gradient(180deg,hsl(315,100%,50%) 50%,transparent 50%); }
<div class="container"> <div class="conical-grad"></div> </div>
As CSS filters do not work in IE, this conical gradient won”t work in IE. Code is also available at https://codepen.io/zFunx/pen/MrmrLx.