<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tim</title>
    <description>The latest articles on DEV Community by Tim (@timbauwens).</description>
    <link>https://dev.to/timbauwens</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F370458%2Ffcfa3a6b-0dfa-42b9-98f9-e528a8c99094.jpeg</url>
      <title>DEV Community: Tim</title>
      <link>https://dev.to/timbauwens</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/timbauwens"/>
    <language>en</language>
    <item>
      <title>Interactive, accessible circle wedges with only CSS</title>
      <dc:creator>Tim</dc:creator>
      <pubDate>Mon, 19 Oct 2020 13:52:49 +0000</pubDate>
      <link>https://dev.to/timbauwens/interactive-accessible-circle-wedges-with-only-css-o9h</link>
      <guid>https://dev.to/timbauwens/interactive-accessible-circle-wedges-with-only-css-o9h</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fww0n075kh4k0dd2q4m0q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fww0n075kh4k0dd2q4m0q.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's one of those things you're almost never asked as a front end dev - but when you are, it's a struggle to find a working example on the web.&lt;/p&gt;

&lt;p&gt;I've searched everywhere, and found many solutions - all of which are very superficial, in other words they fill the design aspects but don't give you any usable or accessible elements in the end.&lt;/p&gt;

&lt;h2&gt;
  
  
  The request:
&lt;/h2&gt;

&lt;p&gt;The client says, "Hey, what we really want here is a spinny wheely thing - like the one at carnivals where you can win a prize depending on where you land - but instead of spinning it, we want each wedge to represent [insert anything you like here] - is that possible? &lt;/p&gt;

&lt;p&gt;And you say "Sure..." because it can't be &lt;em&gt;that&lt;/em&gt; hard, right?&lt;/p&gt;

&lt;p&gt;And then you suffer. All the solutions out there don't create clickable, accessible, style-able elements. &lt;/p&gt;

&lt;h2&gt;
  
  
  The solution:
&lt;/h2&gt;

&lt;p&gt;[tl;dr] &lt;a href="https://codepen.io/tjbauwens/pen/bGepqoj" rel="noopener noreferrer"&gt;Codepen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In it's simplest form you create a container, and make sure it's overflow is hidden and that it's a perfect circle with &lt;code&gt;border-radius: 50%&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the markup you can add the inner elements - they can be buttons, divs, a ul/ol with lis etc... It doesn't really matter what you put in there, it's the CSS calculations that count. Here's my example HTML"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"pie"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;1&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;    
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;2&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;3&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my example I named the container &lt;code&gt;.pie&lt;/code&gt;, here's the important CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.pie&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;150px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;150px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Height and width obviously only need to match each other, but could be anything.&lt;/p&gt;

&lt;p&gt;Then you give the inner elements CSS to make them all appear initially as first-quarter quadrants of the pie container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transform-origin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bottom&lt;/span&gt; &lt;span class="nb"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What you have so far would look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnwdp6zrrufsrtk4jwzbf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnwdp6zrrufsrtk4jwzbf.png" alt="Quadrant"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;transform-origin&lt;/code&gt; probably seems out of place there, but it makes sense later, and is the key to the whole thing...&lt;/p&gt;

&lt;p&gt;The final key to making the wedges is the calculation for transformation of each square into a wedge. This is done by using an ordered combination of: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;transform: rotate()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transform: skeyY()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To make the calculations we need to know the number of degrees each wedge should take in the circle. Let's say&lt;br&gt;
&lt;code&gt;share = 120&lt;/code&gt;&lt;br&gt;
which is correct for our example with 3 equal shares, and we need an iterator, let's use&lt;br&gt;
&lt;code&gt;i = 0&lt;/code&gt;&lt;br&gt;
&lt;em&gt;(I'm sure you can see how this will translate into a dynamic JS function for any number of wedges...)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now the calculation is as follows per wedge in order of appearance:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rotate = (i * share)deg&lt;/code&gt;&lt;br&gt;
&lt;code&gt;skeyY = (share - 90)deg&lt;/code&gt;&lt;br&gt;
&lt;code&gt;i++&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Minus 90 because the wedge starts out square&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Basically the rotation turns the wedge on it's bottom left corner (which is the center of the pie) the number of degrees of all the wedges that are before it. The skewY skews the wedge from being a rectangle to being a wedge of the right degrees.&lt;/p&gt;

&lt;p&gt;Then we have to counter the skewY and rotation on the inner element (especially if you want text there), the calculation for that is:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rotate = (share / 2)deg&lt;/code&gt;&lt;br&gt;
&lt;code&gt;skewY(-(share - 90)deg&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will reverse the transformation and rotate the text to &lt;em&gt;appear&lt;/em&gt; 45 degrees relative to it's containing 'wedge'.&lt;/p&gt;

&lt;p&gt;Now your markup will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"pie"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"transform: rotate(0deg) skewY(30deg)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"transform: skewY(-30deg) rotate(60deg)"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;1&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;    
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"transform: rotate(120deg) skewY(30deg)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"transform: skewY(-30deg) rotate(60deg)"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;2&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"transform: rotate(240deg) skewY(30deg)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"transform: skewY(-30deg) rotate(60deg)"&lt;/span&gt;&lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;3&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fair warning&lt;/strong&gt;&lt;br&gt;
The order or the transform properties is important. Try switching the order and it won't work. I don't have enough time to figure that out, so if anyone here wants to explain that - go for it!&lt;/p&gt;

&lt;p&gt;Here's how it looks in the end, with a bit of extra css so you can see the outcome better.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/tjbauwens/embed/bGepqoj?height=600&amp;amp;default-tab=js,result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;And if you're interested in making it dynamic, here's a very simple implementation:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/tjbauwens/embed/NWrrMPv?height=600&amp;amp;default-tab=js,result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats and thoughts...
&lt;/h2&gt;

&lt;p&gt;Don't try this on Internet Exploder - I haven't, and I won't...&lt;/p&gt;

&lt;p&gt;The only real caveat is that you are limited to a minimum of three wedges. The maximum is really dependent on the inner content of the wedges as well as the overall size of the 'pie'... &lt;/p&gt;

&lt;p&gt;If you're interested, this could most likely be quite easily adapted into a simple pie chart engine - but I don't have the time to figure out the details.&lt;/p&gt;

&lt;p&gt;Hope someone in need finds this, and it helps :-)&lt;/p&gt;

</description>
      <category>css</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
