This is an example of what you should be able to do once the major browsers implement some seriously cool features in the CSS3 draft spec as of April, 2016:
--name: value
assignment and var(--name)
accessor syntax. (Already implemented by Chrome, Firefox, and Webkit!)px
or em
from a percentage. (Partially implemented in Chrome, Firefox, and Safari.)attr(attr-name units)
. (Not yet implemented in any major browser.)Together, these features would enable us to use HTML element attribute values as the basis for calculated values in CSS on a per-element basis, and define (then change) which property the values are applied to. This would open up possibilities for more data-driven design entirely in CSS, without the need for JavaScript.
Note: I’ve used the x-
prefix to denote HTML custom elements, which are a great way to simplify your markup, encapsulate your CSS, and extend the DOM element API via JavaScript. You could just as easily HTML5 elements or classes, though.
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="bar-chart.css">
</head>
<body>
<x-bar-chart min="0" max="200">
<x-bar value="200">A: $100</x-bar>
<x-bar value="150">B: $150</x-bar>
<x-bar value="25">C: $25</x-bar>
</x-bar-chart>
</body>
</html>
/* The bar chart container establishes a common min and max */
x-bar-chart {
--min: 0;
--max: 100;
display: block;
}
x-bar {
/* Each bar has its own value */
--value: 0;
/* And its size is a variable so that we can use it any property,
or even set directly. This should be a number between 0 and 1. */
--size: calc((var(--value) - var(--min)) / (var(--max) - var(--min))));
display: block;
margin-bottom: .5em;
}
/* If you render the bar itself as generated content,
then the content (e.g. text labels) can flow independently
of the element's own bounding box, precluding the need for
overflow: visible */
x-bar::after {
background: slateblue;
content: "";
display: block;
/* by default, a bar has a percentage width based on its size */
height: 1em;
width: calc(100% * var(--size));
}
/* bars can get their value from the value attribute */
x-bar[value] {
/* this syntax parses the value attribute as a number,
rather than using a unit length */
--value: attr(value number);
}
/* charts *and* bars could establish their own min and max */
x-bar-chart[min],
x-bar[min] {
--min: attr(min number);
}
x-bar-chart[max],
x-bar[max] {
--max: attr(max number);
}
@media screen and (min-width: 640px) {
/* then, if we want to get *really* fancy, we can
make the chart go vertical on wider screens */
x-bar-chart {
display: flex;
}
x-bar {
align-self: bottom;
flex: 1;
position: relative;
margin-bottom: 0;
}
/* spacing between bars */
x-bar + x-bar {
margin-left: .5em;
}
x-bar::after {
position: absolute;
bottom: 0;
height: calc(100% * var(--size));
width: 100%;
}
}