I have created a codepen demonstrating my issue. Basically, my axis labels are being created successfully, and are added to the DOM but they are not displaying because they're getting drawn outside of the chart area.
Here is my CSS:
.promo {
fill: rgba(255,0,0,0.5);
}
.price {
fill: $brand-primary;
}
.chart {
height: 50vh;
width: 100%;
overflow: hidden;
}
.svg-container {
display: inline-block;
position: relative;
width: 100%;
padding-bottom: 100%; /* aspect ratio */
vertical-align: top;
overflow: hidden;
}
.svg-content-responsive {
display: inline-block;
position: absolute;
top: 0;
left: 0;
}
And my JS:
let height = $('.chart').height();
let width = $('.chart').width();
let chart = d3.select('.chart')
.append("div")
.classed("svg-container", true) //container class to make it responsive
.append("svg")
.attr('preserveAspectRatio','xMinYMax meet')
.attr('viewBox','0 0 '+width +' '+height )
.classed("svg-content-responsive", true)
.append('g');
//.attr("transform", "translate(50 0)");
let tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
let date = new Date(d[0]);
let year = date.getFullYear();
let allMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
let month = allMonths[date.getMonth()];
return `<strong>$${d[1]} Billion</strong><br>${year} - ${month}`;
});
chart.call(tip);
let x = d3.scaleTime().range([0, width]);
let y = d3.scaleLinear().rangeRound([height, 0]);
d3.json("https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/GDP-data.json", function(response) {
let data = response.data;
x.domain([new Date(data[0][0]), new Date(data[data.length-1][0])]);
y.domain([0, d3.max(data, function(d) { return d[1]; })]);
let barWidth = width / data.length;
chart.append("g")
.attr("class", "axis x")
.attr("transform", "translate(0,"+(height)+")")
.call(d3.axisBottom(x).ticks(10));
chart.append("g")
.attr("class", "axis y")
.call(d3.axisLeft(y).ticks(10));
chart.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("text-anchor", "end")
.text("Gross Domestic Product, USA");
//here x is already the x axis time scale you have defined in your code
var left = x(new Date("Jun 3 1980"));
var right = x(new Date("Apr 22 2013")); //one more day
var wid = right - left;
chart.append("rect")
.attr("x", left)
.attr("width", wid)
.attr('class', 'promo' )
.attr("height", height);
let bar = chart.selectAll('.bar')
.data(data)
.enter();
bar.append('rect')
.attr('class', 'price')
.attr('x', function(d, i) {
return (i*barWidth);
})
.attr('y', function(d) { return y(d[1]); })
.attr("height", function(d) { return height - y(d[1]); })
.attr("width", barWidth)
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
});
Solutions I've encountered relate to charts with specific pixel sizes, and adding margins to these, so that the axis labels occupy this space. Practically, this approach is not possible with a chart that is sized responsively (100% width and 50% of the viewport height).
What can I do to get my labels to display as required?