2 posts on Fallback

Simple pie charts with fallback, today

3 min read 0 comments Report broken page

Five years ago, I had written this extensive Smashing Magazine article detailing multiple different methods for creating simple pie charts, either with clever use of transforms and pseudo-elements, or with SVG stroke-dasharray. In the end, I mentioned creating pie charts with conic gradients, as a future technique. It was actually a writeup of my “The Missing Slice” talk, and an excerpt of my CSS Secrets book, which had just been published.

I was reminded of this article today by someone on Twitter:

https://twitter.com/sam\_kent\_/status/1326805431390531584

I suggested conic gradients, since they are now supported in >87% of users’ browsers, but he needed to support IE11. He suggested using my polyfill from back then, but this is not a very good idea today.

Indeed, unless you really need to display conic gradients, even I would not recommend using the polyfill on a production facing site. It requires -prefix-free, which re-fetches (albeit from cache) your entire CSS and sticks it in a <style> element, with no sourcemaps since those were not a thing back when -prefix-free was written. If you’re already using -prefix-free, the polyfill is great, but if not, it’s way too heavy a dependency.

Pie charts with fallback (modern browsers)

Instead, what I would recommend is graceful degradation, i.e. to use the same color stops, but in a linear gradient.

We can use @supports and have quite an elaborate progress bar fallback. For example, take a look at this 40% pie chart:

.pie {
	height: 20px;
	background: linear-gradient(to right, deeppink 40%, transparent 0);
	background-color: gold;
}

@supports (background: conic-gradient(white, black)) { .pie { width: 200px; height: 200px; background-image: conic-gradient(deeppink 40%, transparent 0); border-radius: 50%; } }

This is what it looks like in Firefox 82 (conic gradients are scheduled to ship unflagged in Firefox 83) or IE11:

Note that because @supports is only used for the pie and not the fallback, the lack of IE11 support for it doesn’t affect us one iota.

If relatively modern browsers are all we care about, we could even use CSS variables for the percentage and the color stops, to avoid duplication, and to be able to set the percentage from the markup:

<div class="pie" style="--p: 40%"></div>
.pie {
	height: 20px;
	--stops: deeppink var(--p, 0%), transparent 0;
	background: linear-gradient(to right, var(--stops));
	background-color: gold;
}

@supports (background: conic-gradient(white, black)) { .pie { width: 200px; height: 200px; background-image: conic-gradient(var(–stops)); border-radius: 50%; } }

You can use a similar approach for 3 or more segments, or for a vertical bar.

One issue with this approach is that our layout needs to work well with two charts of completely different proportions. To avoid that, we could just use a square:

.pie {
	width: 200px;
	height: 200px;
	background: linear-gradient(to right, deeppink 40%, transparent 0) gold;
}

@supports (background: conic-gradient(white, black)) { .pie { background-image: conic-gradient(deeppink 40%, transparent 0); border-radius: 50%; } }

which produces this in IE11:

Granted, a square progress bar is not the same, but it can still convey the same relationship and is easier to design a layout around it since it always has the same aspect ratio.

Why not use radial gradients?

You might be wondering, why not just use a radial gradient, which could use the same dimensions and rounding. Something like this:

There are two problems with this. The first one may be obvious: Horizontal or vertical bars are common for showing the proportional difference between two amounts, albeit less good than a pie chart because it’s harder to compare with 50% at a glance (yes Tufte, pie charts can be better for some things!). Such circular graphs are very uncommon. And for good reason: Drawn naively (e.g. in our case if the radius of the pink circle is 40% of the radius of the yellow circle), their areas do not have the relative relationship we want to depict.

Why is that? Let r be the radius of the yellow circle. As we know from middle school, the area of the entire circle is π_r_², so the area of the yellow ring is π_r_² - (area of pink circle). The area of the pink circle is π(0.4_r_)² = 0.16π_r_². Therefore, the area of the yellow ring is π_r_² - 0.16π_r_² = 0.84π_r_² and their relative ratio is 0.16π_r_² / 0.84π_r_² = 0.16 / 0.84 ≅ 0.19 which is a far cry from the 40/60 (≅ 0.67) we were looking for!

Instead, if we wanted to draw a similar visualization to depict the correct relationship, we need to start from the ratio and work our way backwards. Let r be the radius of the yellow circle and kr the radius of the pink circle. Their ratio is π(kr)² / (π_r_² - π(kr)²) = 4/6 ⇒ _k_² / (1 - _k_²) = 4/6 ⇒ (1 - _k_²) / _k_² = 6/4 ⇒ 1/_k_² - 1 = 6/4 ⇒ 1/_k_² = 10/4 ⇒ k = 2 / sqrt(10) ≅ .632 Therefore, the radius of the pink circle should be around 63.2% of the radius of the yellow circle, and a more correct chart would look like this:

In the general case where the pink circle is depicting the percentage p, we’d want the radius of the pink circle to be sqrt(1 / p) the size of the yellow circle. That’s a fair bit of calculations that we can’t yet automate (though sqrt() is coming!). Moral of the story: use a bar as your fallback!


Use MathML today, with CSS fallback!

2 min read 0 comments Report broken page

These days, I’m working on the slides for my next talk, “The humble border-radius”. It will be about how much work is put into CSS features that superficially look as simple as border-radius, as well as what advances are in store for it in CSS Backgrounds & Borders 4 (of which I’m an editor). It will be fantastic and you should come, but this post is not about my talk.

As you may know, my slides are made with HTML, CSS & JavaScript. At some point, I wanted to insert an equation to show how border-top-left-radius (as an example) shrinks proportionally when the sum of radii on the top side exceeds the width of the element. I don’t like LaTeX because it produces bitmap images that don’t scale and is inaccessible. The obvious open standard to use was MathML, and it can even be directly embedded in HTML5 without all the XML cruft, just like SVG. I had never written MathML before, but after a bit of reading and poking around existing samples, I managed to write the following MathML code:

<math display="block">
    <mrow>
        <msub>
            <mi>r&prime;</mi>
            <mi>top-left</mi>
        </msub>
        <mo>=</mo>
        <mi>min</mi>
        <mo>(</mo>
        <msub>
            <mi>r</mi>
            <mrow>
                <mi>top-left</mi>
            </mrow>
        </msub>
        <mo>,</mo>
        <mi>width</mi>
        <mo>&times;</mo>
        <mfrac>
            <mrow>
                <msub>
                    <mi>r</mi>
                    <mi>top-left</mi>
                </msub>
            </mrow>
            <mrow>
                <msub>
                    <mi>r</mi>
                    <mi>top-left</mi>
                </msub>
                <mo>+</mo>
                <msub>
                    <mi>r</mi>
                    <mi>top-right</mi>
                </msub>
            </mrow>
        </mfrac>
        <mo>)</mo>
    </mrow>
</math>

I was very proud of myself. My first MathML equation! It’s actually pretty simple when you get the hang of it: <mi> is for identifiers, <mo> for operators and those are used everywhere. For more complex stuff, there’s <mfrac> for fractions (along with <mrow> to denote the rows), <msqrt> for square roots and so on.

It looked very nice on Firefox, especially after I applied Cambria Math to it instead of the default Times-ish font:

MathML native support in Firefox

However, I soon realized that as awesome as MathML might be, not not all browsers had seen the light. IE10 and Chrome are the most notable offenders. It looked like an unreadable mess in Chrome:

MathML in Chrome, with no CSS fallback

There are libraries to make it work cross-browser, the most popular of which is MathJax. However, this was pretty big for my needs, I just wanted one simple equation in one goddamn slide. It would be like using a chainsaw to cut a slice of bread!

The solution I decided to go with was to use Modernizr to detect MathML support, since apparently it’s not simple at all. Then, I used the .no-mathml class in conjunction with selectors that target the MathML elements, to mimic proper styling with simple CSS. It’s not a complete CSS library by any means, I just covered what I needed for that particular equation and tried to write it in a generic way, so that if I need it in future equations, I only have to add rules. Here’s a screenshot of the result in Chrome:

MathML in Chrome with CSS fallback

It doesn’t look as good as Firefox, but it’s decent. You can see the CSS rules I used in the following Dabblet:

Obviously it’s not a complete MathML-to-CSS library, if one is even possible, but it works well for my use case. If I have to use more MathML features, I’d write more CSS rules. The intention of this post is not to provide a CSS framework to use as a MathML fallback, but to show you a solution you could adapt to your needs. Hope it helps!