Text elements in D3
Text in D3 is fun and cool. Let’s talk about how fun and cool it is.
The element itself
Text in D3 uses the <text> element. SVG-wise, they look like this:
<text x="40" y="80">Hello I am text</text>
You set the attributes, as always, with attr()
, and you set the text inside like .text("Hello I am text")
.
Wrapping text
The first rule of text elements in D3 is you cannot wrap text. You can try and you might want to, but honestly save that for outside of your visualziation.
(And yes, there are plugins and blah blah blah to do this, but honestly, put your text outside of the visualization, D3 can fill in normal div
s and p
tags, too.)
Positioning text by itself: x
and y
Text in D3 is positioned two ways. One way is good if you’re just positioning text by itself, the other is good if you’re annotating elements. The first method is to just position using x
and y
.
Note: I’m just setting the
x
andy
manually in these examples, instead of binding data and using scales. Your code will definitely be more complicated.
...
svg.append("text")
.text("This is text")
.attr("x", 20)
.attr("y", 20);
Positioning text when annotating elements: dx
and dy
This is normally fine, but sometimes you’re annotating elements. That will make your text show up on top of the element!
...
svg.append("circle")
.attr("cx", 20)
.attr("cy", 20)
.attr("r", 10);
svg.append("text")
.text("This is a circle")
.attr("x", 20)
.attr("y", 20);
You probably want to use the same scale to position the circles and the text, so this is a big problem! Luckily, the text
element also has dx
and dy
, which mean “offset from the x
and y
” - so first you position on top of your data element with x
and y
, then use dx
and dy
to move it off to the side.
Here’s the same code as above but with a dx
and dy
specified.
...
svg.append("circle")
.attr("cx", 20)
.attr("cy", 20)
.attr("r", 10);
svg.append("text")
.text("This is a circle")
.attr("x", 20)
.attr("y", 20)
.attr("dx", 12)
.attr("dy", 5);
Aligning your text: text-anchor
You can also align your text to the left/right/center of the coordinate you position it at. This is important if you want to label below (usually center aligned), or to the left or right of the element.
...
svg.append("circle")
.attr("cx", 20)
.attr("cy", 20)
.attr("r", 2);
svg.append("text")
.attr("x", 20)
.attr("y", 20)
.attr("text-anchor", "start")
.text("Text starts at x/y");
...
svg.append("circle")
.attr("cx", 20)
.attr("cy", 20)
.attr("r", 2);
svg.append("text")
.attr("x", 20)
.attr("y", 20)
.attr("text-anchor", "end")
.text("Text ends at x/y");
...
svg.append("circle")
.attr("cx", 20)
.attr("cy", 20)
.attr("r", 2);
svg.append("text")
.attr("x", 20)
.attr("y", 20)
.attr("text-anchor", "middle")
.text("Text centered around x/y");
Styling your text
The easiest way to style your text is to just use CSS. Below I’m going to use inline CSS, but you should definitely use an external CSS file (see the CSS section).
For the attributes, it’s an odd combination of SVG-specific styles (fill
and stroke
) but the normal font-family
etc from styling normal HTML.
<style>
text {
font-family: 'Comic Sans MS', 'Papyrus', sans-serif;
font-size: 32px;
font-weight: bold;
fill: red;
}
</style>
<script>
...
svg.append("text")
.attr("x", 20)
.attr("y", 20)
.text("This is well-styled text");
</script>