Skip to content

Instantly share code, notes, and snippets.

@robcrock
Last active November 29, 2018 16:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robcrock/09a0301b5cb74d1e1ab54c463de15a02 to your computer and use it in GitHub Desktop.
Save robcrock/09a0301b5cb74d1e1ab54c463de15a02 to your computer and use it in GitHub Desktop.
#KnowledgeGaps | Learning How to Create a Slope Chart
<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>
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
/*
* 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