Skip to content

Instantly share code, notes, and snippets.

@btpoe
Last active February 8, 2017 18:47
Show Gist options
  • Save btpoe/4f1077a6eb83e3b52f10 to your computer and use it in GitHub Desktop.
Save btpoe/4f1077a6eb83e3b52f10 to your computer and use it in GitHub Desktop.
Smooth transitions for different screen widths
////////////////////////////
// Slope Calc Mixin //
////////////////////////////
//
// Usage:
//
// .my-widget {
// @include slope-calc(padding, 20px 320px, 60px 1440px, 60px 1441px);
// }
//
// Outputs:
//
// .my-widget {
// padding: calc(3.57143vw + .53571rem);
// }
//
// @media only screen and (min-width: 90em)
// .my-widget {
// padding: 3.75rem;
// }
// }
//
//
// Flags:
//
// Flags are an optional argument passed in at the end of the slope-calc include.
// In scss, strings work with or without quotes.
//
// - important
// apply the css "!important" flag to the property (or properties) at all breakpoints.
//
// - clip
// at the largest breakpoint, set the property to a rem value to keep the property from growing any more.
//
//
@function remove($list, $value, $recursive: false) {
$result: ();
@for $i from 1 through length($list) {
@if type-of(nth($list, $i)) == list and $recursive {
$result: append($result, remove(nth($list, $i), $value, $recursive));
}
@else if nth($list, $i) != $value {
$result: append($result, nth($list, $i));
}
}
@return $result;
}
@function strip-unit($number) {
@if type-of($number) == 'number' and not unitless($number) {
@return $number / ($number * 0 + 1);
}
@return $number;
}
@function px-to-em($number, $base:16) {
@return (strip-unit($number)/$base) * 1em;
}
@function unitless-px($number, $base:16) {
@if(unitless($number)) {
@return $number;
}
@else {
$unit: unit($number);
$number: strip-unit($number);
@if ($unit == 'px') {
@return $number;
}
@return $number*$base;
}
}
@function rem($number, $base:16) {
@return unitless-px($number)/$base * 1rem;
}
@function slope-calc-internal($from, $to) {
$to-size: unitless-px(nth($to, 1));
$to-breakpoint: unitless-px(nth($to, 2)) / 100;
$from-size: unitless-px(nth($from, 1));
$from-breakpoint: unitless-px(nth($from, 2)) / 100;
@if($from-breakpoint > $to-breakpoint) {
$tmp: $to-breakpoint;
$to-breakpoint: $from-breakpoint;
$from-breakpoint: $tmp;
$tmp: $to-size;
$to-size: $from-size;
$from-size: $tmp;
}
$pieces: rem($from-size);
$calc: $pieces;
@if $from-size != $to-size {
$slope: ($to-size - $from-size) / ($to-breakpoint - $from-breakpoint);
$y-intercept: $from-size - ($from-breakpoint * $slope);
$pieces: $slope*1vw, ($y-intercept/16)*1rem;
$calc: calc(#{nth($pieces, 1)} + #{nth($pieces, 2)});
}
@return (
pieces: $pieces,
calc: $calc,
breakpoint: px-to-em($from-breakpoint*100px)
);
}
@function slope-calc($mobile, $desktop) {
@return map-get(slope-calc-internal($mobile, $desktop), calc);
}
@function slope-calc-transform($prop, $from, $to) {
$pieces: map-get(slope-calc-internal($from, $to), pieces);
@if type-of($pieces) == 'list' {
@return #{$prop + '(' + nth($pieces, 1) + ')'} #{$prop + '(' + nth($pieces, 2) + ')'};
}
@return #{$prop + '(' + $pieces + ')'};
}
@function slope-calc-args($slopes) {
$args: nth($slopes, length($slopes));
@if type-of($args) == 'string' or type-of($args) == 'list' and type-of(nth($args, 1)) == 'string' {
$slopes: remove($slopes, $args);
@if type-of($args) == 'string' {
$args: append((), $args);
}
}
@else {
$args: ();
}
@return (
args: $args,
slopes: $slopes
);
}
@mixin slope-calc($prop, $slopes...) {
@if type-of($prop) == 'list' {
@each $p in $prop {
@include slope-calc($p, $slopes...);
}
}
@else {
$getArgs: slope-calc-args($slopes);
$args: map-get($getArgs, args);
$slopes: map-get($getArgs, slopes);
$smallest: nth($slopes, 1);
@each $slope in $slopes {
@if unitless-px(nth($slope, 2)) < unitless-px(nth($smallest, 2)) {
$smallest: $slope;
}
}
$slopes: remove($slopes, $smallest);
$secondSmallest: nth($slopes, 1);
@each $slope in $slopes {
@if unitless-px(nth($slope, 2)) < unitless-px(nth($secondSmallest, 2)) {
$secondSmallest: $slope;
}
}
$results: slope-calc-internal($smallest, $secondSmallest);
$value: map-get($results, calc) if(index($args, important) != null, !important, null);
@if (nth($secondSmallest, 2) == (nth($smallest, 2) + 1)) {
$value: rem(unitless-px(nth($smallest, 1)));
}
@if index($args, media-query) == null {
#{$prop}: $value;
}
@else {
@media only screen and (min-width: #{map-get($results, breakpoint)}) {
#{$prop}: $value;
}
}
@if (index($args, media-query) == null) {
$args: append($args, media-query);
}
@if length($slopes) > 1 {
$slopes: append($slopes, $args);
@include slope-calc($prop, $slopes...);
}
@elseif (index($args, clip) != null) {
$args: remove($args, clip);
$slope: nth($slopes, 1);
$slopes: $slope, nth($slope, 1) nth($slope, 2) + 1, $args;
@include slope-calc($prop, $slopes...);
}
}
}
@mixin font-size($slopes...) {
@include slope-calc(font-size, $slopes...);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment