lib/dd.breakpoints.scss (226 lines of code) (raw):

/** * Breakpoints for SCSS. Works with the Deloitte Digital DD.bp JavaScript * * @version 2.0.4 * @copyright 2012-2021 Deloitte Digital Australia - http://www.deloittedigital.com/au * @author Deloitte Digital Australia deloittedigital@deloitte.com.au * @license BSD 3-Clause (http://opensource.org/licenses/BSD-3-Clause) */ @use "sass:map"; @use "sass:math"; // Global variables $is-responsive: true !default; // toggles if responsive stylesheets are required - used for outputting legacy non-responsive stylesheets using the same code $base-font-size: 16 !default; // sets the base font size so that em to px conversions can be calculated correctly // developer mode $dev-mode: () !default; $_dev-mode: ( enabled: false, selector: "body::after", position: top left, on-dark: false ); // merge defaults with user config $_dev-mode: map.merge($_dev-mode, $dev-mode); // Min breakpoint sizes $breakpoints: ( xxs: 359, xs: 480, s: 640, m: 768, l: 1024, xl: 1244, xxl: 1410, xxxl: 1570, fhd: 1900, ) !default; // Range for the static stylesheet to use. Is used when $is-responsive is equal to false // and ignores breakpoints outside of the specified range $static: ( min: 0, max: 1244 ) !default; // Range for the print stylesheet to use. It applies @media screen to breakpoints outside of this $print: ( min: 0, max: 550 ) !default; // Automatically calculate the max breakpoints based on the min breakpoints provided @function _calc-max-bps() { $bps-max: (); $key: false; @each $bp in $breakpoints { @if $key == false { $key: nth($bp, 1); } @else { $bps-max: map.merge($bps-max, (#{$key}: nth($bp, 2) - 1)); $key: nth($bp, 1); } } @return $bps-max; } // Max breakpoint sizes $_breakpoints-max: _calc-max-bps(); // Adds the em unit to a number @function _add-em($number, $type: "em") { @if type_of($number) == "number" { $unit: 1em; @if $type == "rem" { $unit: 1rem; } @return math.div($number, $number * 0 + 1) * $unit; } @else { @error "Expected number but was passed #{type_of($number)}: #{$number}"; } } // Converts px to ems using the $base-font-size global variable @function _px-to-ems($px) { @return math.div($px, $base-font-size); } // Converts a bp name (e.g. l) to the px variable then to ems @function _bp-to-ems($bp, $ismax: false) { @if type_of($bp) == "number" { @return _px-to-ems($bp); } $bps: $breakpoints; @if $ismax == true { $bps: $_breakpoints-max; } $width: _px-to-ems(map.get($bps, $bp)); @return $width; } // Check if the bp provided falls inside the valid min/max region @function _bp-is-valid-between($valid-min, $valid-max, $min, $max: 0, $property: width) { // ignore height media queries @if ($property != width) { @return false; } // setup em values for all breakpoints $valid-min-ems: _bp-to-ems($valid-min); $valid-max-ems: _bp-to-ems($valid-max); $min-ems: _bp-to-ems($min); $max-ems: _bp-to-ems($max); // if max is 0 we have a min-and-above situation @if ($max == 0) { // need to check that the min is greater than the valid min, // AND also that the min is less than the valid maximum @if ($min-ems >= $valid-min-ems) and ($min-ems < $valid-max-ems) { @return true; } @return false; } // if min is 0 we have a max-and-below situation @if ($min == 0) { @if ($max-ems >= $valid-max-ems) { @return true; } @return false; } // if the min is above the valid max, or the max is below the valid min @if ($min-ems > $valid-max-ems) or ($max-ems < $valid-min-ems) { @return false; } // if the breakpoint is a bp-between (assumed because $max and $min aren't 0) // don't show if the max isn't above the valid max @if ($max-ems < $valid-max-ems) { @return false; } @return true; } // Check if the content should be in the print stylesheet @function _bp-is-valid-for-print($min, $max: 0, $property: width) { @return _bp-is-valid-between(map.get($print, "min"), map.get($print, "max"), $min, $max, $property); } // Check if the content should be in the static stylesheet @function _bp-is-valid-for-static($min, $max: 0, $property: width) { @return _bp-is-valid-between(map.get($static, "min"), map.get($static, "max"), $min, $max, $property); } // Returns a min-width media query based on bp name or px @mixin _min($min, $property: width) { @if $is-responsive == true { $bp-min: _add-em(_bp-to-ems($min, false)); $bp-type: min-#{$property}; @if _bp-is-valid-for-print($min, 0, $property) { @media ($bp-type: $bp-min) { @content; } } @else { @media only screen and ($bp-type: $bp-min) { @content; } } } @else { @if _bp-is-valid-for-static($min, 0, $property) { @if _bp-is-valid-for-print($min, 0, $property) { @content; } @else { @media screen { @content; } } } } } // Returns a max-width media query based on bp name or px @mixin _max($max, $property: width) { @if $is-responsive == true { $bp-max: _add-em(_bp-to-ems($max, true)); $bp-type: max-#{$property}; @if _bp-is-valid-for-print(0, $max, $property) { @media ($bp-type: $bp-max) { @content; } } @else { @media only screen and ($bp-type: $bp-max) { @content; } } } @else { @if _bp-is-valid-for-static(0, $max, $property) { @if _bp-is-valid-for-print(0, $max, $property) { @content; } @else { @media screen { @content; } } } } } // Returns a min-width and max-width media query based on bp name (can be the same bp name) or px @mixin _between($min, $max, $property: width) { @if $is-responsive == true { $bp-min: _add-em(_bp-to-ems($min, false)); $bp-max: _add-em(_bp-to-ems($max, true)); $bp-type-min: min-#{$property}; $bp-type-max: max-#{$property}; @if _bp-is-valid-for-print($min, $max, $property) { @media ($bp-type-min: $bp-min) and ($bp-type-max: $bp-max) { @content; } } @else { @media only screen and ($bp-type-min: $bp-min) and ($bp-type-max: $bp-max) { @content; } } } @else { @if _bp-is-valid-for-static($min, $max, $property) { @if _bp-is-valid-for-print($min, $max, $property) { @content; } @else { @media screen { @content; } } } } } // Main width based breakpoint mixin - can use both px (will be converted to ems) or breakpoints names (e.g. s, m, l) @mixin get($min, $max:0, $property: width) { @if $min == retina or $min == hdpi { // if the first variable is "retina" then we don't need the standard bp mixin @media (-webkit-min-device-pixel-ratio: 1.5), (min--moz-device-pixel-ratio: 1.5), (-o-min-device-pixel-ratio: 3/2), (min-device-pixel-ratio: 1.5) { @content; } } @else if $min == static { @if $is-responsive == false { @content; } } @else if $max == 0 { // @include bp.get(l); if the second variable is blank or 0, we want min (e.g. large and above) @include _min($min, $property) { @content; } } @else if $min == 0 { // @include bp.get(0, l); if the first variable is 0, we want max (e.g. large and below) @include _max($max, $property) { @content; } } @else { // @include bp.get(s, l); if both variables are different, we want between (e.g. small to large) // @include bp.get(l, l); if both are the same, we want just that breakpoint (e.g. large) @include _between($min, $max, $property) { @content; } } } // Height based breakpoint mixin - can use px (will be converted to ems) @mixin get-height($min, $max:0) { @include get($min, $max, height) { @content; } } // return the min width of a breakpoint in either px or ems (default) @function get-width-from-bp($bp, $type: "em") { @if $type == "px" { @return map.get($breakpoints, $bp) + "px"; } @if $type == "em" or $type == "rem" { @return _add-em(_px-to-ems(map.get($breakpoints, $bp)), $type); } @error "Invalid unit type #{$type}. Valid types are 'px', 'em' or 'rem'."; @return 0; } // Developer Mode - displays a small panel indicating the current breakpoint name @if map.get($_dev-mode, "enabled") == true { #{map.get($_dev-mode, "selector")} { opacity: 0.5; font-size: 10px; display: block; position: fixed; z-index: 9999999; padding: 0 5px; font-family: monospace; content: "none"; @if map.get($_dev-mode, "on-dark") == true { color: #FFF; background-color: #000; } @else { color: #000; background-color: #FFF; } @each $prop in map.get($_dev-mode, "position") { #{$prop}: 0; } @each $bp in $breakpoints { @include get(nth($bp, 1)) { content: "#{nth($bp, 1)}"; } } } }