Accepted answer

I am not an expert in d3.js, but I think this can be easily done. There are different ways to go about it. I have created a pen for your use case.

I will paste the important part of the code below. In your chart, you will have to certainly make some adjustments to suit your needs. Feel free to play around with the values until you feel they are stable.

// Your array containing labels for left and right values

var leftSideData = ["left1", "left2", "left3", "left4", "left5", "left6", "left7", "left8"];

var rightSideData = ["right1", "right2", "right3", "right4", "right5", "right6", "right7", "right8"];

var left = svg.selectAll(".leftData")
    .attr("class", "leftVal")
    .attr("transform", function(d, i) {
      return "translate(0," + i * 57 + ")";

    .attr("x", 0)
    .attr("y", 9)
    .attr("dy", ".35em")
    .style("text-anchor", "end")
    .text(function(d) {
      return d;

  var right = svg.selectAll(".rightData")
    .attr("class", "rightVal")
    .attr("transform", function(d, i) {
      return "translate(0," + i * 57 + ")";

    .attr("x", width + 30)
    .attr("y", 9)
    .attr("dy", ".35em")
    .style("text-anchor", "end")
    .text(function(d) {
      return d;

I won't say this is perfect, but I hope you get an idea about how to approach it. All the best!!


It's funny, just by asking the q on SE I find it helps me reformulate the problem.. and then some time later a new try yields a result. Anyone else find that?

I managed to make it work by changing the way the SVG was created. So I now have the following structure:

><g> (one for each bar)
><other stuff like axies>

It turns out that <text> elements cannot be added to <rect> elements (well they can, be added but they won't render).

the code is:

var data = [10,2,4,-10,...etc...];

var leftLabels = ["left 1","left 1", ...etc...];

var rightLabels = ["right 1","right 2", ...etc...];

//chart dimentions
var margin = { top: 20, right: 30, bottom: 40, left: 30 },
    width = 600 - margin.left - margin.right,
    barHeight = 30,
    height = barHeight * data.length;

//chart bar scaling
var x = d3.scale.linear()
.range([100, width-100]);

var y = d3.scale.ordinal()
.rangeRoundBands([0, height], 0.1);

var chart =".chartsvg")
.attr("width", width + margin.left + margin.right)
.attr("height", barHeight * data.length + + margin.bottom)
.attr("transform", "translate(" + margin.left + "," + + ")");

x.domain([d3.min(data), d3.max(data)]);

//append a g for each data item 
var bar = chart.selectAll(".bar")

//in each bar add a rect for the bar chart bar
  .attr("class", function (d) { return "bar--" + (d < 0 ? "negative" : "positive"); })
  .attr("x", function (d) { return x(Math.min(0, d)); })
  .attr("y", function (d, i) { return i* barHeight; })
  .attr("width", function (d) { return Math.abs(x(d) - x(0)); })
  .attr("height", barHeight-1);

//append the labels to each g using the label data
    .attr("x", width)
    .attr("y", function (d, i) { return (i * barHeight)+barHeight/2; })
    .attr("dy", ".5em")
    .text(function (d) { return d; });

    .attr("x", 0)
    .attr("y", function (d, i) { return (i * barHeight) + barHeight / 2; })
    .attr("dy", ".5em")
    .attr("text-anchor", "start")
    .text(function (d) { return d; });
//then append axis etc...

Formatting: something else to note. It turns out that to color the text in the label you need to use "stroke" and "fill" attributes. These are broadly equiv to the HTML "color" attribute on text.

Related Query

More Query from same tag