Skip to content

Instantly share code, notes, and snippets.

@jhogue
Last active November 2, 2015 03:23
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 jhogue/53967147ed89778c713d to your computer and use it in GitHub Desktop.
Save jhogue/53967147ed89778c713d to your computer and use it in GitHub Desktop.
Responsive Typography
/* The idea:
One list of breakpoints.
One list of type sizes/scales with a corresponding key name.
One function that can iterate and output all type sizes.
One function that can iterate over the breakpoints, find the
matching type size array, and output all breakpoint sizes for that element.
Try this in Sassmeister to see the results
*/
// Core functions
@function strip-units($value) {
@return $value / ($value * 0 + 1);
}
@function px2em( $pixel, $base-size:$base-font-size ) {
$pixel: strip-units($pixel);
$base-size: strip-units($base-size);
@return ($pixel / $base-size) * 1em;
}
@function bp($size: 'base') {
@return px2em( map-get( $breakpoints, $size ) );
}
@function type-size($elem, $size: 'base') {
@return map-get( map-get($type-sizes, $elem), $size );
}
// Global variables
$base-font-size: 16px !default;
$base-line-height: 28px !default;
// Breakpoints Map
$breakpoints: (
// List as unitless pixels
base: 320,
x-small: 480,
small: 640,
medium: 760,
large: 960,
x-large: 1200
);
// Typographic Scales Map
$type-sizes: (
// List as unitless pixels, use SASS function to convert to whatever you want
// Not supplying these programatically. Allows curation of sizes.
// Use the same $key names as the corresponding breakpoint
// 1.2 typographic scale
base: (
giga: 52,
mega: 44,
kilo: 37,
h1: 31,
h2: 26,
h3: 22,
h4: 19,
base: 16,
micro: 13,
),
// 1.25 typographic scale
small: (
giga: 72,
mega: 58,
kilo: 47,
h1: 38,
h2: 31,
h3: 25,
h4: 20,
base: 18,
micro: 14,
),
// 1.3 typographic scale
large: (
giga: 91,
mega: 70,
kilo: 54,
h1: 42,
h2: 33,
h3: 26,
h4: 20,
base: 19,
micro: 15,
),
);
// Some magic
// Check the $key-s by name and treat some of them special
@mixin type-size-key-value-output($item,$value) {
$base-size-unitless: strip-units($base-font-size);
@if str-slice(#{$item},0,1) == 'h' {
// Output these as HTMl elements
#{$item} {
font-size: $value * 1px;
font-size: ($value/$base-size-unitless) * 1rem;
}
} @elseif $item == 'base' {
// Output 'base' as a custom set of HTML elements
p,ul,ol,dl,table,form {
font-size: $value * 1px;
font-size: ($value/$base-size-unitless) * 1rem;
}
} @else {
// Output anything else as a class
.#{$item} {
font-size: $value * 1px;
font-size: ($value/$base-size-unitless) * 1rem;
}
}
}
// Mixin to return all elements/sizes for an entire array set
// $type-sizes: ( $array: ( $key: $value ) );
@mixin all-type-sizes($array: 'base') {
@each $item, $value in map-get($type-sizes, $array) {
@include type-size-key-value-output($item,$value);
}
}
/* Example: output the base set of element/values */
@include all-type-sizes();
/* Example: output a specific set of element/values */
@media (min-width: bp(small) ) {
@include all-type-sizes(small);
}
/* Example: output one specific value for a breakpoint/element */
.element { font-size: px2em( type-size(small,h1) ); }
// Iterate over the list of breakpoints and return only one element at all sizes
// $breakpoints: ( $bp-name: $bp-value );
// $type-sizes: ( $key: ( $elem: $value ) );
@mixin one-type-size( $elem: 'base' ) {
// First, loop over the breakpoints
@each $bp-name, $bp in $breakpoints {
@if map-has-key($type-sizes,$bp-name) {
// Found a matching key value for an array of type sizes
// Now loop over those matched key/value pairs
@each $key, $value in map-get($type-sizes,$bp-name) {
// When there are values in $type-sizes that match the name of a $breakpoints
@if $elem == $key {
// Finally, we output some CSS
@if $bp-name == 'base' {
@include type-size-key-value-output($key,$value);
} @else {
@media (min-width: px2em($bp)) {
@include type-size-key-value-output($key,$value);
}
}
}
}
}
}
}
/* Example: output the entire array of sizes according to breakpoints for one element */
/* The base element */
@include one-type-size() {}
/* The H1 element */
@include one-type-size(h1) {}
/* The .micro class */
@include one-type-size(micro) {}
@jhogue
Copy link
Author

jhogue commented Oct 30, 2015

The idea: predefine a list of responsive typography sizes. Output them all together in one go to make applying them easy, or, allow one value to be called for one-off elements.

Important personal goals:

  • Allow hand-curated type sizes instead of forcing a scale mathematically
  • Allow a different type scale for different viewport width
  • Allow the ability to get all sizes at once, or just one size at a time

Requested: A new function that would return the responsive value of just one element (iterate over the Map to get all the H1 values for all breakpoints, for instance).

@jhogue
Copy link
Author

jhogue commented Nov 2, 2015

Updated with a new core set of functions. Added breakpoints into the mix as another map, and renamed the $key values of the type-size Map to correspond. That allowed me to create a function that loops over the breakpoints, and if a $key name in the $type-sizes Map matches the name of the breakpoint, we output the requested element and value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment