Insert padding so that points do not overlap with y or x-axis
1.) This is controlled by the domain of your scales. Since your domains are set to the extent of the data, the axis starts there. Easy fix is to increase your domain to be +- N percent of the range. Also, I recommend remove the .nice()
as you'll just end up fighting it for control the of the range.
// get extents and range
var xExtent = d3.extent(data, function(d) { return d.grade; }),
xRange = xExtent[1] - xExtent[0],
yExtent = d3.extent(data, function(d) { return d.bin; }),
yRange = yExtent[1] - yExtent[0];
// set domain to be extent +- 5%
x.domain([xExtent[0] - (xRange * .05), xExtent[1] + (xRange * .05)]);
y.domain([yExtent[0] - (yRange * .05), yExtent[1] + (yRange * .05)]);
2.) This is controlled by the outerTickSize option. Just set it to zero.
var yAxisLeft = d3.svg.axis()
.scale(y)
.ticks(yTicks)
.outerTickSize(0) //<-- set to zero
.orient("left");
Full working code sample:
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
<title>Proportion of Students Suspended <body></body> Grade</title>
<style type="text/css">
body {
font: 10px Helvetica;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script type="text/javascript">
// Set up the margins
var margin = {top: 50, right: 50, bottom: 30, left: 50},
width = 1000 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom
yTicks = 5
var x = d3.scale.linear()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var xAxisBot = d3.svg.axis()
.scale(x)
.outerTickSize(0)
.orient("bottom");
var xAxisTop = d3.svg.axis()
.scale(x)
.tickFormat('')
.outerTickSize(0)
.orient("top");
var yAxisLeft = d3.svg.axis()
.scale(y)
.ticks(yTicks)
.outerTickSize(0)
.orient("left");
var yAxisRight = d3.svg.axis()
.scale(y)
.ticks(yTicks)
.tickFormat('')
.outerTickSize(0)
.orient("right");
var line = d3.svg.line()
.x(function(d) { return x(d.grade); })
.y(function(d) { return y(d.bin); });
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 data = [{"grade":1,"bin":0.0398,"number":14943,"total":3.2306},{"grade":2,"bin":0.0605,"number":14128,"total":3.3778},{"grade":3,"bin":0.0777,"number":13590,"total":3.4621},{"grade":4,"bin":0.103,"number":13147,"total":3.7474},{"grade":5,"bin":0.1207,"number":12936,"total":3.7055},{"grade":6,"bin":0.202,"number":12857,"total":5.2757},{"grade":7,"bin":0.2534,"number":12962,"total":5.7908},{"grade":8,"bin":0.2561,"number":13362,"total":5.7759},{"grade":9,"bin":0.1873,"number":16618,"total":5.8429},{"grade":10,"bin":0.168,"number":14996,"total":5.4448},{"grade":11,"bin":0.1178,"number":13119,"total":4.3997},{"grade":12,"bin":0.0605,"number":12061,"total":3.8986}];
var xExtent = d3.extent(data, function(d) { return d.grade; }),
xRange = xExtent[1] - xExtent[0],
yExtent = d3.extent(data, function(d) { return d.bin; }),
yRange = yExtent[1] - yExtent[0];
x.domain([xExtent[0] - (xRange * .05), xExtent[1] + (xRange * .05)]);
y.domain([yExtent[0] - (yRange * .05), yExtent[1] + (yRange * .05)]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxisBot)
.append("text")
.attr("class", "label")
.attr("x", width/2)
.attr("y", 28)
.style("text-anchor", "end")
.text("Grade");
svg.append("g")
.attr("class", "x axis")
.call(xAxisTop);
svg.append("g")
.attr("class", "y axis")
.call(yAxisLeft)
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("y", -40)
.attr("x", -(height / 5))
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Proportion of Students Suspended at Least Once");
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + width + ", 0)")
.call(yAxisRight);
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line)
.style("fill", "none")
.style("stroke", "#3B3A35")
.style("stroke-width", "1.5px");
svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", function(d) { return 10; })
.attr("cx", function(d) { return x(d.grade); })
.attr("cy", function(d) { return y(d.bin); })
.attr("transform", "translate(0, 0)")
.on("mouseover", function(d) {
//Get this bar's x/y values, then augment for the tooltip
var xPosition = parseFloat(d3.select(this).attr("cx")) + 0;
var yPosition = parseFloat(d3.select(this).attr("cy")) + 0;
d3.select(this)
.transition()
.duration(500)
.style("fill-opacity", .35)
.attr("r", 20)
})
.on("mouseout", function() {
//Hide the tooltip
d3.select(this)
.transition()
.duration(500)
.style("fill-opacity", 1)
.attr("r", function(d) { return 10; });
})
.style("fill", "#3B3A35")
.style("stroke", "#3B3A35")
.style("stroke-width", "1.2px");
</script>
</body>
</html>