Skip to content

Instantly share code, notes, and snippets.

@frank-who
Last active June 15, 2020 06:52
Show Gist options
  • Save frank-who/bd147701fb4e8caf224c9b19d36899c2 to your computer and use it in GitHub Desktop.
Save frank-who/bd147701fb4e8caf224c9b19d36899c2 to your computer and use it in GitHub Desktop.
Sass baseline mixin

Usage

  h1,
  h2,
  h3,
  h4,
  h5,
  h6
    color: $c-txtPrimary
    font-family: $ff-primary
    font-weight: 700
    line-height: 1.15
    text-rendering: optimizeLegibility

  .a-h0
    +baseline(1.875rem, $baseline-spaces: 10)
    font-weight: 700

  h1, .a-h1
    +baseline(1.5rem, $baseline-spaces: 5)

  h2, .a-h2
    +baseline(1.25rem, $baseline-spread: 6, $baseline-spaces: 4)

  h3, .a-h3
    +baseline($fs-h3, $baseline-spread: 6, $baseline-spaces: 2)

  h4, .a-h4,
  h5, .a-h5,
  h6, .a-h6
    +baseline(0.875rem, $baseline-spread: 5, $baseline-spaces: 1)
    text-transform: uppercase

  address,
  dd,
  ol,
  p,
  ul,
  .a-p
    +baseline(1rem)
/*
How it works
============
Fonts are aligned to the designed baseline by adding padding to the top of the
tag and then removed from the bottom margin / padding by subtracting the same
value. This will ensure that the vertical rhythm is maintained and consistent
regardless of the font-size passed in.
Rules
=====
All margins and line-heights must be multiples of $--baseline. #NuffSaid
References
==========
* https://medium.com/@razvanonofrei/aligning-type-to-baseline-the-right-way-using-sass-e258fce47a9b
* https://codepen.io/fluxus/pen/BMGKMK?editors=1100
* https://jamonserrano.github.io/plumber-sass/measure
* https://open.nytimes.com/how-we-implemented-a-baseline-grid-using-css-cb13cac45201
* https://blog.prototypr.io/vertical-rhythm-in-sketch-3aca0642164e
*/
/// Set base font-size and line-height
///
$--base-line-height: 1.5;
$--base-font-size: 1rem;
/// Calculate cap height
/// Get `$--cap-height-ratio` from https://jamonserrano.github.io/plumber-sass/measure
///
$--cap-height-ratio: 0.113;
$--cap-height: 1 - (2 * $--cap-height-ratio);
/// Calculate baseline
/// Given `$--base-line-height` = `24px` and `$--base-font-size` = `16px`.
/// 6 = 4px baseline
/// 4 = 6px baseline
/// 3 = 8px baseline
/// 2 = 12px baseline
///
$--baseline-divisor: 6;
$--baseline: ($--base-line-height * $--base-font-size) / $--baseline-divisor;
/// @example
/// baseline(1rem)
///
/// @example
/// baseline($font-size:1rem, $baseline-spaces:2)
///
/// @param {Number} $font-size [$--base-font-size] - font size of the element in REM.
/// @param {String | Number} $baseline-spread [auto] - how many `$--baseline` units must the text span across. Can be a number or `auto`.
/// @param {Number} $baseline-spaces [$--baseline-divisor] - how many `$--baseline` units must be used for bottom spacing.
/// @param {String} $spacing-type [margin] - which spacing method must be used. Can be `margin` or `padding`.
/// @param {Bool} $enable [true] - enables or disables baseline calculations.
/// @param {Bool} $debug [true] - enables or disables visual debugging.
///
@mixin baseline(
$font-size: $--base-font-size,
$baseline-spread: auto,
$baseline-spaces: $--baseline-divisor,
$spacing-type: margin,
$enable: true,
$debug: false
) {
/// `$baseline-spread:auto` is simple default to get you started.
/// For best results tweak `$baseline-spread` with a number.
@if ($baseline-spread == auto) {
$--auto-offset: 0.5rem;
@if ($font-size < 1rem) {
$--auto-offset: 0.25rem;
}
$baseline-spread: ceil(($font-size + $--auto-offset) / $--baseline);
}
/// Re-calculate line-height based on the number of baseline units needed.
$--line-height: $--baseline * $baseline-spread;
/// `$--baseline-offset` pushes the text down using padding-top to align the font to `$--baseline`.
$--baseline-offset: 0;
@if ($enable == true) {
$--baseline-offset: (($--line-height - $--cap-height * $font-size) / 2);
}
/// `$--baseline-offset` needs to be subtracted from `$--bottom-space` to stay on rhythm.
$--bottom-space: ($baseline-spaces * $--baseline) - $--baseline-offset;
@if ($--bottom-space < 0) {
$--bottom-space: 0;
}
--baseline-offset: #{$--baseline-offset};
--baseline: #{$--baseline};
--baseline-spread: #{$baseline-spread};
--bottom-space: #{$--bottom-space};
--line-height: #{$--line-height};
font-size: $font-size;
line-height: $--line-height;
padding-top: $--baseline-offset;
@if ($spacing-type == margin) {
margin-bottom: $--bottom-space;
} @else if ($spacing-type == padding) {
padding-bottom: $--bottom-space;
}
@if ($debug == true) {
background: rgba(#89B3BD, 0.3) linear-gradient(to bottom, rgba(red, 0.8) 0, transparent 1px) repeat-y;
background-size: 100% $--baseline * $baseline-spread;
color: black;
padding-left: 100px !important;
position: relative;
&:before {
background-color: rgba(green, 0.3) !important;
content: '';
height: $--baseline-offset;
left: 0;
position: absolute;
right: 0;
top: 0;
};
&:after {
background-color: rgba(orange, 0.3) !important;
bottom: $--bottom-space * -1;
content: '';
height: $--bottom-space;
left: 0;
position: absolute;
right: 0;
}
}
}
body.u-debug-baseline
background: #FFF linear-gradient(to bottom, cyan 0, transparent 1px) repeat-y
background-size: 100% $--baseline
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment