<div id="map"></div>
#map {
  padding: 0;
  margin: 0;
  height: 50em;
  width: 100%;
}

.leaflet-tile-container {
  position: absolute;
  left: 0px;
  top: 0px;
  width: 100%;
  height: 100%;
}

.map-view img {
  max-width: none;
  max-height: none;
}

.info {
  padding: .5em 1em;
  font-family: Roboto, Helvetica, Arial, sans-serif;
  font-size: 1.5rem;
  background: white;
  background: rgba(255, 255, 255, 0.9);
  box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
  border-radius: 5px;
  padding: .5rem 1rem;
  width: 60%;
}

.info h4 {
  font-size: 1.25rem;
  margin: 0 0 5px;
  color: #777;
}

.states { 
  font-style: italic;
}
.money {
  color: #cc5527;
  font-weight: bold;
}
.info > .disclaimer {
  font-style: italic;
  font-size: 1rem;
}
var mapboxAccessToken = 'pk.eyJ1Ijoic2NpZiIsImEiOiJjaWgyOHJkZW8weHJrd3dtMHJ1cnV0ZDY2In0.5wK8t52sB90Exoi6StYlBw',
  map = L.map('map').setView([40, -96], 4);

L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=' + mapboxAccessToken, {
  id: 'mapbox.streets',
  attribution: '',
  minZoom: 4
}).addTo(map);

//convert our funding numbers to a scale

function fundingConverter() {
  var states = statesData.features;
  for (var i = 0; i < states.length; i++) {
    var raw_funding = states[i].properties.funding,
      percentage = states[i].properties.percentage,
      numerator = raw_funding - 2000;
    denominator = 16000;
    //Percentage(x,a,b) = x−a/b−a
    if (!percentage) {
      states[i].properties.percentage = 0;
    }
    var decimal_percentage = numerator / denominator;
    states[i].properties.percentage = decimal_percentage * 100;
  }
}

fundingConverter();

//['#fff5eb','#fee6ce','#fdd0a2','#fdae6b','#fd8d3c','#f16913','#d94801','#a63603','#7f2704']

function getColor(d) {
  return d > 90 ? '#7f2704' :
    d > 80 ? '#a63603' :
    d > 70 ? '#d94801' :
    d > 60 ? '#f16913' :
    d > 50 ? '#fd8d3c' :
    d > 40 ? '#fdae6b' :
    d > 30 ? '#fdd0a2' :
    d > 20 ? '#fee6ce' :
    d > 10 ? '#fff5eb' :
    d > 0 ? '#feedde' :
    '#feedde';
}

function style(feature) {
  return {
    fillColor: getColor(feature.properties.percentage),
    weight: 2,
    opacity: 1,
    color: 'white',
    dashArray: '3',
    fillOpacity: 0.7
  };
}

function highlightFeature(e) {
  var layer = e.target;
  layer.setStyle({
    weight: 3,
    color: '#cc5527',
    dashArray: '',
    fillOpacity: 0.7
  });

  if (!L.Browser.ie && !L.Browser.opera && !L.Browser.edge) {
    layer.bringToFront();
  }

  info.update(layer.feature.properties);
}

function resetHighlight(e) {
  geojson.resetStyle(e.target);
  info.update();
}

function zoomToFeature(e) {
  map.fitBounds(e.target.getBounds());
}

function onEachFeature(feature, layer) {
  layer.on({
    mouseover: highlightFeature,
    mouseout: resetHighlight,
    click: highlightFeature
  });
}

function toCommas(x) {
  return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

geojson = L.geoJson(statesData, {
  style: style,
  onEachFeature: onEachFeature
}).addTo(map);

var info = L.control();

info.onAdd = function(map) {
  this._div = L.DomUtil.create('div', 'info'); // create a div with a class "info"
  this.update();
  return this._div;
};

// method that we will use to update the control based on feature properties passed
info.update = function(props) {
  this._div.innerHTML = '<h4>Higher education funding by state (2015)</h4>' + '<p class="disclaimer">Darker colors represent more funding per student.</p>' + (props ?
    '<span class="states">' + props.name + ": " + '</span>' + "<span class='money'>" + "$" + toCommas(props.funding) + '</span>':
    'Hover over a state...');
};

info.addTo(map);

// a workaround for the map not rendering on pageload
$(document).ready(function() {
  map.invalidateSize(false);
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js
  2. https://codepen.io/juntan/pen/NAQrJO.js