CSS pie charts without JavaScript: keep the loop in PHP

The pitch for CSS-only charts is familiar: drop the charting library and its runtime cost, keep the markup semantic. Antoine Villepreux just took the last script out of a CSS pie chart on CSS-Tricks, and the write-up is clever. Dropping JavaScript is the headline, but the transferable idea is different. A pie chart needs an accumulation loop somewhere, because every slice has to know the total of the slices before it, and on a WordPress site that loop belongs in PHP, where it has worked for years in every browser.

Does no JavaScript hold in real browsers?

Not yet, and the post half admits it. The zero-script version reads percentages off data attributes with the upgraded attr() function, the one that accepts type(<number>) so the value becomes a real number that calc() can add. Chrome shipped that in version 133 in early 2025. Firefox and Safari haven’t, per the MDN reference and Can I use. The author keeps repetitive nth-child chains and counters as the working path for exactly that reason. On a client store with a normal browser mix, a chart that only computes in Chromium is not shippable, so “sans JavaScript” means “the values arrive another way”.

Where does the CSS pie chart trick live?

In the parent element. CSS children can’t read their siblings, so the original article used a small JS loop to set an --accum variable on each item. The fork moves all the values onto the parent <ul> as data-percentage-1 through data-percentage-4, builds running totals as chained custom properties, and hands each one to its slice with nth-child(). That parent-owns-the-data pattern survives attr() being unavailable. It only needs something that already knows the numbers to set them, and in WordPress that’s the render step. Once sibling-index() goes Baseline the repetitive selectors shrink too, which is the same simplification I wrote about for staggered nth-child layouts.

How would I ship this on a client site?

Render it in PHP. Loop over the data once at render time, print the custom properties inline, and keep the CSS generic:

function bbioon_render_pie_chart( array $slices ): string {
	$accum = 0;
	$props = '';
	$items = '';

	foreach ( array_values( $slices ) as $i => $slice ) {
		$n      = $i + 1;
		$props .= "--p-{$n}:{$slice['pct']};--accum-{$n}:{$accum};";
		$items .= sprintf(
			'<li>%1$s %2$s%%</li>',
			esc_html( $slice['label'] ),
			esc_html( $slice['pct'] )
		);
		$accum += (float) $slice['pct'];
	}

	return sprintf(
		'<ul class="bbioon-pie" style="%s">%s</ul>',
		esc_attr( $props ),
		$items
	);
}

The CSS side is one rule per slice, exactly like the fork minus attr():

.bbioon-pie li:nth-child(3) {
  --p: var(--p-3);
  --accum: var(--accum-3);
}

A fifth slice becomes a new array entry. There’s no build step, no browser sniffing, and no library download. The numbers sit in the markup as real text. It’s the same instinct behind doing discounted price math in custom properties: the server supplies the values and the CSS paints them. If you want a small chart like this on a landing page or a WooCommerce report without adding Chart.js, that’s the kind of work I do for clients, so get in touch and I’ll wire it to your data.

Is the accessibility settled?

No, and the first commenter on the post says why: ul and li carry no chart semantics, and the counter-based percentages were verified against one screen reader. The author’s reply is the honest one: don’t treat it as solved, and test in your own context before production. My floor is simpler. Keep the label and the number as visible text in each li and treat the circle as decoration, because pseudo-element content is where screen reader behavior varies the most.

I’m still not sure what happens when attr() with types and sibling-index() are Baseline. Does the no-script chart survive contact with real feature requests, or does the first tooltip drag JavaScript back in? That decides whether this becomes a default or stays a demo, and I can’t tell yet. Either way I’d keep the loop in PHP, because that version works today.

author avatar
Ahmad Wael
I'm a WordPress and WooCommerce developer with 15+ years of experience building custom e-commerce solutions and plugins. I specialize in PHP development, following WordPress coding standards to deliver clean, maintainable code. Currently, I'm exploring AI and e-commerce by building multi-agent systems and SaaS products that integrate technologies like Google Gemini API with WordPress platforms, approaching every project with a commitment to performance, security, and exceptional user experience.

Leave a Comment