Skip to content

Instantly share code, notes, and snippets.

@tedw
Created January 16, 2021 19:26
Show Gist options
  • Save tedw/f8ba9be15cf926d2dc983a7004c089a6 to your computer and use it in GitHub Desktop.
Save tedw/f8ba9be15cf926d2dc983a7004c089a6 to your computer and use it in GitHub Desktop.
Generated by SassMeister.com.
/// Base font size
/// @group Main
/// @type Number
$fs-base-font-size: 16px !default;
/// Convert px to em
/// @group Main
/// @param {Number | Map} $values - Value or values to convert
/// @param {Number} $context [$fs-base-font-size] - Base font size
/// @return {*} - Converted value or list of values
/// @require {variable} $fs-base-font-size - Base font size
@function fs-em($values, $context: $fs-base-font-size) {
// Ensure context size is in pixels
@if unit($context) != 'px' {
@error '🔴 #{$context} size must be in pixels';
}
// Placeholder list for converted values
$output: ();
@each $val in $values {
// Check if pixel value
@if type-of($val) == 'number' and unit($val) == 'px' {
// Convert to ems
$val: ($val / $context) * 1em;
}
// Do nothing to all other values
@else if $fs-debug-mode {
@warn '⚠️ Can’t convert non-pixel value to ems: #{$val}';
}
// Append value to output list
$output: append($output, $val);
}
// Return converted value(s)
@return $output;
}
/// Convert px to rem
/// @group Main
/// @param {Number | Map} $values - Value values to convert
/// @param {Number} $context [$fs-base-font-size] - Base font size
/// @return {*} - Converted value or list of values
/// @require {variable} $fs-base-font-size - Base font size
@function fs-rem($values) {
// Placeholder list for converted values
$output: ();
@each $val in $values {
// Check if pixel value
@if type-of($val) == 'number' and unit($val) == 'px' {
// Convert to rems
$val: ($val / $fs-base-font-size) * 1rem;
}
// Do nothing to all other values
@else if $fs-debug-mode and $val != 0 {
@warn '⚠️ Can’t convert non-pixel value to rems: #{$val}';
}
// Append value to output list
$output: append($output, $val);
}
// Return converted value(s)
@return $output;
}
////
/// @group Main
////
/// Base media query mixin
/// @param {Number | Map} $conditions - Width or map of conditions
///
/// @example scss
/// @include fs-media((min-width: 600px)) {…}
///
/// @include fs-media((min-width: 600px, max-width: 900px, min-height: 500px, min-aspect-ratio: "1/1")) {…}
///
/// @ignore Convert units to ems when applicable http://zellwk.com/blog/media-query-units/
/// @ignore Note: EMs in media queries are relative to the initial browser font-size (16px) http://www.w3.org/TR/css3-mediaqueries/#units
/// @ignore Demo: http://www.sassmeister.com/gist/908ff8ee2e2e0b18f768fcbc87df385c
@mixin fs-media($conditions) {
// Check if $conditions is a valid map
@if type-of($conditions) != 'map' {
@error '🔴 “#{$conditions}” is not a valid Sass map';
}
@else {
$mq-conditions: '';
// Convert map to properly formatted media query string
@each $type, $value in $conditions {
// If value is a number, we may need to convert to ems
@if type-of($value) == 'number' {
// Convert px to em
@if unit($value) == 'px' {
$value: ($value / 16px) * 1em;
}
// Convert rem to em
@else if unit($value) == 'rem' {
$value: ($value / 1rem) * 1em;
}
}
// Use str-insert() with -1 index to append value to the end
$mq-conditions: str-insert($mq-conditions, 'and (#{$type}: #{$value}) ', -1);
}
// Output the media query
@media all #{$mq-conditions} {
@content;
}
}
}
/// Min-width media query helper
/// @require {mixin} fs-media
/// @param {Number} $width - Breakpoint width
///
/// @example scss
/// @include fs-min-width(960px) {…}
///
@mixin fs-min-width($width) {
@include fs-media((min-width: $width)) {
@content;
}
}
/// Max-width media query helper
/// @require {mixin} fs-media
/// @param {Number} $width - Breakpoint width
///
/// @example scss
/// @include fs-max-width(960px) {…}
///
@mixin fs-max-width($width) {
@include fs-media((max-width: $width)) {
@content;
}
}
/// Min-height media query helper
/// @require {mixin} fs-media
/// @param {Number} $height - Breakpoint height
///
/// @example scss
/// @include fs-min-height(500px) {…}
///
@mixin fs-min-height($height) {
@include fs-media((min-height: $height)) {
@content;
}
}
/// Max-height media query helper
/// @require {mixin} fs-media
/// @param {Number} $height - Breakpoint height
///
/// @example scss
/// @include fs-max-height(500px) {…}
///
@mixin fs-max-height($height) {
@include fs-media((max-height: $height)) {
@content;
}
}
@function fs-scale($start, $end, $min-width, $max-width, $units: 'rem') {
@if $start > 0 and $end > 0 and unit($start) != unit($end) {
@error '🔴 fs-scale() units don’t match';
}
$slope: ($end - $start) / ($max-width - $min-width);
$intercept: $end - ($slope * $max-width);
@if (fs-strip-unit($intercept) == 0) {
@return $slope * 100vw;
}
@else {
@if $units == 'em' {
@return calc(#{$slope * 100vw} + #{fs-em($intercept)});
}
@else {
@return calc(#{$slope * 100vw} + #{fs-rem($intercept)});
}
}
}
/// Scale a value for any number of properites relative to the viewport width
/// @group Main
/// @param {String | List} $properties - Properties to scale
/// @param {Number} $start - Starting value
/// @param {String} $units - Output units
/// @require {function} fs-rem
/// @require {function} fs-scale
/// @require {mixin} fs-min-width
/// @require {mixin} fs-max-width
/// @ignore Demo https://www.sassmeister.com/gist/9f87f8c19e91c811831d84fc8484ed24
/// @link http://www.sassmeister.com/gist/7f22e44ace49b5124eec
/// @link http://madebymike.com.au/writing/precise-control-responsive-typography/
/// @link https://zellwk.com/blog/viewport-based-typography/
/// @link http://codepen.io/indrekpaas/pen/VarLaJ?editors=1100
/// @link http://codepen.io/maranomynet/pen/ozNpXV?editors=1100
/// @link https://www.smashingmagazine.com/2016/05/fluid-typography/
/// @example scss
/// @include fs-scale(font-size, (320px:18px, 768px:26px, 1024px:38px);
/// @example scss
/// @include fs-scale(margin-bottom margin-top, (320px:18px, 768px:26px, 1024px:38px));
@mixin fs-scale-poly($properties, $map, $units: 'rem') {
$length: length($map);
@if ($length < 2) {
@error "fs-scale() requires at least two breakpoints"
}
$breakpoints: map-keys($map);
$values: map-values($map);
// Initial value
$start-val: nth($values, 1);
@each $property in $properties {
@if $units == 'em' {
#{$property}: fs-em($start-val);
}
@else {
#{$property}: fs-rem($start-val);
}
}
// Scale up with calc() at each breakpoint
@for $i from 1 through ($length - 1) {
$prev-breakpoint: nth($breakpoints, $i);
$new-breakpoint: nth($breakpoints, $i + 1);
$prev-value: nth($values, $i);
$new-value: nth($values, $i + 1);
@include fs-min-width($new-breakpoint) {
@each $property in $properties {
#{$property}: fs-scale($prev-value, $new-value, $prev-breakpoint, $new-breakpoint, $units);
}
}
}
// Final value
$end-val: nth($values, $length);
$end-breakpoint: nth($breakpoints, $length);
@include fs-min-width($end-breakpoint) {
@each $property in $properties {
@if $units == 'em' {
#{$property}: fs-em($end-val);
}
@else {
#{$property}: fs-rem($end-val);
}
}
}
}
.foo {
@include fs-scale-poly(font-size, (576px: 22px, 768px: 24px, 992px: 34px));
}
.bar {
@include fs-scale-poly(font-size, (576px: 22px, 768px: 24px, 992px: 34px), $units: em);
}
.foo {
font-size: 1.375rem;
}
@media all and (min-width: 48em) {
.foo {
font-size: calc(1.0416666667vw + 1rem);
}
}
@media all and (min-width: 62em) {
.foo {
font-size: calc(4.4642857143vw + -0.6428571429rem);
}
}
@media all and (min-width: 62em) {
.foo {
font-size: 2.125rem;
}
}
.bar {
font-size: 1.375em;
}
@media all and (min-width: 48em) {
.bar {
font-size: calc(1.0416666667vw + 1em);
}
}
@media all and (min-width: 62em) {
.bar {
font-size: calc(4.4642857143vw + -0.6428571429em);
}
}
@media all and (min-width: 62em) {
.bar {
font-size: 2.125em;
}
}
{
"sass": {
"compiler": "Ruby Sass/3.7.4",
"extensions": {},
"syntax": "SCSS",
"outputStyle": "expanded"
},
"autoprefixer": false
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment