Cascading Stylesheets (CSS) have been with us since 1996, making them one of the oldest staples of the Web, even though they only reached widespread popularity with the tables versus CSS wars of the early 2000s.
You're probably familiar with using CSS for styling HTML. So, this section will be a refreshing breeze after all that weird-looking SVG stuff.
My favorite thing about CSS is its simplicity; consider the following code:
selector {
attribute: value;
}
That describes CSS better than I can--you use selectors to modify properties using values. Although there's a bit more to it, particularly in terms of how properties cascade down the DOM tree, the above is pretty much it.
We've been using selectors all this time. A selector is any string that describes one or more elements in a DOM tree.
To review:
- path: Selects all the <path> element
- .axis: Selects all the elements with a class="axis" attribute
- .axis line: Selects all the <line> elements that are children of the class="axis" elements
- .axis, line: Selects all the class="axis" and <line> elements
D3 selections are a subset of CSS selectors; so, any selection you can make with d3.selectAll , you can specify using CSS.
We can invoke CSS with D3 in three ways:
- Defining a class attribute with the .attr() method, which can be brittle
- Using the .classed() method, the preferred way to define classes
- Defining styling directly with the .style() method
Let's throw readability to the wind for a second and make our axes totally trippy.
Go into index.css and add the following at the end:
.trippy {
animation: wheee 3s infinite;
fill: green !important;
}
@keyframes wheee {
0% {stroke: red;}
25% {stroke: yellow;}
50% {stroke: blue;}
75% {stroke: green;}
100% {stroke: red;}
}
Now, ensure that the following line is in lib/main.js to load the CSS into your HTML file; you can also use the <link> tags in your HTML, but again, that's boring:
import '../styles/index.css';
Now, we amend the drawing loop from earlier to look as follows:
axes.forEach((axis, i) =>
chart.container.append('g')
.data(d3.range(0, amount))
.classed('trippy', i % 2)
.attr('transform', `translate(0,${(i * 50) + chart.margin.top})`)
.call(axis)
);
We'll have none of that foolishness with specifying the same values five times in a row. Using the .classed() function, we add the .trippy class to every second axis. .classed() adds the specified class if the second argument is true or missing, and removes it otherwise. All the numbers on the second and fourth axes now change color, and it's amazing and totally life reaffirming.
I hope that you're getting excited, because we're finally through this terribly boring review chapter, and we'll soon move on to all kinds of supreme awesomeness! We'll be talking more about animation in Chapter 5, Defining the User Experience - Animation and Interaction.