Last active
November 29, 2018 16:18
-
-
Save robcrock/09a0301b5cb74d1e1ab54c463de15a02 to your computer and use it in GitHub Desktop.
#KnowledgeGaps | Learning How to Create a Slope Chart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<style> | |
body { | |
font-family: Roboto; | |
} | |
/* Header styling */ | |
#title { | |
font-family: "Noto Sans"; | |
font-size: 42; | |
line-height: 110%; | |
} | |
#sub-title { | |
margin: 5px 0px 10px 0px; | |
width: 375px; | |
color: #afafaf; | |
} | |
.red { | |
color: #9C454C; | |
font-weight: bold; | |
} | |
.blue { | |
color: #4577A3; | |
font-weight: bold; | |
} | |
/* Footer style */ | |
a { | |
text-align: right; | |
} | |
/* Tooltip formating */ | |
.flex { | |
display: flex; | |
justify-content: space-between; | |
} | |
.flex .left { | |
padding-top: 5px; | |
margin-left: 25px; | |
} | |
.flex .right { | |
padding-top: 5px; | |
margin-right: 25px; | |
} | |
#tooltip { | |
display: none; | |
height: 125px; | |
width: 192px; | |
border-radius: 4px; | |
border: 1px solid #bbbbbb; | |
background-color: rgb(255, 255, 255); | |
box-shadow: 1px 1px 1px 0 rgba(0,0,0,0.4); | |
font-family: Roboto; | |
font-size: 12px; | |
} | |
.tt-header { | |
font-size: 20px; | |
font-family: Noto Sans; | |
text-align: center; | |
margin: 10 auto 0 auto; | |
} | |
#net { | |
font-size: 12px; | |
color: #939698; | |
text-align: center; | |
margin: 0 auto 5 auto; | |
} | |
/* y-axis formatting */ | |
.y-axis, text { | |
font-weight: 400; | |
font-size: 12px; | |
color: #CECECE; | |
} | |
.y-axis path { | |
display: none; | |
} | |
.tick line { | |
stroke: #F1F1F1; | |
} | |
.v-line { | |
stroke: black; | |
stroke-dasharray: 3; | |
opacity: .2; | |
} | |
/* Mark formatting */ | |
.pos.barbell{ | |
stroke: #4577A3; | |
} | |
.neg.barbell{ | |
stroke: #9C454C; | |
} | |
.barbell line{ | |
stroke-width: 3; | |
} | |
.barbell line{ | |
stroke-width: 3; | |
} | |
.pos circle { | |
fill: #4577A3; | |
} | |
.neg circle { | |
fill: #9C454C; | |
} | |
.pos circle { | |
fill: #4577A3; | |
} | |
.neg circle { | |
fill: #9C454C; | |
} | |
/* Lable formatting */ | |
.outflow-lable { | |
text-anchor: middle; | |
font-size: 12px; | |
font-weight: 400; | |
fill: #9C454C; | |
opacity: .5; | |
} | |
.inflow-lable { | |
text-anchor: middle; | |
font-size: 12px; | |
font-weight: 400; | |
fill: #4577A3; | |
opacity: .5; | |
} | |
</style> | |
<link rel="stylesheet" href="skeleton.css"> | |
<link href="https://fonts.googleapis.com/css?family=Noto+Sans:700|Roboto" rel="stylesheet"> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.js"></script> | |
</head> | |
<body> | |
<div class="container"> | |
<div class="header"> | |
<div id="title">Are More People Coming or Going?</div> | |
<div id="sub-title">Below we look at how many people flowed <span class="blue">into</span> or <span class="red">out</span> of a short list of countries in 2015.</div> | |
</div> | |
<select class="u-full-width" id="country"> | |
<option>Australia</option> | |
<option>Colombia</option> | |
<option>France</option> | |
<option>Indonesia</option> | |
<option>Spain</option> | |
<option>United Kingdom</option> | |
</select> | |
<div class="chart"></div> | |
<div id="tooltip"> | |
<div class="tt-header"></div> | |
<div id="net"></div> | |
<div id="outflow" class="flex"> | |
<div class="left" id="outflow"></div> | |
<div class="right" id="outflow"></div> | |
</div> | |
<div id="inflow" class="flex"> | |
<div class="left"></div> | |
<div class="right"></div> | |
</div> | |
</div> | |
<button class="u-full-width scale">Change to Log Scale</button> | |
<a class="twelve columns" href="https://stats.oecd.org/Index.aspx?DataSetCode=MIG">OECD.Stat</a> | |
</div> | |
</body> | |
<script> | |
class slopeChart { | |
constructor(opts) { | |
// Make the opts available locally | |
this.element = opts.element; | |
this.svgWidth = opts.width; | |
this.svgHeight = opts.height; | |
this.margin = opts.margin; | |
this.padding = opts.padding; | |
this.data = opts.transformedData; | |
// Create additional setup variables we'll need locally based on the opts | |
this.plotWidth = this.svgWidth - (this.margin.left + this.margin.right); | |
this.plotHeight = this.svgHeight - (this.margin.top + this.margin.bottom); | |
this.chartWidth = this.plotWidth - (this.padding.right + this.padding.left); | |
this.chartHeight = this.plotHeight - (this.padding.top + this.padding.bottom); | |
this.draw(); | |
} | |
draw() { | |
const svg = d3.select(this.element) | |
.append('svg') | |
.attr("width", this.svgWidth) | |
.attr("height", this.svgHeight) | |
.attr("translate", `transform(${[this.margin.left, this.margin.top]})`); | |
this.plot = svg.selectAll("g").data([null]); | |
this.plot2 = svg.append('g') | |
.classed("decoration-layer", true) | |
.attr("translate", `transform(${[this.padding.left, this.padding.top]}))`); | |
this.plotEnter = this.plot.enter().append('g') | |
.classed("axis-layer", true) | |
.attr("translate", `transform(${[this.padding.left, this.padding.top]}))`); | |
this.plotEnter2 = this.plot.enter().append('g') | |
.classed("mark-layer", true) | |
.attr("translate", `transform(${[this.padding.left, this.padding.top]}))`); | |
this.addDecorations(); | |
this.updateScales(); | |
this.gupAxes(); | |
this.gupBarbells(); | |
} | |
addDecorations() { | |
//////////////////////////////////////////////////////////////////////////////// | |
///////////////////////////// VERTICAL DASHED LINES //////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
this.plot2 | |
.append("line") | |
.classed("v-line", true) | |
.attr("x1", this.plotWidth - (this.padding.right + this.margin.right + 12)) | |
.attr("y1", 0) | |
.attr("x2", this.plotWidth - (this.padding.right + this.margin.right + 12)) | |
.attr("y2", this.chartHeight) | |
//////////////////////////////////////////////////////////////////////////////// | |
//////////////////////// LABELS BELOW THE VERTICAL LINES /////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
this.plot2 | |
.append("line") | |
.classed("v-line", true) | |
.attr("x1", this.chartWidth * .25 + this.padding.left + this.margin.left) | |
.attr("y1", 0) | |
.attr("x2", this.chartWidth * .25 + this.padding.left + this.margin.left) | |
.attr("y2", this.chartHeight); | |
const outflowLabel = this.plot2 | |
.append("text") | |
.classed("outflow-lable", true) | |
.attr("x", this.margin.left + this.padding.left + (this.chartWidth * .25)) | |
.attr("y", this.chartHeight) | |
.attr("dy", 30) | |
.text("OUTFLOW") | |
.on("mouseover.highlight", function(d) { | |
d3.select(this) | |
.style("opacity", 1); | |
d3.selectAll(".neg") | |
.style("opacity", 1); | |
d3.selectAll(".pos") | |
.style("opacity", .3); | |
}) | |
.on("mouseout.highlight", function(d) { | |
d3.selectAll(".barbell") | |
.style("opacity", .5); | |
}); | |
const inflowLabel = this.plot2 | |
.append("text") | |
.classed("inflow-lable", true) | |
.attr("x", this.margin.left + this.padding.left + (this.chartWidth * .75)) | |
.attr("y", this.chartHeight) | |
.attr("dy", 30) | |
.text("INFLOW") | |
.on("mouseover.highlight", function(d) { | |
d3.select(this) | |
.style("opacity", 1); | |
d3.selectAll(".pos") | |
.style("opacity", 1); | |
d3.selectAll(".neg") | |
.style("opacity", .3); | |
}) | |
.on("mouseout.highlight", function(d) { | |
d3.selectAll(".pos") | |
.style("opacity", .5); | |
d3.selectAll(".neg") | |
.style("opacity", .5); | |
}); | |
} | |
updateScales() { | |
//////////////////////////////////////////////////////////////////////////////// | |
/////////////////// FIND THE MIN AND MAX OF ALL MOVEMENT /////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
const migration = []; | |
for(const record of this.data) { | |
migration.push(record.outflow); | |
migration.push(record.inflow); | |
} | |
[this.minM, this.maxM] = d3.extent(migration); | |
//////////////////////////////////////////////////////////////////////////////// | |
////////////////////// SET SCALES BASED ON BUTTON TEXT ///////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
if (document.querySelector("button.scale").textContent.includes("Linear")) { | |
this.yScale = d3.scaleLog() | |
.domain([this.minM, this.maxM]) | |
.range([this.chartHeight, this.margin.top + this.padding.top]); | |
} else { | |
this.yScale = d3.scaleLinear() | |
.domain([this.minM, this.maxM]) | |
.range([this.chartHeight, this.margin.top + this.padding.top]); | |
} | |
} | |
gupAxes() { | |
this.yAxis = d3.axisRight() | |
.scale(this.yScale) | |
.ticks(10, d3.format(",k")) | |
.tickSize( (this.margin.left + this.padding.left) - this.chartWidth * .85); | |
this.yAxisG = this.plotEnter.selectAll('g').data([null]); | |
this.yAxisGEnter = this.yAxisG.enter().append('g') | |
.attr("class", "y-axis") | |
.attr("transform", `translate(${this.chartWidth}, 0 )`) | |
const t = d3.transition().duration(750); | |
this.yAxisGEnter.exit().transition(t).remove(); | |
this.yAxisGEnter | |
.merge(this.yAxisG) | |
.transition(t) | |
.call(this.yAxis); | |
} | |
gupBarbells() { | |
// This is our UPDATE selection since it's the data join | |
this.groups = this.plotEnter2.selectAll("g") | |
.data(this.data, d => d.country) | |
this.groups.exit().remove(); | |
this.gEnter = this.groups.enter().append("g") | |
.attr("class", d => `${d["pos-or-neg"]} barbell`) | |
.style("opacity", .5); | |
this.gEnter | |
.merge(this.gEnter); | |
//////////////////////////////////////////////////////////////////////////////// | |
//////////////////////////// HIGHLIGHT ACTIVE BARBELLS ///////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
this.gEnter | |
// Dim other marks to bring the hover mark into focus | |
.on("mouseover.highlight", function(d) { | |
this.classList.add("hovered") | |
d3.selectAll(".barbell") | |
.style("opacity", .3); | |
d3.select(".hovered") | |
.style("opacity", 1); | |
}) | |
// Reset to the default | |
.on("mouseout.highlight", function(d) { | |
this.classList.remove("hovered") | |
d3.selectAll(".barbell") | |
.style("opacity", .5); | |
}) | |
//////////////////////////////////////////////////////////////////////////////// | |
//////////////////////////////// REVEAL TOOLTIPS /////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
const tooltip = d3.select("#tooltip"); | |
this.gEnter | |
.on("mousemove.tooltip", function(d) { | |
tooltip.transition() | |
.style("display", "block") | |
.style("opacity", .9); | |
const commaFormat = d3.format(","); | |
// Positioning the tooltip to the bottom right of your cursor | |
tooltip | |
.style("position", "fixed") | |
.style("left", d3.event.clientX + 20) | |
.style("top", d3.event.clientY + 20); | |
// Creating the country header | |
tooltip.select(".tt-header") | |
.text(d.country); | |
// Add the the subtitle of Net value | |
tooltip.select("#net") | |
.text(`Net ${commaFormat(d.net)}`) | |
// Insert row of data for Outflow | |
tooltip.select("#outflow").select(".left") | |
.text("OUTFLOW") | |
tooltip.select("#outflow").select(".right") | |
.text(commaFormat(d.outflow)) | |
// Insert row of data for Inflow | |
tooltip.select("#inflow").select(".left") | |
.text("INFLOW") | |
tooltip.select("#inflow").select(".right") | |
.text(commaFormat(d.inflow)) | |
}) | |
.on("mouseout.tooltip", function() { | |
tooltip.style("display", "none"); | |
}); | |
const t = d3.transition().duration(750); | |
this.lines = this.gEnter.append("line") | |
.attr("x1", this.margin.left + this.padding.left + (this.chartWidth * .25)) | |
.attr("x2", this.margin.left + this.padding.left + (this.chartWidth * .75)) | |
.attr("y1", d => this.yScale(d.outflow)) | |
.attr("y2", d => this.yScale(d.inflow)) | |
.merge(this.groups.select("line")) | |
.transition(t) | |
.attr("y1", d => this.yScale(d.outflow)) | |
.attr("y2", d => this.yScale(d.inflow)); | |
this.circlesOut = this.gEnter.append("circle") | |
.classed("circle-out", true) | |
.attr("r", 4) | |
.attr("cx", this.margin.left + this.padding.left + (this.chartWidth * .25)) | |
.attr("cy", d => this.yScale(d.outflow)) | |
.merge(this.groups.select('.circle-out')) | |
.transition(t) | |
.attr("cy", d => this.yScale(d.outflow)); | |
this.circlesIn = this.gEnter.append("circle") | |
.classed("circle-in", true) | |
.attr("r", 4) | |
.attr("cx", this.margin.left + this.padding.left + (this.chartWidth * .75)) | |
.attr("cy", d => this.yScale(d.inflow)) | |
.merge(this.groups.select('.circle-in')) | |
.transition(t) | |
.attr("cy", d => this.yScale(d.inflow)); | |
} | |
updateButtonText() { | |
if (document.querySelector("button.scale").textContent.includes("Log")) { | |
document.querySelector("button.scale").textContent = "Change to Linear Scale"; | |
} else { | |
document.querySelector("button.scale").textContent = "Change to Log Scale"; | |
} | |
} | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
////////////////////////// LOAD DATA FOR THE 1ST TIME ////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
d3.csv('OECD-data.csv').then( data => { | |
function initializeData(data) { // , key = document.querySelector("#country").value) { | |
// Group data by each country in our list | |
const nested = d3.nest() | |
.key(d => d["country"]) | |
.entries(data); | |
// Filter data by the current country selection | |
const filtered = nested | |
.filter( d => d.key === document.querySelector("#country").value); | |
// Initialize a new data array to use in our visualization | |
const transformedData = filtered[0].values.map( d => { | |
return { | |
country: d["foreign nationality"], | |
outflow: +d.outflow, | |
inflow: +d.inflow, | |
net: +d.inflow - +d.outflow, | |
"pos-or-neg": +d.inflow - +d.outflow >= 0 ? "pos" : "neg" | |
} | |
}) | |
return transformedData; | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
////////////////////////////// SET THE CHART SIZE ////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
const width = 500; | |
const height = 450; | |
const margin = {top: 10, right: 50, bottom: 0, left: 30}; | |
const padding = {top: 10, right: 20, bottom: 20, left: 30}; | |
//////////////////////////////////////////////////////////////////////////////// | |
/////////////////////////////// CREATE NEW CHART /////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
const chart = new slopeChart({ | |
element: document.querySelector('.chart'), | |
width, | |
height, | |
margin, | |
padding, | |
transformedData: initializeData(data) | |
}); | |
//////////////////////////////////////////////////////////////////////////////// | |
///////////////////////////// HAND CONTROL CHANGES ///////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
d3.select('#country').on('change', () => { | |
chart.data = initializeData(data); | |
chart.updateScales(); | |
chart.gupAxes(); | |
chart.gupBarbells(); | |
}); | |
d3.selectAll('button.scale').on('click', () => { | |
chart.updateButtonText(); | |
chart.updateScales(); | |
chart.gupAxes(); | |
chart.gupBarbells(); | |
}); | |
}) | |
</script> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
country | foreign nationality | outflow | inflow | |
---|---|---|---|---|
United Kingdom | Australia | 6700 | 22187 | |
United Kingdom | Austria | 1103 | 1401 | |
United Kingdom | Belgium | 1865 | 1739 | |
United Kingdom | Czech Republic | 56 | 323 | |
United Kingdom | Finland | 154 | 343 | |
United Kingdom | Germany | 8840 | 10726 | |
United Kingdom | Hungary | 277 | 414 | |
United Kingdom | Iceland | 74 | 161 | |
United Kingdom | Ireland | 5600 | 5000 | |
United Kingdom | Italy | 734 | 1482 | |
United Kingdom | Japan | 5622 | 6673 | |
United Kingdom | Korea | 1995 | 1305 | |
United Kingdom | Luxembourg | 334 | 452 | |
United Kingdom | Netherlands | 4355 | 5766 | |
United Kingdom | New Zealand | 4607 | 10264 | |
United Kingdom | Norway | 837 | 984 | |
United Kingdom | Slovenia | 6 | 83 | |
United Kingdom | Spain | 18451 | 14991 | |
United Kingdom | Sweden | 825 | 1666 | |
United Kingdom | Switzerland | 3471 | 3924 | |
Australia | Austria | 224 | 288 | |
Australia | Belgium | 110 | 127 | |
Australia | Czech Republic | 45 | 62 | |
Australia | Finland | 33 | 58 | |
Australia | Germany | 1828 | 2888 | |
Australia | Hungary | 14 | 51 | |
Australia | Iceland | 17 | 25 | |
Australia | Italy | 82 | 213 | |
Australia | Japan | 2692 | 3619 | |
Australia | Korea | 1721 | 1668 | |
Australia | Luxembourg | 18 | 24 | |
Australia | Netherlands | 704 | 1015 | |
Australia | New Zealand | 2282 | 5546 | |
Australia | Norway | 169 | 188 | |
Australia | Slovenia | 5 | 8 | |
Australia | Spain | 145 | 411 | |
Australia | Sweden | 273 | 334 | |
Australia | Switzerland | 364 | 458 | |
Australia | United Kingdom | 6000 | 16000 | |
Colombia | Australia | 100 | 939 | |
Colombia | Austria | 67 | 158 | |
Colombia | Belgium | 118 | 242 | |
Colombia | Czech Republic | 23 | 29 | |
Colombia | Finland | 10 | 35 | |
Colombia | Germany | 1786 | 2751 | |
Colombia | Hungary | 2 | 30 | |
Colombia | Iceland | 5 | 7 | |
Colombia | Italy | 185 | 773 | |
Colombia | Japan | 287 | 364 | |
Colombia | Korea | 118 | 107 | |
Colombia | Luxembourg | 8 | 19 | |
Colombia | Netherlands | 304 | 438 | |
Colombia | New Zealand | 40 | 189 | |
Colombia | Norway | 44 | 76 | |
Colombia | Spain | 7273 | 9368 | |
Colombia | Sweden | 107 | 284 | |
Colombia | Switzerland | 199 | 419 | |
France | Australia | 400 | 1616 | |
France | Austria | 918 | 1199 | |
France | Belgium | 8496 | 11977 | |
France | Czech Republic | 45 | 252 | |
France | Finland | 167 | 226 | |
France | Germany | 12920 | 14908 | |
France | Hungary | 229 | 376 | |
France | Iceland | 48 | 134 | |
France | Italy | 869 | 1703 | |
France | Japan | 3765 | 4990 | |
France | Korea | 2150 | 1821 | |
France | Luxembourg | 1836 | 4119 | |
France | Netherlands | 3011 | 4038 | |
France | New Zealand | 685 | 4481 | |
France | Norway | 642 | 746 | |
France | Slovak Republic | 1 | 77 | |
France | Slovenia | 7 | 178 | |
France | Spain | 6847 | 9020 | |
France | Sweden | 514 | 1001 | |
France | Switzerland | 7088 | 14767 | |
France | United Kingdom | 7000 | 15000 | |
Indonesia | Australia | 300 | 2076 | |
Indonesia | Austria | 67 | 158 | |
Indonesia | Belgium | 91 | 164 | |
Indonesia | Czech Republic | 16 | 26 | |
Indonesia | Finland | 13 | 38 | |
Indonesia | Germany | 1633 | 2470 | |
Indonesia | Hungary | 3 | 48 | |
Indonesia | Iceland | 2 | 7 | |
Indonesia | Italy | 37 | 218 | |
Indonesia | Japan | 8441 | 14295 | |
Indonesia | Korea | 7111 | 8538 | |
Indonesia | Luxembourg | 1 | 4 | |
Indonesia | Netherlands | 1053 | 1481 | |
Indonesia | New Zealand | 125 | 534 | |
Indonesia | Norway | 91 | 90 | |
Indonesia | Spain | 55 | 160 | |
Indonesia | Sweden | 67 | 124 | |
Indonesia | Switzerland | 187 | 248 | |
Indonesia | United Kingdom | 1000 | 1000 | |
Spain | Australia | 100 | 552 | |
Spain | Austria | 1087 | 1613 | |
Spain | Belgium | 2335 | 4137 | |
Spain | Czech Republic | 16 | 112 | |
Spain | Finland | 137 | 284 | |
Spain | Germany | 16435 | 23598 | |
Spain | Hungary | 77 | 322 | |
Spain | Iceland | 75 | 178 | |
Spain | Italy | 479 | 1906 | |
Spain | Japan | 1605 | 1827 | |
Spain | Korea | 274 | 244 | |
Spain | Luxembourg | 229 | 689 | |
Spain | Netherlands | 3542 | 4957 | |
Spain | New Zealand | 103 | 209 | |
Spain | Norway | 604 | 1272 | |
Spain | Slovak Republic | 2 | 85 | |
Spain | Slovenia | 5 | 299 | |
Spain | Sweden | 459 | 1286 | |
Spain | Switzerland | 3099 | 7042 | |
Spain | United Kingdom | 9000 | 20000 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Skeleton V2.0.4 | |
* Copyright 2014, Dave Gamache | |
* www.getskeleton.com | |
* Free to use under the MIT license. | |
* http://www.opensource.org/licenses/mit-license.php | |
* 12/29/2014 | |
*/ | |
/* Table of contents | |
–––––––––––––––––––––––––––––––––––––––––––––––––– | |
- Grid | |
- Base Styles | |
- Typography | |
- Links | |
- Buttons | |
- Forms | |
- Lists | |
- Code | |
- Tables | |
- Spacing | |
- Utilities | |
- Clearing | |
- Media Queries | |
*/ | |
/* Grid | |
–––––––––––––––––––––––––––––––––––––––––––––––––– */ | |
.container { | |
position: relative; | |
width: 100%; | |
max-width: 500px; | |
margin: 0 auto; | |
padding: 0 20px; | |
box-sizing: border-box; } | |
.column, | |
.columns { | |
width: 100%; | |
float: left; | |
box-sizing: border-box; } | |
/* For devices larger than 400px */ | |
@media (min-width: 400px) { | |
.container { | |
width: 85%; | |
padding: 0; } | |
} | |
/* For devices larger than 550px */ | |
@media (min-width: 550px) { | |
.container { | |
width: 80%; } | |
.column, | |
.columns { | |
margin-left: 4%; } | |
.column:first-child, | |
.columns:first-child { | |
margin-left: 0; } | |
.one.column, | |
.one.columns { width: 4.66666666667%; } | |
.two.columns { width: 13.3333333333%; } | |
.three.columns { width: 22%; } | |
.four.columns { width: 30.6666666667%; } | |
.five.columns { width: 39.3333333333%; } | |
.six.columns { width: 48%; } | |
.seven.columns { width: 56.6666666667%; } | |
.eight.columns { width: 65.3333333333%; } | |
.nine.columns { width: 74.0%; } | |
.ten.columns { width: 82.6666666667%; } | |
.eleven.columns { width: 91.3333333333%; } | |
.twelve.columns { width: 100%; margin-left: 0; } | |
.one-third.column { width: 30.6666666667%; } | |
.two-thirds.column { width: 65.3333333333%; } | |
.one-half.column { width: 48%; } | |
/* Offsets */ | |
.offset-by-one.column, | |
.offset-by-one.columns { margin-left: 8.66666666667%; } | |
.offset-by-two.column, | |
.offset-by-two.columns { margin-left: 17.3333333333%; } | |
.offset-by-three.column, | |
.offset-by-three.columns { margin-left: 26%; } | |
.offset-by-four.column, | |
.offset-by-four.columns { margin-left: 34.6666666667%; } | |
.offset-by-five.column, | |
.offset-by-five.columns { margin-left: 43.3333333333%; } | |
.offset-by-six.column, | |
.offset-by-six.columns { margin-left: 52%; } | |
.offset-by-seven.column, | |
.offset-by-seven.columns { margin-left: 60.6666666667%; } | |
.offset-by-eight.column, | |
.offset-by-eight.columns { margin-left: 69.3333333333%; } | |
.offset-by-nine.column, | |
.offset-by-nine.columns { margin-left: 78.0%; } | |
.offset-by-ten.column, | |
.offset-by-ten.columns { margin-left: 86.6666666667%; } | |
.offset-by-eleven.column, | |
.offset-by-eleven.columns { margin-left: 95.3333333333%; } | |
.offset-by-one-third.column, | |
.offset-by-one-third.columns { margin-left: 34.6666666667%; } | |
.offset-by-two-thirds.column, | |
.offset-by-two-thirds.columns { margin-left: 69.3333333333%; } | |
.offset-by-one-half.column, | |
.offset-by-one-half.columns { margin-left: 52%; } | |
} | |
/* Base Styles | |
–––––––––––––––––––––––––––––––––––––––––––––––––– */ | |
/* NOTE | |
html is set to 62.5% so that all the REM measurements throughout Skeleton | |
are based on 10px sizing. So basically 1.5rem = 15px :) */ | |
html { | |
font-size: 62.5%; } | |
body { | |
font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ | |
line-height: 1.6; | |
font-weight: 400; | |
font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; | |
color: #222; } | |
/* Typography | |
–––––––––––––––––––––––––––––––––––––––––––––––––– */ | |
h1, h2, h3, h4, h5, h6 { | |
margin-top: 0; | |
margin-bottom: 2rem; | |
font-weight: 300; } | |
h1 { font-size: 4.0rem; line-height: 1.2; letter-spacing: -.1rem;} | |
h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; } | |
h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; } | |
h4 { font-size: 2.4rem; line-height: 1.35; letter-spacing: -.08rem; } | |
h5 { font-size: 1.8rem; line-height: 1.5; letter-spacing: -.05rem; } | |
h6 { font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; } | |
/* Larger than phablet */ | |
@media (min-width: 550px) { | |
h1 { font-size: 5.0rem; } | |
h2 { font-size: 4.2rem; } | |
h3 { font-size: 3.6rem; } | |
h4 { font-size: 3.0rem; } | |
h5 { font-size: 2.4rem; } | |
h6 { font-size: 1.5rem; } | |
} | |
p { | |
margin-top: 0; } | |
/* Links | |
–––––––––––––––––––––––––––––––––––––––––––––––––– */ | |
a { | |
color: #1EAEDB; } | |
a:hover { | |
color: #0FA0CE; } | |
/* Buttons | |
–––––––––––––––––––––––––––––––––––––––––––––––––– */ | |
.button, | |
button, | |
input[type="submit"], | |
input[type="reset"], | |
input[type="button"] { | |
display: inline-block; | |
height: 38px; | |
padding: 0 30px; | |
color: #555; | |
text-align: center; | |
font-size: 11px; | |
font-weight: 600; | |
line-height: 38px; | |
letter-spacing: .1rem; | |
text-transform: uppercase; | |
text-decoration: none; | |
white-space: nowrap; | |
background-color: transparent; | |
border-radius: 4px; | |
border: 1px solid #bbb; | |
cursor: pointer; | |
box-sizing: border-box; } | |
.button:hover, | |
button:hover, | |
input[type="submit"]:hover, | |
input[type="reset"]:hover, | |
input[type="button"]:hover, | |
.button:focus, | |
button:focus, | |
input[type="submit"]:focus, | |
input[type="reset"]:focus, | |
input[type="button"]:focus { | |
color: #333; | |
border-color: #888; | |
outline: 0; } | |
.button.button-primary, | |
button.button-primary, | |
input[type="submit"].button-primary, | |
input[type="reset"].button-primary, | |
input[type="button"].button-primary { | |
color: #FFF; | |
background-color: #33C3F0; | |
border-color: #33C3F0; } | |
.button.button-primary:hover, | |
button.button-primary:hover, | |
input[type="submit"].button-primary:hover, | |
input[type="reset"].button-primary:hover, | |
input[type="button"].button-primary:hover, | |
.button.button-primary:focus, | |
button.button-primary:focus, | |
input[type="submit"].button-primary:focus, | |
input[type="reset"].button-primary:focus, | |
input[type="button"].button-primary:focus { | |
color: #FFF; | |
background-color: #1EAEDB; | |
border-color: #1EAEDB; } | |
/* Forms | |
–––––––––––––––––––––––––––––––––––––––––––––––––– */ | |
input[type="email"], | |
input[type="number"], | |
input[type="search"], | |
input[type="text"], | |
input[type="tel"], | |
input[type="url"], | |
input[type="password"], | |
textarea, | |
select { | |
height: 38px; | |
padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ | |
background-color: #fff; | |
border: 1px solid #D1D1D1; | |
border-radius: 4px; | |
box-shadow: none; | |
box-sizing: border-box; } | |
/* Removes awkward default styles on some inputs for iOS */ | |
input[type="email"], | |
input[type="number"], | |
input[type="search"], | |
input[type="text"], | |
input[type="tel"], | |
input[type="url"], | |
input[type="password"], | |
textarea { | |
-webkit-appearance: none; | |
-moz-appearance: none; | |
appearance: none; } | |
textarea { | |
min-height: 65px; | |
padding-top: 6px; | |
padding-bottom: 6px; } | |
input[type="email"]:focus, | |
input[type="number"]:focus, | |
input[type="search"]:focus, | |
input[type="text"]:focus, | |
input[type="tel"]:focus, | |
input[type="url"]:focus, | |
input[type="password"]:focus, | |
textarea:focus, | |
select:focus { | |
border: 1px solid #33C3F0; | |
outline: 0; } | |
label, | |
legend { | |
display: block; | |
margin-bottom: .5rem; | |
font-weight: 600; } | |
fieldset { | |
padding: 0; | |
border-width: 0; } | |
input[type="checkbox"], | |
input[type="radio"] { | |
display: inline; } | |
label > .label-body { | |
display: inline-block; | |
margin-left: .5rem; | |
font-weight: normal; } | |
/* Lists | |
–––––––––––––––––––––––––––––––––––––––––––––––––– */ | |
ul { | |
list-style: circle inside; } | |
ol { | |
list-style: decimal inside; } | |
ol, ul { | |
padding-left: 0; | |
margin-top: 0; } | |
ul ul, | |
ul ol, | |
ol ol, | |
ol ul { | |
margin: 1.5rem 0 1.5rem 3rem; | |
font-size: 90%; } | |
li { | |
margin-bottom: 1rem; } | |
/* Code | |
–––––––––––––––––––––––––––––––––––––––––––––––––– */ | |
code { | |
padding: .2rem .5rem; | |
margin: 0 .2rem; | |
font-size: 90%; | |
white-space: nowrap; | |
background: #F1F1F1; | |
border: 1px solid #E1E1E1; | |
border-radius: 4px; } | |
pre > code { | |
display: block; | |
padding: 1rem 1.5rem; | |
white-space: pre; } | |
/* Tables | |
–––––––––––––––––––––––––––––––––––––––––––––––––– */ | |
th, | |
td { | |
padding: 12px 15px; | |
text-align: left; | |
border-bottom: 1px solid #E1E1E1; } | |
th:first-child, | |
td:first-child { | |
padding-left: 0; } | |
th:last-child, | |
td:last-child { | |
padding-right: 0; } | |
/* Spacing | |
–––––––––––––––––––––––––––––––––––––––––––––––––– */ | |
button, | |
.button { | |
margin-bottom: 1rem; } | |
input, | |
textarea, | |
select, | |
fieldset { | |
margin-bottom: 1.5rem; } | |
pre, | |
blockquote, | |
dl, | |
figure, | |
table, | |
p, | |
ul, | |
ol, | |
form { | |
margin-bottom: 2.5rem; } | |
/* Utilities | |
–––––––––––––––––––––––––––––––––––––––––––––––––– */ | |
.u-full-width { | |
width: 100%; | |
box-sizing: border-box; } | |
.u-max-full-width { | |
max-width: 100%; | |
box-sizing: border-box; } | |
.u-pull-right { | |
float: right; } | |
.u-pull-left { | |
float: left; } | |
/* Misc | |
–––––––––––––––––––––––––––––––––––––––––––––––––– */ | |
hr { | |
margin-top: 3rem; | |
margin-bottom: 3.5rem; | |
border-width: 0; | |
border-top: 1px solid #E1E1E1; } | |
/* Clearing | |
–––––––––––––––––––––––––––––––––––––––––––––––––– */ | |
/* Self Clearing Goodness */ | |
.container:after, | |
.row:after, | |
.u-cf { | |
content: ""; | |
display: table; | |
clear: both; } | |
/* Media Queries | |
–––––––––––––––––––––––––––––––––––––––––––––––––– */ | |
/* | |
Note: The best way to structure the use of media queries is to create the queries | |
near the relevant code. For example, if you wanted to change the styles for buttons | |
on small devices, paste the mobile query code up in the buttons section and style it | |
there. | |
*/ | |
/* Larger than mobile */ | |
@media (min-width: 400px) {} | |
/* Larger than phablet (also point when grid becomes active) */ | |
@media (min-width: 550px) {} | |
/* Larger than tablet */ | |
@media (min-width: 750px) {} | |
/* Larger than desktop */ | |
@media (min-width: 1000px) {} | |
/* Larger than Desktop HD */ | |
@media (min-width: 1200px) {} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment