title: Styling tooltip in multi-line D3.js line chart
body: <p>i have made a multi-line chart using D3.js with tooltips. Everything is working fine in this graph but i want to add styling to tooltips for all the charts in the graph but unable to do so.</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>var margin = {
      top: 20,
      right: 30,
      bottom: 30,
      left: 40
    },
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;
  
  var z = d3.scale.category20c();
  
  var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
  
  var parseDate = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ");
  
  var data = [{
    data: [
      ["2016-01-20T05:31:17.000Z", 95.9, {}],
      ["2016-01-20T05:31:47.000Z", 95.9, {}],
      ["2016-01-20T05:32:17.000Z", 95.4, {}],
      ["2016-01-20T05:32:47.000Z", 96.1, {}],
      ["2016-01-20T05:33:17.000Z", 95.7, {}],
      ["2016-01-20T05:33:47.000Z", 95.9, {}],
      ["2016-01-20T05:34:17.000Z", 95.5, {}],
      ["2016-01-20T05:34:47.000Z", 95.9, {}],
      ["2016-01-20T05:35:17.000Z", 95.8, {}],
      ["2016-01-20T05:35:47.000Z", 95.9, {}],
      ["2016-01-20T05:36:17.000Z", 95.7, {}],
      ["2016-01-20T05:36:47.000Z", 95.7, {}],
      ["2016-01-20T05:37:17.000Z", 95.9, {}],
      ["2016-01-20T05:37:47.000Z", 95.5, {}],
      ["2016-01-20T05:38:17.000Z", 95.4, {}],
      ["2016-01-20T05:38:47.000Z", 95.8, {}],
      ["2016-01-20T05:39:17.000Z", 96.0, {}],
      ["2016-01-20T05:39:47.000Z", 96.1, {}],
      ["2016-01-20T05:40:17.000Z", 95.8, {}],
      ["2016-01-20T05:40:47.000Z", 96.0, {}],
      ["2016-01-20T05:41:17.000Z", 95.9, {}],
      ["2016-01-20T05:41:47.000Z", 94.9, {}],
      ["2016-01-20T05:42:17.000Z", 95.8, {}],
      ["2016-01-20T05:42:47.000Z", 95.9, {}],
      ["2016-01-20T05:43:17.000Z", 95.8, {}],
      ["2016-01-20T05:43:47.000Z", 96.0, {}],
      ["2016-01-20T05:44:17.000Z", 95.7, {}],
      ["2016-01-20T05:44:47.000Z", 96.0, {}],
      ["2016-01-20T05:45:17.000Z", 95.9, {}],
      ["2016-01-20T05:45:47.000Z", 96.0, {}],
      ["2016-01-20T05:46:17.000Z", 95.8, {}],
      ["2016-01-20T05:46:47.000Z", 96.0, {}],
      ["2016-01-20T05:47:17.000Z", 95.7, {}],
      ["2016-01-20T05:47:47.000Z", 96.2, {}],
      ["2016-01-20T05:48:17.000Z", 95.8, {}],
      ["2016-01-20T05:48:47.000Z", 95.9, {}],
      ["2016-01-20T05:49:17.000Z", 95.7, {}],
      ["2016-01-20T05:49:47.000Z", 95.9, {}],
      ["2016-01-20T05:50:18.000Z", 95.7, {}],
      ["2016-01-20T05:50:48.000Z", 95.8, {}],
      ["2016-01-20T05:51:18.000Z", 95.7, {}],
      ["2016-01-20T05:51:48.000Z", 95.9, {}],
      ["2016-01-20T05:52:18.000Z", 95.5, {}],
      ["2016-01-20T05:52:48.000Z", 95.9, {}],
      ["2016-01-20T05:53:18.000Z", 95.8, {}],
      ["2016-01-20T05:53:48.000Z", 95.9, {}],
      ["2016-01-20T05:54:18.000Z", 95.7, {}],
      ["2016-01-20T05:54:48.000Z", 95.9, {}],
      ["2016-01-20T05:55:18.000Z", 95.8, {}],
      ["2016-01-20T05:55:48.000Z", 95.8, {}],
      ["2016-01-20T05:56:18.000Z", 95.6, {}],
      ["2016-01-20T05:56:48.000Z", 95.7, {}],
      ["2016-01-20T05:57:18.000Z", 95.7, {}],
      ["2016-01-20T05:57:48.000Z", 95.8, {}],
      ["2016-01-20T05:58:18.000Z", 95.7, {}],
      ["2016-01-20T05:58:48.000Z", 95.7, {}],
      ["2016-01-20T05:59:18.000Z", 95.6, {}],
      ["2016-01-20T05:59:48.000Z", 95.8, {}],
      ["2016-01-20T06:00:18.000Z", 95.7, {}],
      ["2016-01-20T06:00:48.000Z", 95.7, {}],
      ["2016-01-20T06:01:18.000Z", 95.6, {}],
      ["2016-01-20T06:01:48.000Z", 95.7, {}],
      ["2016-01-20T06:02:18.000Z", 95.8, {}],
      ["2016-01-20T06:02:48.000Z", 95.8, {}],
      ["2016-01-20T06:03:18.000Z", 95.8, {}],
      ["2016-01-20T06:03:48.000Z", 95.8, {}],
      ["2016-01-20T06:04:18.000Z", 95.8, {}],
      ["2016-01-20T06:04:48.000Z", 95.8, {}],
      ["2016-01-20T06:05:18.000Z", 95.7, {}],
      ["2016-01-20T06:05:48.000Z", 95.7, {}]
    ],
    label: "a"
  }, {
    data: [
      ["2016-01-20T05:31:17.000Z", 90.9, {}],
      ["2016-01-20T05:31:47.000Z", 91.9, {}],
      ["2016-01-20T05:32:17.000Z", 92.4, {}],
      ["2016-01-20T05:32:47.000Z", 90.1, {}],
      ["2016-01-20T05:33:17.000Z", 89.7, {}],
      ["2016-01-20T05:33:47.000Z", 91.9, {}],
      ["2016-01-20T05:34:17.000Z", 85.5, {}],
      ["2016-01-20T05:34:47.000Z", 93.9, {}],
      ["2016-01-20T05:35:17.000Z", 94.8, {}],
      ["2016-01-20T05:35:47.000Z", 93.9, {}],
      ["2016-01-20T05:36:17.000Z", 92.7, {}],
      ["2016-01-20T05:36:47.000Z", 95.7, {}],
      ["2016-01-20T05:37:17.000Z", 92.9, {}],
      ["2016-01-20T05:37:47.000Z", 93.5, {}],
      ["2016-01-20T05:38:17.000Z", 93.4, {}],
      ["2016-01-20T05:38:47.000Z", 93.8, {}],
      ["2016-01-20T05:39:17.000Z", 93.0, {}],
      ["2016-01-20T05:39:47.000Z", 93.1, {}],
      ["2016-01-20T05:40:17.000Z", 93.8, {}],
      ["2016-01-20T05:40:47.000Z", 93.0, {}],
      ["2016-01-20T05:41:17.000Z", 93.9, {}],
      ["2016-01-20T05:41:47.000Z", 93.9, {}],
      ["2016-01-20T05:42:17.000Z", 92.8, {}],
      ["2016-01-20T05:42:47.000Z", 92.9, {}],
      ["2016-01-20T05:43:17.000Z", 93.8, {}],
      ["2016-01-20T05:43:47.000Z", 93.0, {}],
      ["2016-01-20T05:44:17.000Z", 93.7, {}],
      ["2016-01-20T05:44:47.000Z", 93.0, {}],
      ["2016-01-20T05:45:17.000Z", 93.9, {}],
      ["2016-01-20T05:45:47.000Z", 93.0, {}],
      ["2016-01-20T05:46:17.000Z", 93.8, {}],
      ["2016-01-20T05:46:47.000Z", 96.0, {}],
      ["2016-01-20T05:47:17.000Z", 92.7, {}],
      ["2016-01-20T05:47:47.000Z", 92.2, {}],
      ["2016-01-20T05:48:17.000Z", 92.8, {}],
      ["2016-01-20T05:48:47.000Z", 92.9, {}],
      ["2016-01-20T05:49:17.000Z", 92.7, {}],
      ["2016-01-20T05:49:47.000Z", 92.9, {}],
      ["2016-01-20T05:50:18.000Z", 93.7, {}],
      ["2016-01-20T05:50:48.000Z", 93.8, {}],
      ["2016-01-20T05:51:18.000Z", 92.7, {}],
      ["2016-01-20T05:51:48.000Z", 92.9, {}],
      ["2016-01-20T05:52:18.000Z", 92.5, {}],
      ["2016-01-20T05:52:48.000Z", 94.9, {}],
      ["2016-01-20T05:53:18.000Z", 94.8, {}],
      ["2016-01-20T05:53:48.000Z", 94.9, {}],
      ["2016-01-20T05:54:18.000Z", 94.7, {}],
      ["2016-01-20T05:54:48.000Z", 94.9, {}],
      ["2016-01-20T05:55:18.000Z", 94.8, {}],
      ["2016-01-20T05:55:48.000Z", 93.8, {}],
      ["2016-01-20T05:56:18.000Z", 94.6, {}],
      ["2016-01-20T05:56:48.000Z", 94.7, {}],
      ["2016-01-20T05:57:18.000Z", 93.7, {}],
      ["2016-01-20T05:57:48.000Z", 93.8, {}],
      ["2016-01-20T05:58:18.000Z", 93.7, {}],
      ["2016-01-20T05:58:48.000Z", 93.7, {}],
      ["2016-01-20T05:59:18.000Z", 93.6, {}],
      ["2016-01-20T05:59:48.000Z", 93.8, {}],
      ["2016-01-20T06:00:18.000Z", 93.7, {}],
      ["2016-01-20T06:00:48.000Z", 93.7, {}],
      ["2016-01-20T06:01:18.000Z", 93.6, {}],
      ["2016-01-20T06:01:48.000Z", 94.7, {}],
      ["2016-01-20T06:02:18.000Z", 94.8, {}],
      ["2016-01-20T06:02:48.000Z", 94.8, {}],
      ["2016-01-20T06:03:18.000Z", 94.8, {}],
      ["2016-01-20T06:03:48.000Z", 94.8, {}],
      ["2016-01-20T06:04:18.000Z", 94.8, {}],
      ["2016-01-20T06:04:48.000Z", 94.8, {}],
      ["2016-01-20T06:05:18.000Z", 94.7, {}],
      ["2016-01-20T06:05:48.000Z", 94.7, {}]
    ],
    label: "b"
  }]
  
  
  var x = d3.time.scale()
    .range([0, width]);
  
  var y = d3.scale.linear()
    .range([height, 0]);
  
  var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");
  
  var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");
  
  var line = d3.svg.line()
    .interpolate("monotone")
    .x(function(d) {
      return x(parseDate.parse(d[0]));
    })
    .y(function(d) {
      return y(d[1]);
    });
  
  var ary = [];
  data.forEach(function(d) {
    ary.push(d.data);
  });
  
  x.domain(d3.extent(d3.merge(ary), function(d) {
    return parseDate.parse(d[0]);
  }));
  
  y.domain([
    d3.min(data, function(c) {
      return d3.min(c.data, function(v) {
        return v[1];
      });
    }),
    d3.max(data, function(c) {
      return d3.max(c.data, function(v) {
        return v[1];
      });
    })
  ]);
  
  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);
  
  svg.append("g")
    .attr("class", "y axis")
    .call(yAxis);
  
  var series = svg.selectAll(".series")
    .data(data)
    .enter().append("g")
    .attr("class", "series");
  
  series.append("path")
    .attr("class", "line")
    .attr("d", function(d) {
      return line(d.data);
    })
    .style("stroke", function(d, i) {
      return z(i);
    });
  
  series.append("text")
    .datum(function(d) {
      return {
        label: d.label,
        data: d.data[d.data.length - 1]
      };
    })
    .attr("transform", function(d) {
      return "translate(" + x(parseDate.parse(d.data[0])) + "," + y(d.data[1]) + ")";
    })
    .attr("x", 3)
    .attr("dy", ".35em");
  
  var mouseG = svg.append("g")
    .attr("class", "mouse-over-effects");
  
  mouseG.append("path") // this is the black vertical line to follow mouse
    .attr("class", "mouse-line")
    .style("stroke", "black")
    .style("stroke-width", "1px")
    .style("opacity", "0");
  
  var lines = document.getElementsByClassName('line');
  
  var mousePerLine = mouseG.selectAll('.mouse-per-line')
    .data(data)
    .enter()
    .append("g")
    .attr("class", "mouse-per-line");
  
  mousePerLine.append("circle")
    .attr("r", 7)
    .style("stroke", function(d, i) {
      return z(i);
    })
    .style("fill", "none")
    .style("stroke-width", "1px")
    .style("opacity", "0");
  
  mousePerLine.append("text")
    .attr("transform", "translate(10,3)");
  
  mouseG.append('svg:rect') // append a rect to catch mouse movements on canvas
    .attr('width', width) // can't catch mouse events on a g element
    .attr('height', height)
    .attr('fill', 'none')
    .attr('pointer-events', 'all')
    .on('mouseout', function() { // on mouse out hide line, circles and text
      d3.select(".mouse-line")
        .style("opacity", "0");
      d3.selectAll(".mouse-per-line circle")
        .style("opacity", "0");
      d3.selectAll(".mouse-per-line text")
        .style("opacity", "0");
    })
    .on('mouseover', function() { // on mouse in show line, circles and text
      d3.select(".mouse-line")
        .style("opacity", "1");
      d3.selectAll(".mouse-per-line circle")
        .style("opacity", "1");
      d3.selectAll(".mouse-per-line text")
        .style("opacity", "1");
    })
    .on('mousemove', function() { // mouse moving over canvas
      var mouse = d3.mouse(this);
      d3.select(".mouse-line")
        .attr("d", function() {
          var d = "M" + mouse[0] + "," + height;
          d += " " + mouse[0] + "," + 0;
          return d;
        });
  
      d3.selectAll(".mouse-per-line")
        .attr("transform", function(d, i) {
          console.log(width / mouse[0])
          var xDate = x.invert(mouse[0]),
            bisect = d3.bisector(function(d) {
              return d[0];
            }).right;
          var idx = bisect(d.data, xDate);
  
          var beginning = 0,
            end = lines[i].getTotalLength(),
            target = null;
  
          while (true) {
            target = Math.floor((beginning + end) / 2);
            var pos = lines[i].getPointAtLength(target);
            if ((target === end || target === beginning) &amp;&amp; pos.x !== mouse[0]) {
              break;
            }
            if (pos.x &gt; mouse[0]) end = target;
            else if (pos.x &lt; mouse[0]) beginning = target;
            else break; //position found
          }
  
          d3.select(this).select('text')
            .text(y.invert(pos.y).toFixed(2));
  
          return "translate(" + mouse[0] + "," + pos.y + ")";
        });
    });</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>text.inner-circle {
    font-weight: 400;
    font-size: 12px;
    text-transform: uppercase;
  }
  
  text.inner-text {
    font-weight: 400;
    font-size: 36px;
    font-family: 'Metric Regular', 'Metric';
    text-align: center;
    font-style: normal;
    text-transform: uppercase;
  }
  
  path {
    stroke: steelblue;
    stroke-width: 2;
    fill: none;
  }
  
  .axis path,
  .axis line {
    fill: none;
    stroke: grey;
    stroke-width: 2;
    shape-rendering: crispEdges;
  }
  
  .grid .tick {
    stroke: lightgrey;
    stroke-opacity: 0.7;
    shape-rendering: crispEdges;
  }
  
  .grid path {
    stroke-width: 0;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"&gt;&lt;/script&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>I want to add a small white box at the top of each chart line with both x and y values. Please help me out.</p>
  
  <p><a href="https://jsfiddle.net/Lk4k2L8o/" rel="nofollow">JSFIDDLE</a></p>