How to draw a circle sector in CSS?
That is very well possible using overflow
and transform
properties without any need to do complex calculations.
> Rotate transform
For angles less than 180deg
Add an element with aspect ratio 2:1 and
overflow: hidden;
Add a pseudo-element with with top border radii same as the height of the element and bottom radii as 0.
Put
transform-origin: 50% 100%;
This transforms the pseudo-element from its middle bottom.Transform: rotate(); the pseudo element by supplement of the required angle,
i.e.,transform: rotate(180 - rqrd. angle);
See how it works :
EG :
A 40deg sector using this method : Fiddle
div {
...
overflow: hidden;
...
}
div:before {
...
border-radius: 100px 100px 0 0;
transform-origin: 50% 100%;
transform: rotate(140deg);
...
}
div {
height: 100px;
width: 200px;
overflow: hidden;
position: relative;
}
div:before {
height: inherit;
width: inherit;
position: absolute;
content: "";
border-radius: 100px 100px 0 0;
background-color: crimson;
-webkit-transform-origin: 50% 100%;
-moz-transform-origin: 50% 100%;
-ms-transform-origin: 50% 100%;
transform-origin: 50% 100%;
-webkit-transform: rotate(140deg);
-moz-transform: rotate(140deg);
-ms-transform: rotate(140deg);
transform: rotate(140deg);
}
<div></div>
> Skew transform
You can also put image inside sector!
This can be done using skew
transforms on parent and -ve skew on pseudoelement :
Fiddle
div {
...
overflow: hidden;
transform-origin: 0% 100%;
transform: skew(-50deg); /*Complement of rqrd angle*/
...
}
div:before {
...
transform-origin: 0% 100%;
transform: skew(50deg);
...
}
See how this works :
div {
height: 200px;
width: 200px;
overflow: hidden;
-webkit-transform-origin: 0% 100%;
-moz-transform-origin: 0% 100%;
-ms-transform-origin: 0% 100%;
transform-origin: 0% 100%;
-webkit-transform: skew(-50deg);
-moz-transform: skew(-50deg);
-ms-transform: skew(-50deg);
transform: skew(-50deg); /*Complement of rqrd angle or (90 - angle)*/
position: relative;
}
div:before {
height: inherit;
width: inherit;
position: absolute;
content: "";
border-radius: 0 200px 0 0;
background: url('http://www.placekitten.com/g/300/200/');
-webkit-transform-origin: 0% 100%;
-moz-transform-origin: 0% 100%;
-ms-transform-origin: 0% 100%;
transform-origin: 0% 100%;
-webkit-transform: skew(50deg);
-moz-transform: skew(50deg);
-ms-transform: skew(50deg);
transform: skew(50deg);
}
<div></div>
Acknowledgements : I don't want to be a self stealer, I used the ideas which I had previously used here and here.
CSS and Multiple Background Gradients
Rather than trying to draw the green portion, you could draw the white portions instead:
pie {
border-radius: 50%;
background-color: green;
}
.ten {
background-image:
/* 10% = 126deg = 90 + ( 360 * .1 ) */
linear-gradient(126deg, transparent 50%, white 50%),
linear-gradient(90deg, white 50%, transparent 50%);
}
pie {
width: 5em;
height: 5em;
display: block;
border-radius: 50%;
background-color: green;
border: 2px solid green;
float: left;
margin: 1em;
}
.ten {
background-image: linear-gradient(126deg, transparent 50%, white 50%), linear-gradient(90deg, white 50%, transparent 50%);
}
.twentyfive {
background-image: linear-gradient(180deg, transparent 50%, white 50%), linear-gradient(90deg, white 50%, transparent 50%);
}
.fifty {
background-image: linear-gradient(90deg, white 50%, transparent 50%);
}
/* Slices greater than 50% require first gradient
to be transparent -> green */
.seventyfive {
background-image: linear-gradient(180deg, transparent 50%, green 50%), linear-gradient(90deg, white 50%, transparent 50%);
}
.onehundred {
background-image: none;
}
<pie class="ten"></pie>
<pie class="twentyfive"></pie>
<pie class="fifty"></pie>
<pie class="seventyfive"></pie>
<pie class="onehundred"></pie>
Demo: http://jsfiddle.net/jonathansampson/7PtEm/
Scalable Vector Graphics
If it's an option, you can accomplish a similar effect using SVG <circle>
and <path>
elements. Consider the following:
<svg>
<circle cx="115" cy="115" r="110"></circle>
<path d="M115,115 L115,5 A110,110 1 0,1 190,35 z"></path>
</svg>
The above is fairly straight forward. We have an element containing a circle and a path. The circle's center is at 115x115 (making the SVG element 230x230). The circle has a radius of 110, making it a total of 220 wide (leaving a border of 10).
We then add a <path>
element, which is the most complicated portion of this example. This element has one attribute which determines where, and how the path is drawn. It starts with the following value:
M115,115
This instructs the path to start in the center of the aforementioned circle. Next, we draw a line from this location to the next location:
L115,5
This draws a vertical line from the center of the circle up to the top of the element (well, five pixels from the top). It is at this point things get a little more complicated but still very much intelligible.
We now draw an arc from our present location (115,5):
A110,110 1 0,1 190,35 z
This creates our arc and gives it a radius matching that of our circle (110). The two values represent the x-radius and y-radius, and both are equal since we're dealing with a circle. The next set of important numbers are the last, 190,35
. This tells the arc where to complete.
As for the rest of the information (1 0,1
and z
) these control the curvature, direction, and terminal of the arc itself. You can learn more about them by consulting any online SVG path reference.
To accomplish a "slice" of a different size, merely change the 190,35
to reflect a larger or smaller set of coordinates. You may find that you'll need to create a second, arc if you want to span more than 180 degrees.
If you want to determine the x and y coordinates from an angle, you can use the following equations:
x = cx + r * cos(a)
y = cy + r * sin(a)
With the above example, a degree of 76 would be:
x = 115 + 110 * cos(76)
y = 115 + 110 * sin(76)
Which gives us 205.676,177.272
.
With some ease, you can create the following:
circle {
fill: #f1f1f1;
stroke: green;
stroke-width: 5;
}
path {
fill: green;
}
svg.pie {
width: 230px;
height: 230px;
}
<svg class="pie">
<circle cx="115" cy="115" r="110"></circle>
<path d="M115,115 L115,5 A110,110 1 0,1 190,35 z"></path>
</svg>
<svg class="pie">
<circle cx="115" cy="115" r="110"></circle>
<path d="M115,115 L115,5 A110,110 1 0,1 225,115 z"></path>
</svg>
<svg class="pie">
<circle cx="115" cy="115" r="110"></circle>
<path d="M115,115 L115,5 A110,110 1 0,1 115,225 A110,110 1 0,1 35,190 z"></path>
</svg>
Demo: http://jsfiddle.net/jonathansampson/tYaVW/