What is the difference between svg's x and dx attribute?

Svgd3.js

Svg Problem Overview


What is the difference between svg's x and dx attribute (or y and dy)? When would be a proper time to use the axis shift attribute (dx) versus the location attribute (x)?

For example, I have noticed a lot of d3 examples doing something like this

chart.append("text")
   .attr("x", 0)
   .attr("y", 0)
   .attr("dy", -3)
   .text("I am a label")

What is the advantage or reasoning for setting both y and dy when the following seems to do the same thing?

chart.append("text")
   .attr("x", 0)
   .attr("y", -3)
   .text("I am a label")

Svg Solutions


Solution 1 - Svg

x and y are absolute coordinates and dx and dy are relative coordinates (relative to the specified x and y).

In my experience, it is not common to use dx and dy on <text> elements (although it might be useful for coding convenience if you, for example, have some code for positioning text and then separate code for adjusting it).

dx and dy are mostly useful when using <tspan> elements nested inside a <text> element to establish fancier multi-line text layouts.

For more details you can check out the Text section of the SVG spec.

Solution 2 - Svg

To add to Scott's answer, dy used with em (font size units) is very useful for vertically aligning text relative to the absolute y coordinate. This is covered in the MDN dy text element example.

Using dy=0.35em can help vertically centre text regardless of font size. It also helps if you want to rotate the centre of your text around a point described by your absolute coordinates.

<style>
text { fill: black; text-anchor: middle; }
line { stroke-width: 1; stroke: lightgray; }
</style>


<script>
dataset = d3.range(50,500,50);

svg = d3.select("body").append("svg");
svg.attr('width',500).attr('height', 500);

svg.append("line").attr('x1', 0).attr('x2', 500).attr('y1', 100).attr('y2', 100);
svg.append("line").attr('x1', 0).attr('x2', 500).attr('y1', 200).attr('y2', 200);

group = svg.selectAll("g")
    .data(dataset)
    .enter()
    .append("g");

// Without the dy=0.35em offset
group.append("text")
    .text("My text")
    .attr("x",function (d) {return d;})
    .attr("y",100)
    .attr("transform", function(d, i) {return "rotate("+45*i+","+d+",100)";});

// With the dy=0.35em offset
group.append("text")
    .text("My text")
    .attr("x",function (d) {return d;})
    .attr("y",200)
    .attr("dy","0.35em")
    .attr("transform", function(d, i) {return "rotate("+45*i+","+d+",200)";});
<script>

View it in Codepen

If you don't include "dy=0.35em", the words rotate around the bottom of the text and after 180 align below where they were before rotation. Including "dy=0.35em" rotates them around the centre of the text.

Note that dy can't be set using CSS.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNathan ReeseView Question on Stackoverflow
Solution 1 - SvgScott CameronView Answer on Stackoverflow
Solution 2 - Svgangus lView Answer on Stackoverflow