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 divs 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 and y manually in these examples, instead of binding data and using scales. Your code will definitely be more complicated.

Open example in new window

...
svg.append("text")
	.text("This is text")
	.attr("x", 20)
	.attr("y", 20);

Open example in new window


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!

Open example in new window

...
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);

Open example in new window

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.

Open example in new window

...
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);

Open example in new window


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.

Open example in new window

...
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");

Open example in new window

Open example in new window

...
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");

Open example in new window

Open example in new window

...
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");

Open example in new window


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.

Open example in new window

<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>

Open example in new window