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)}";
}
}
}
}