title: Light gridlines for already-existing axis
body: <p><strong>page.html</strong>:</p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;!-- https://bl.ocks.org/mbostock/3886208 --&gt;
  &lt;style&gt;
      #tooltip {
          position: absolute;
          width: 250px;
          z-index: 2;
          height: auto;
          padding: 10px;
          background-color: white;
          -webkit-border-radius: 10px;
          -moz-border-radius: 10px;
          border-radius: 10px;
          -webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
          -moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
          box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
          pointer-events: none;
      }
  
      .legend {
          font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
          font-size: 60%;
      }
  
      #tooltip.hidden {
          display: none;
      }
  
      #tooltip p {
          margin: 0;
          font-family: sans-serif;
          font-size: 16px;
          line-height: 20px;
      }
      g[class="col_1"] rect:hover {
          fill:#80061b;
      }
      g[class="col_2"] rect:hover {
          fill:#008394;
      }   
      div.slider-container {
        margin: 20px 20px 20px 80px;
      }
      div#month-slider {
        width: 50%;
        margin: 0px 0px 0px 300px;
        background:#e3eff4;
      }
  
      div#month-slider .ui-slider-handle {
        text-align: center;
      }
  
      .title {
          font-size: 30px;
          font-weight: bold;
      }
  
      .grid line {
          stroke: lightgrey;
          stroke-opacity: 0.7;
          shape-rendering: crispEdges;
      }
  
      .grid path {
          stroke-width: 0;
      }
  &lt;/style&gt;
  &lt;link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"&gt;
  &lt;script src="https://code.jquery.com/jquery-3.2.1.min.js"&gt;&lt;/script&gt;
  &lt;script
    src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"
    integrity="sha256-eGE6blurk5sHj+rmkfsGYeKyZx3M4bG+ZlFyA7Kns7E="
    crossorigin="anonymous"&gt;&lt;/script&gt;
  &lt;script src="https://d3js.org/d3.v4.js"&gt;&lt;/script&gt;
  &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/1.7.0/d3-legend.min.js"&gt;&lt;/script&gt;
  &lt;body&gt;
  
  &lt;div id="tooltip" class="hidden"&gt;
      &lt;p&gt;&lt;strong&gt;Month: &lt;/strong&gt;&lt;span id="month"&gt;&lt;/span&gt;&lt;p&gt;
      &lt;p&gt;&lt;strong&gt;&lt;span id="sessionLabel"&gt;&lt;/span&gt;: &lt;/strong&gt;&lt;span id="sessionCount"&gt;&lt;/span&gt;&lt;/p&gt;
  &lt;/div&gt;
  
  &lt;div class="slider-container"&gt;
    &lt;span&gt;Prior &lt;strong&gt;&lt;span id="value" class="value"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;
    &lt;div id="month-slider"&gt;
  
    &lt;/div&gt;
  &lt;/div&gt;
  
  &lt;script&gt;
  var margin = {top: 50, right: 20, bottom: 50, left: 80},
      width = 1300 - margin.left - margin.right,
      height = 600 - margin.top - margin.bottom;
  
  var svg = d3.select("body").append("svg")
              .attr("width", width + margin.left + margin.right)
              .attr("height", height + margin.top + margin.bottom);
  
  
  var g = svg.append("g")
             .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
  
  // parse the date / time
  // look at the .csv in Notepad! DO NOT LOOK AT EXCEL!
  var parseDate = d3.timeParse("%m/%d/%Y");
  
  var col_1 = "#CE1126",
      col_2 = "#00B6D0";
  
  var x = d3.scaleTime()
            .range([0, width - margin.left - margin.right]);
  var y = d3.scaleLinear().range([height, 0]);
  var z = d3.scaleOrdinal()
            .range([col_1, col_2]); // red and blue 
  
  var xMonthAxis = d3.axisBottom(x)
                .ticks(d3.timeMonth.every(1))
                .tickFormat(d3.timeFormat("%b")); // label every month
  
  var xYearAxis = d3.axisBottom(x)
                    .ticks(d3.timeYear.every(1))
                    .tickFormat(d3.timeFormat("%Y")); // label every year
  
  var yAxis = d3.axisLeft(y).tickFormat(d3.format('.2s')).tickSize(-width);
  
  var formatNum = d3.format(",")
  
  // load .csv file
  d3.csv("test_data.csv", function(d, i, columns) {
    for (i = 1, t = 0; i &lt; columns.length; ++i) t += d[columns[i]] = +d[columns[i]];
    d.total = t;
    return d;
  }, function(error, data){
      if (error) throw error;
  
      data.forEach(function(d) {
          d.date = parseDate(d.date);
      });
  
      var keys = data.columns.slice(1); 
  
      data.sort(function(a, b) { return b.date - a.date; });
  
  
      x.domain(d3.extent( data, function(d){ return d.date }) );
  
      var max = x.domain()[1];
      var min = x.domain()[0];
      var datePlusOneMonth = d3.timeDay.offset(d3.timeMonth.offset(max, 1), -1); // last day of current month: move up one month, back one day 
  
      x.domain([min,datePlusOneMonth]);
  
      y.domain([0, d3.max(data, function(d) { return d.total; })]).nice();
      z.domain(keys);
  
      // x-axis
      var monthAxis = g.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + height + ")")
        .call(xMonthAxis);
  
      var defaultSliderValue = 25;
  
      d3.select("#value")
        .text(function(){
          if (defaultSliderValue == 1){
              return defaultSliderValue + " month"
          } else {
              return defaultSliderValue + " months"
          }
      });
  
      // calculate offset date based on initial slider value
      var offsetDate = defaultSliderValue ? d3.timeDay.offset(d3.timeMonth.offset((new Date(datePlusOneMonth.getFullYear(), datePlusOneMonth.getMonth()-defaultSliderValue)), 1), -1) : min
      // set x domain and re-render xAxis
      x.domain([offsetDate, datePlusOneMonth]);
      g.select('.x.axis').call(xMonthAxis);
  
      var filteredData = data.filter(function(d) { return d.date &gt;= offsetDate; });   
      barWidth = (width - margin.right- margin.left)/(filteredData.length+1);    
  
      // the bars 
      g.append("g").classed('bars', true)
       .selectAll("g")
       .data(d3.stack().keys(keys)(filteredData))
       .enter().append("g")
       .attr('class', function(d) { return d.key; })
       .attr("fill", function(d) { return z(d.key); })
       .selectAll("rect")
       .data(function(d) { return d; })
       .enter()
       .append("rect")
       .attr("x", function(d) { return x(d.data.date); })
       .attr("y", function(d) { return y(d[1]); })
       .attr("height", function(d) { return y(d[0]) - y(d[1]); })
       .attr("width", barWidth)
       .on("mousemove", function(d) {
  
          //Get this bar's x/y values, then augment for the tooltip
          var xPosition = parseFloat(d3.mouse(this)[0]) + 88;
          var yPosition = parseFloat(d3.mouse(this)[1]) + 64;
          var value = d.data[d3.select(this.parentNode).attr('class')]; // differentiating between col1 and col2 values
          var valueClass = d3.select(this.parentNode).attr('class');
  
          //Update the tooltip position and value
          d3.select("#tooltip")
            .style("left", xPosition + "px")
            .style("top", yPosition + "px")   
  
          d3.select("#tooltip")  
            .select("#sessionCount")
            .text(formatNum(value)); // return the value 
  
          d3.select("#tooltip")                    
            .select("#month")
            .text(d3.timeFormat("%B %Y")(d.data.date)); // return the value 
  
          d3.select("#tooltip")                    
            .select("#sessionLabel")
            .text(valueClass); // return the class 
  
          //Show the tooltip
          d3.select("#tooltip").classed("hidden", false);
  
        })
       .on("mouseout", function() {
          //Hide the tooltip
          d3.select("#tooltip").classed("hidden", true);
  
       });
  
      const firstDataYear = x.domain()[0];
      if (firstDataYear.getMonth() == 11){ // When .getmonth() == 11, this shows two years overlapping with each other, making the label look ugly
          const firstDataYearOffset = d3.timeDay.offset(firstDataYear, 1);
          var tickValues = x.ticks().filter(function(d) { return !d.getMonth()});
          if(tickValues.length &amp;&amp; firstDataYearOffset.getFullYear() !== tickValues[1].getFullYear()) {
              tickValues = [firstDataYearOffset].concat(tickValues); 
          } else {
              tickValues = [firstDataYearOffset];
          }
      } else { 
          var tickValues = x.ticks().filter(function(d) { return !d.getMonth()});
          if(tickValues.length &amp;&amp; firstDataYear.getFullYear() !== tickValues[0].getFullYear()) {
              tickValues = [firstDataYear].concat(tickValues); 
          } else {
              tickValues = [firstDataYear];
          }
      }
  
      xYearAxis.tickValues(tickValues);
  
      var yearAxis = g.append("g")
                       .attr("class", "yearaxis axis")
                       .attr("transform", "translate(0," + (height + 25) + ")")
                       .call(xYearAxis);
  
      var valueAxis = g.append("g")
                   .attr("class", "y axis")
                   .call(yAxis);
  
      monthAxis.selectAll("g").select("text")
        .attr("transform","translate(" + barWidth/2 + ",0)");
  
      // add the Y gridlines
  
      var options = d3.keys(data[0]).filter(function(key) { return key !== "date"; }).reverse();
      var legend = svg.selectAll(".legend")
                      .data(options.slice().filter(function(type){ return type != "total"}))
                      .enter().append("g")
                      .attr("class", "legend")
                      .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
  
      legend.append("rect")
            .attr("x", width - 18)
            .attr("width", 18)
            .attr("height", 18)
            .attr('class', function(d) { return d; })
            .style("fill", z)
            .on("mouseover", function(d){
                  if (d == 'col_2') {
                      d3.selectAll(".col_2").style("fill", '#008394');
                  }
                  if (d == 'col_1') {
                      d3.selectAll(".col_1").style("fill", '#80061b');
                  };
  
              })
             .on("mouseout", function(){
                  d3.selectAll(".col_2").style("fill", col_2);
                  d3.selectAll(".col_1").style("fill", col_1);
              })
             ;
  
      function capitalizeFirstLetter(string) {
          return string.charAt(0).toUpperCase() + string.slice(1);
      }
  
      legend.append("text")
            .attr("x", width - 24)
            .attr("y", 9)
            .attr("dy", ".35em")
            .style("text-anchor", "end")
            .text(function(d) { return capitalizeFirstLetter(d); });
  
      // Initialize jQuery slider
  $('div#month-slider').slider({
      min: 1,
    max: 25,
    value: defaultSliderValue,
    create: function() {
      // add value to the handle on slider creation
      $(this).find('.ui-slider-handle').html($( this ).slider( "value" ));
    },
    slide: function(e, ui) {
      // change values on slider handle and label based on slider value   
      if (ui.value == 1){
          $('div.slider-container span.value').html(ui.value + ' month');
      } else { 
          $('div.slider-container span.value').html(ui.value + ' months');
      }
          $(e.target).find('.ui-slider-handle').html(ui.value);
  
      // calculate offset date based on slider value
      var offsetDate = ui.value ? d3.timeDay.offset(d3.timeMonth.offset((new Date(datePlusOneMonth.getFullYear(), datePlusOneMonth.getMonth()-ui.value)), 1), -1) : min
      // set x domain and re-render xAxis
      x.domain([offsetDate, datePlusOneMonth]);
      g.select('.x.axis').call(xMonthAxis);
  
      const firstDataYear = x.domain()[0];
      if (firstDataYear.getMonth() == 11){ // When .getmonth() == 11, this shows two years overlapping with each other, making the label look ugly
          const firstDataYearOffset = d3.timeDay.offset(firstDataYear, 1);
          var tickValues = x.ticks().filter(function(d) { return !d.getMonth()});
          if(tickValues.length == 2 &amp;&amp; firstDataYearOffset.getFullYear() !== tickValues[1].getFullYear()) {
              tickValues = [firstDataYearOffset].concat(tickValues); 
          } else {
              tickValues = [firstDataYearOffset];
          }
      } else { 
          var tickValues = x.ticks().filter(function(d) { return !d.getMonth()});
          if(tickValues.length &amp;&amp; firstDataYear.getFullYear() !== tickValues[0].getFullYear()) {
              tickValues = [firstDataYear].concat(tickValues); 
          } else {
              tickValues = [firstDataYear];
          }
      }
      xYearAxis.tickValues(tickValues);
      g.select('.yearaxis.axis').call(xYearAxis);
  
  
          // calculate filtered data based on new offset date, set y axis domain and re-render y axis
      var filteredData = data.filter(function(d) { return d.date &gt;= offsetDate; });
      y.domain([0, d3.max(filteredData, function(d) { return d.total; })]).nice();    
      g.select('.y.axis').transition().duration(200).call(yAxis);
  
  
      // re-render the bars based on new filtered data
      // the bars 
      var bars = g.select("g.bars")
       .selectAll("g")
       .data(d3.stack().keys(keys)(filteredData));
  
       var barRects = bars.enter().append("g").merge(bars)
       .attr('class', function(d) { return d.key; })
       .attr("fill", function(d) { return z(d.key); })
       .selectAll("rect")
       .data(function(d) { return d; });
  
       barRects.exit().remove();
  
       barRects.enter()
       .append("rect");
  
     barWidth = (width - margin.right- margin.left)/(filteredData.length+1);     
  
     monthAxis.selectAll("g").select("text")
        .attr("transform","translate(" + barWidth/2 + ",0)");
  
       g.select("g.bars").selectAll('g rect')
       .attr("x", function(d) { return x(d.data.date); })
       .attr("y", function(d) { return y(d[1]); })
       .attr("height", function(d) { return y(d[0]) - y(d[1]); })
       .attr("width", barWidth)
       .on("mousemove", function(d) {
  
          //Get this bar's x/y values, then augment for the tooltip
          var xPosition = parseFloat(d3.mouse(this)[0]) + 88;
          var yPosition = parseFloat(d3.mouse(this)[1]) + 64;
          var value = d.data[d3.select(this.parentNode).attr('class')]; // differentiating between col1 and col2 values
          var valueClass = d3.select(this.parentNode).attr('class');
  
          //Update the tooltip position and value
          d3.select("#tooltip")
            .style("left", xPosition + "px")
            .style("top", yPosition + "px")   
  
          d3.select("#tooltip")  
            .select("#sessionCount")
            .text(formatNum(value)); // return the value 
  
          d3.select("#tooltip")                    
            .select("#month")
            .text(d3.timeFormat("%B %Y")(d.data.date)); // return the value 
  
          d3.select("#tooltip")                    
            .select("#sessionLabel")
            .text(valueClass); // return the class 
  
          //Show the tooltip
          d3.select("#tooltip").classed("hidden", false);
       })
       .on("mouseout", function() {
          //Hide the tooltip
          d3.select("#tooltip").classed("hidden", true);
       });
  
    }
  });
  
  });
  
  g.append("text")
     .attr("class", "title")
     .attr("x", (width / 2))             
     .attr("y", 0 - (margin.top / 2))
     .attr("text-anchor", "middle")  
     .text("Title");
  &lt;/script&gt;
  
  &lt;/body&gt;
  </code></pre>
  
  <p><strong>test_data.csv</strong>:</p>
  
  <pre><code>date,col_1,col_2
  11/1/2012,1977652,1802851
  12/1/2012,1128739,948687
  1/1/2013,1201944,1514667
  2/1/2013,1863148,1834006
  3/1/2013,1314851,1906060
  4/1/2013,1283943,1978702
  5/1/2013,1127964,1195606
  6/1/2013,1773254,977214
  7/1/2013,1929574,1127450
  8/1/2013,1980411,1808161
  9/1/2013,1405691,1182788
  10/1/2013,1336790,937890
  11/1/2013,1851053,1358400
  12/1/2013,1472623,1214610
  1/1/2014,1155116,1757052
  2/1/2014,1571611,1935038
  3/1/2014,1898348,1320348
  4/1/2014,1444838,1934789
  5/1/2014,1235087,950194
  6/1/2014,1272040,1580656
  7/1/2014,980781,1680164
  8/1/2014,1391291,1115999
  9/1/2014,1211125,1542148
  10/1/2014,1020824,1782795
  11/1/2014,1685081,926612
  12/1/2014,1469254,1767071
  1/1/2015,1168523,935897
  2/1/2015,1602610,1450541
  3/1/2015,1830278,1354876
  4/1/2015,1275158,1412555
  5/1/2015,1560961,1839718
  6/1/2015,949948,1587130
  7/1/2015,1413765,1494446
  8/1/2015,1166141,1305105
  9/1/2015,958975,1202219
  10/1/2015,902696,1023987
  11/1/2015,961441,1865628
  12/1/2015,1363145,1954046
  1/1/2016,1862878,1470741
  2/1/2016,1723891,1042760
  3/1/2016,1906747,1169012
  4/1/2016,1963364,1927063
  5/1/2016,1899735,1936915
  6/1/2016,1300369,1430697
  7/1/2016,1777108,1401210
  8/1/2016,1597045,1566763
  9/1/2016,1558287,1140057
  10/1/2016,1965665,1953595
  11/1/2016,1800438,937551
  12/1/2016,1689152,1221895
  1/1/2017,1607824,1963282
  2/1/2017,1878431,1415658
  3/1/2017,1730296,1947106
  4/1/2017,1956756,1696780
  5/1/2017,1746673,1662892
  6/1/2017,989702,1537646
  7/1/2017,1098812,1592064
  8/1/2017,1861973,1892987
  9/1/2017,1129596,1406514
  10/1/2017,1528632,1725020
  11/1/2017,925850,1795575
  </code></pre>
  
  <p><strong>Output</strong>:</p>
  
  <p><a href="https://i.stack.imgur.com/EgsPo.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/EgsPo.png" alt="enter image description here"></a></p>
  
  <p>Two things I would like changed about this:</p>
  
  <p>1) The y-axis grid lines should not be black, but the same color as what is at <a href="https://bl.ocks.org/d3noob/c506ac45617cf9ed39337f99f8511218" rel="nofollow noreferrer">https://bl.ocks.org/d3noob/c506ac45617cf9ed39337f99f8511218</a>, with CSS</p>
  
  <pre><code>.grid line {
    stroke: lightgrey;
    stroke-opacity: 0.7;
    shape-rendering: crispEdges;
  }
  </code></pre>
  
  <p>The ticks and y-axis themselves should remain black.</p>
  
  <p>2) The grid line should not extend past the right end of the last bar above. </p>
  
  <p>I already attempted the method in the link above, and the color is correct, but the hover events no longer work.</p>