19

So I made a chart in d3 and used the default x axis format,

d3.axisBottom(x)

which output the following graph:

months and years

How can I manually create and customize this format? In particular, I'd like to use short month names, like "Oct", so that "October" doesn't obscure the following year label.

Matthew James Davis
  • 12,134
  • 7
  • 61
  • 90

1 Answers1

36

Use tickFormat to format the ticks in your x axis. In your case, .tickFormat(d3.timeFormat("%b")) will return short month names (but it will make the year disappear).

Here is the demo:

var svg = d3.select("body")
  .append("svg")
  .attr("width", 500)
  .attr("height", 100)   
            
var xScale = d3.scaleTime()
  .domain([new Date("2014-01-01"), new Date("2016-01-01")])
  .range([0, 450]);
        
var xAxis = d3.axisBottom(xScale)
  .tickFormat(d3.timeFormat("%b"));
  
svg.append("g")
  .call(xAxis);
<script src="https://d3js.org/d3.v4.min.js"></script>

To keep the month / year default functionality, you need to create your own custom format.

var xAxis = d3.axisBottom(xScale)
   .tickFormat(function(date){
       if (d3.timeYear(date) < date) {
         return d3.timeFormat('%b')(date);
       } else {
         return d3.timeFormat('%Y')(date);
       }
    });

Check the demo:

var svg = d3.select("body")
  .append("svg")
  .attr("width", 500)
  .attr("height", 100)   
            
var xScale = d3.scaleTime()
  .domain([new Date("2014-01-01"), new Date("2016-01-01")])
  .range([0, 500]);

var xAxis = d3.axisBottom(xScale)
  .tickFormat(function(date){
    if (d3.timeYear(date) < date) {
      return d3.timeFormat('%b')(date);
    } else {
      return d3.timeFormat('%Y')(date);
    }
  });
  
svg.append("g")
  .attr("class", "x axis")
  .call(xAxis);
 
d3.selectAll(".ticks");
<script src="https://d3js.org/d3.v4.min.js"></script>
Matthew James Davis
  • 12,134
  • 7
  • 61
  • 90
Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171
  • 4
    Is there a way to preserve the original functionality of the axis ticks showing the year as well? – ksav Oct 21 '16 at 11:35
  • 1
    @ksav I actually figured it out on my own. Editing the answer too. – Matthew James Davis Oct 24 '16 at 04:21
  • hey, which is the default behaviour if you are watching some months of 2014 and some month of 2015....what is supossed to be displayed by default if I don add a tickFormat function?? I couldn't find it in the docs. Is is supossed to display nov dec 2015 february March...etc on the time axis?? – John Sep 18 '18 at 22:39
  • 1
    @Juan It's very unpredictable. It depends, among other things, on the domain. Very hard to say, and that's why a time axis is so complicated to be customised. – Gerardo Furtado Sep 18 '18 at 22:44
  • 2
    yeah, I asked mostly because sometimes I have to write custom functions to display months or years depending on "d" conditions and sometimes by default it does it alone...sometimes it displays the same tick multiple times...I feel it's still one of those parts of d3 that I don't feel comfortable with yet. Thank you Gerardo, you helped me a lot of times already along these years – John Sep 18 '18 at 22:48
  • 2
    For an extended version also formatting weeks, days, hours, this example may help: https://bl.ocks.org/wboykinm/34627426d84f3242e0e6ecb2339e9065 – Chris Nov 14 '18 at 01:23
  • @Chris - thanks! This was exactly what I needed. – Nick Tiberi Apr 16 '21 at 20:18