|
// Variables: |
|
$type-settings: ( |
|
320: |
|
( |
|
"ratio": 1.333, |
|
"base": 14, |
|
"types": (1: (line-height: 1), 2: (line-height: 1), 3: (line-height: 1), 4: (line-height: 2), 5: (line-height: 3)) |
|
), |
|
576: |
|
( |
|
"ratio": 1.333, |
|
"base": 16, |
|
"types": (1: (line-height: 1), 2: (line-height: 1), 3: (line-height: 1), 4: (line-height: 2), 5: (line-height: 3)) |
|
), |
|
768: |
|
( |
|
"ratio": 1.5, |
|
"base": 18, |
|
"types": (1: (line-height: 1), 2: (line-height: 1), 3: (line-height: 2), 4: (line-height: 3), 5: (line-height: 4)) |
|
), |
|
992: |
|
( |
|
"ratio": 1.618, |
|
"base": 20, |
|
"types": (1: (line-height: 1), 2: (line-height: 2), 3: (line-height: 2), 4: (line-height: 4), 5: (line-height: 6)) |
|
) |
|
); |
|
|
|
:root { |
|
--baseline: 1.75rem; |
|
--gap: 1.75rem; |
|
} |
|
|
|
@media (max-width: 576px) { |
|
:root { |
|
--baseline: 1.5rem; |
|
} |
|
} |
|
|
|
// Functions: |
|
|
|
// poly-fluid-sizing |
|
// Generate linear interpolated size values through multiple break points |
|
// @param $property - A string CSS property name |
|
// @param $map - A SASS map of viewport unit and size value pairs |
|
// @requires function linear-interpolation |
|
// @requires function map-sort |
|
// @example: @include poly-fluid-sizing('font-size', (576px: 22px, 768px: 24px, 992px: 34px)); |
|
@mixin poly-fluid-sizing($property, $map) { |
|
// Get the number of provided breakpoints |
|
$length: length(map-keys($map)); |
|
|
|
// Error if the number of breakpoints is < 2 |
|
@if ($length < 2) { |
|
@error "poly-fluid-sizing() $map requires at least values"; |
|
} |
|
|
|
// Sort the map by viewport width (key) |
|
$map: map-sort($map); |
|
$keys: map-keys($map); |
|
$minItem: map-get($map, nth($keys, 1)); |
|
|
|
// Minimum size |
|
font-size: map-get($minItem, "font-size"); |
|
line-height: map-get($minItem, "line-height"); |
|
|
|
// Interpolated size through breakpoints |
|
@for $i from 1 through ($length - 1) { |
|
$item: map-get($map, nth($keys, $i)); |
|
|
|
@media (min-width: nth($keys,$i)) { |
|
font-size: linear-interpolation( |
|
( |
|
nth($keys, $i): map-get($item, "font-size"), |
|
nth($keys, ($i + 1)): map-get(map-get($map, nth($keys, ($i + 1))), "font-size") |
|
) |
|
); |
|
line-height: map-get(map-get($map, nth($keys, ($i + 1))), "line-height"); |
|
} |
|
} |
|
|
|
// Maxmimum size |
|
@media (min-width: nth($keys,$length)) { |
|
$maxItem: map-get($map, nth($keys, $length)); |
|
font-size: map-get($maxItem, "font-size"); |
|
line-height: map-get($maxItem, "line-height"); |
|
} |
|
} |
|
|
|
// linear-interpolation |
|
// Calculate the definition of a line between two points |
|
// @param $map - A SASS map of viewport widths and size value pairs |
|
// @returns A linear equation as a calc() function |
|
// @example: font-size: linear-interpolation((320px: 18px, 768px: 26px)); |
|
@function linear-interpolation($map) { |
|
$keys: map-keys($map); |
|
@if (length($keys) != 2) { |
|
@error "linear-interpolation() $map must be exactly 2 values"; |
|
} |
|
// The slope |
|
$m: (map-get($map, nth($keys, 2)) - map-get($map, nth($keys, 1)))/ (nth($keys, 2) - nth($keys, 1)); |
|
|
|
// The y-intercept |
|
$b: map-get($map, nth($keys, 1)) - $m * nth($keys, 1); |
|
|
|
// Determine if the sign should be positive or negative |
|
$sign: "+"; |
|
@if ($b < 0) { |
|
$sign: "-"; |
|
$b: abs($b); |
|
} |
|
|
|
@return calc(#{$m * 100}vw #{$sign} #{$b}); |
|
} |
|
|
|
// list-sort |
|
// Sort a SASS list |
|
// @param $list - A SASS list |
|
// @returns A sorted SASS list |
|
// @requires function list-remove |
|
@function list-sort($list) { |
|
$sortedlist: (); |
|
@while length($list) > 0 { |
|
$value: nth($list, 1); |
|
@each $item in $list { |
|
@if $item < $value { |
|
$value: $item; |
|
} |
|
} |
|
$sortedlist: append($sortedlist, $value, "space"); |
|
$list: list-remove($list, index($list, $value)); |
|
} |
|
@return $sortedlist; |
|
} |
|
|
|
// map-sort |
|
// Sort map by keys |
|
// @param $map - A SASS map |
|
// @returns A SASS map sorted by keys |
|
// @requires function list-sort |
|
@function map-sort($map) { |
|
$keys: list-sort(map-keys($map)); |
|
$sortedMap: (); |
|
@each $key in $keys { |
|
$sortedMap: map-merge($sortedMap, ($key: map-get($map, $key))); |
|
} |
|
@return $sortedMap; |
|
} |
|
|
|
// list-remove |
|
// Remove an item from a list |
|
// @param $list - A SASS list |
|
// @param $index - The list index to remove |
|
// @returns A SASS list |
|
@function list-remove($list, $index) { |
|
$newList: (); |
|
@for $i from 1 through length($list) { |
|
@if $i != $index { |
|
$newList: append($newList, nth($list, $i), "space"); |
|
} |
|
} |
|
@return $newList; |
|
} |
|
|
|
// modular-scale |
|
// Calc size with ratio |
|
// @param $value - Base of ratio |
|
// @param $ratio - 1.618 or something |
|
// @param $muliple - Number of Sequece |
|
// @returns scale |
|
@function modular-scale($value, $ratio, $multiple) { |
|
$modular-scale: $value; |
|
@if ($multiple == 0) { |
|
@return $modular-scale; |
|
} |
|
@for $i from 1 through $multiple { |
|
$modular-scale: $modular-scale * $ratio; |
|
} |
|
@return $modular-scale; |
|
} |
|
|
|
// type-scale |
|
// convert $type-settings to modular-scale function |
|
// @param $level - level rate |
|
// @param $_baseline - line-height "default" |
|
// @returns $typescale-map |
|
@function type-scale($level, $_baseline: var(--baseline)) { |
|
$typescale-map: (); |
|
@each $query, $options in $type-settings { |
|
$map: (); |
|
$ratio: map-get($options, "ratio"); |
|
$base: map-get($options, "base"); |
|
$types: map-get($options, "types"); |
|
$getLevel: map-get($types, $level); |
|
$getLines: map-get($getLevel, "line-height"); |
|
$fontSize: modular-scale($base, $ratio, $level - 1); |
|
$map: map-merge($map, ($query * 1px: (font-size: $fontSize * 1px, line-height: line-height($getLines)))); |
|
$typescale-map: map-merge($typescale-map, $map); |
|
} |
|
@return $typescale-map; |
|
} |
|
|
|
// line-height |
|
// Calc line-height with level |
|
// @param $level - line rate |
|
// @returns line-height |
|
@function line-height($level) { |
|
@return calc(#{$level} * var(--baseline)); |
|
} |
|
|
|
|
|
|
|
// Styles: |
|
* { |
|
box-sizing: border-box; |
|
} |
|
|
|
html { |
|
box-sizing: border-box; |
|
height: 100%; |
|
&.has-grid { |
|
background-size: 1px var(--baseline); |
|
background-image: linear-gradient(rgba(#00bcd4, .23) 1px, transparent 0%, transparent); |
|
h1, h2, h3 { |
|
background-color: rgba(#ff0, 0.25); |
|
} |
|
} |
|
} |
|
|
|
body { |
|
line-height: var(--baseline); |
|
padding: var(--baseline) var(--gap); |
|
padding-bottom: calc(var(--baseline) * 2); |
|
font-weight: 400; |
|
margin: 0 auto; |
|
width: 70rem; |
|
max-width: 100%; |
|
font-family: Circular Std, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, |
|
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; |
|
letter-spacing: -.01em; |
|
-webkit-font-smoothing: antialiased; |
|
text-rendering: optimizeLegibility; |
|
-webkit-font-smoothing: antialiased; |
|
-moz-osx-font-smoothing: grayscale; |
|
} |
|
|
|
.wrapper { |
|
display: grid; |
|
width: 48rem; |
|
margin: 0 auto; |
|
max-width: 100%; |
|
grid-column-gap: 1em; |
|
} |
|
|
|
h1, |
|
h2, |
|
h3, |
|
h4 { |
|
margin: 0; |
|
font-weight: 700; |
|
margin-bottom: var(--baseline); |
|
} |
|
|
|
h1 { |
|
@include poly-fluid-sizing("font-size", type-scale(4)); |
|
font-family: Playfair Display; |
|
font-weight: 900; |
|
word-spacing: 0.02em; |
|
letter-spacing: -.026em; |
|
// margin-bottom: 0; |
|
&.large { |
|
@include poly-fluid-sizing("font-size", type-scale(5)); |
|
} |
|
} |
|
|
|
h2 { |
|
@include poly-fluid-sizing("font-size", type-scale(3)); |
|
color: #CFCFD1; |
|
word-spacing: 0.03em; |
|
letter-spacing: -.032em; |
|
} |
|
|
|
h3 { |
|
@include poly-fluid-sizing("font-size", type-scale(2)); |
|
letter-spacing: -.036em; |
|
} |
|
|
|
p, h4, ul, ol { |
|
margin-top: 0; |
|
margin-bottom: var(--baseline); |
|
@include poly-fluid-sizing("font-size", type-scale(1)); |
|
} |
|
|
|
|
|
/* Let's make sure all's aligned */ |
|
pre, table, blockquote { |
|
margin-top: 0; |
|
margin-bottom: var(--baseline); |
|
} |
|
|
|
ul, ol { |
|
padding: 0; |
|
padding-left: var(--gap); |
|
list-style-type: disc; |
|
} |
|
|
|
ul ul, ol ol, ul ol, ol ul { |
|
margin-top: 0; |
|
margin-bottom: 0; |
|
} |
|
|
|
hr, .hr { |
|
margin: 0; |
|
padding: 0; |
|
padding-bottom: var(--baseline); |
|
border: 0; |
|
border-top: 1px solid #eee; |
|
} |
|
|
|
a, b, i, strong, em, small, code { |
|
line-height: 0; |
|
} |
|
|
|
sub, sup { |
|
line-height: 0; |
|
position: relative; |
|
vertical-align: baseline; |
|
} |
|
|
|
sup { |
|
top: -0.5em; |
|
} |
|
|
|
sub { |
|
bottom: -0.25em; |
|
} |
|
|
|
|
|
// |
|
// DEMO |
|
// |
|
.toggle--grid { |
|
position: fixed; |
|
padding: 1rem; |
|
background-color: rgba(white, 0.92); |
|
box-shadow: 1px -1px 12px rgba(black, 0.16); |
|
bottom: 0; |
|
border-radius: 0 10px 0 0; |
|
left: 0; |
|
cursor: pointer; |
|
user-select: none; |
|
transition: background-color 0.2s ease-in; |
|
&:hover { |
|
background-color: #fff; |
|
} |
|
span { |
|
padding-left: 10px; |
|
} |
|
} |