/* * Copyright (c) 2016 Martin Donath * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ /* ---------------------------------------------------------------------------- * Variables * ------------------------------------------------------------------------- */ /* * Device-specific breakpoints * * @type Map */ $break-devices: () !default; /* ---------------------------------------------------------------------------- * Breakpoint helpers * ------------------------------------------------------------------------- */ /* * Choose minimum and maximum device widths * * @param {Map} $devices Map of devices * @return {List} Minimum and maximum width */ @function break-select-min-max($devices) { $min: 1000000; $max: 0; @each $key, $value in $devices { @while type-of($value) == map { $value: break-select-min-max($value); } @if type-of($value) == list { @each $number in $value { @if type-of($number) == number { $min: min($number, $min); @if $max != null { $max: max($number, $max); } } @else { @error "Invalid number: #{$number}"; } } } @elseif type-of($value) == number { $min: min($value, $min); $max: null; } @else { @error "Invalid value: #{$value}"; } } @return $min, $max; } /* * Select minimum and maximum widths for a device breakpoint * * @param {String} $device Device * @return {List} Minimum and maximum width */ @function break-select-device($device) { $current: $break-devices; @for $n from 1 through length($device) { @if type-of($current) == map { $current: map-get($current, nth($device, $n)); } @else { @error "Invalid device map: #{$devices}"; } } @if type-of($current) == list or type-of($current) == number { $current: (default: $current); } @return break-select-min-max($current); } /* ---------------------------------------------------------------------------- * Breakpoint mixins * ------------------------------------------------------------------------- */ /* * A minimum-maximum media query breakpoint * * @param {Number|List} $breakpoint Number or number pair */ @mixin break-at($breakpoint) { @if type-of($breakpoint) == number { @media only screen and (min-width: $breakpoint) { @content; } } @elseif type-of($breakpoint) == list { $min: nth($breakpoint, 1); $max: nth($breakpoint, 2); @if type-of($min) == number and type-of($max) == number { @media only screen and (min-width: $min) and (max-width: $max) { @content; } } @else { @error "Invalid breakpoint: #{$breakpoint}"; } } @else { @error "Invalid breakpoint: #{$breakpoint}"; } } /* * An orientation media query breakpoint * * @param {String} $breakpoint Orientation */ @mixin break-at-orientation($breakpoint) { @if type-of($breakpoint) == string { @media only screen and (orientation: $breakpoint) { @content; } } @else { @error "Invalid breakpoint: #{$breakpoint}"; } } /* * A maximum-aspect-ratio media query breakpoint * * @param {Number} $breakpoint Ratio */ @mixin break-at-ratio($breakpoint) { @if type-of($breakpoint) == number { @media only screen and (max-aspect-ratio: $breakpoint) { @content; } } @else { @error "Invalid breakpoint: #{$breakpoint}"; } } /* * A minimum-maximum media query device breakpoint * * @param {String|List} $breakpoint Device */ @mixin break-at-device($device) { @if type-of($device) == string { $device: $device,; } @if type-of($device) == list { $breakpoint: break-select-device($device); @if nth($breakpoint, 2) != null { $min: nth($breakpoint, 1); $max: nth($breakpoint, 2); @media only screen and (min-width: $min) and (max-width: $max) { @content; } } @else { @error "Invalid device: #{$device}"; } } @else { @error "Invalid device: #{$device}"; } } /* * A minimum media query device breakpoint * * @param {String|List} $breakpoint Device */ @mixin break-from-device($device) { @if type-of($device) == string { $device: $device,; } @if type-of($device) == list { $breakpoint: break-select-device($device); $min: nth($breakpoint, 1); @media only screen and (min-width: $min) { @content; } } @else { @error "Invalid device: #{$device}"; } } /* * A maximum media query device breakpoint * * @param {String|List} $breakpoint Device */ @mixin break-to-device($device) { @if type-of($device) == string { $device: $device,; } @if type-of($device) == list { $breakpoint: break-select-device($device); $max: nth($breakpoint, 2); @media only screen and (max-width: $max) { @content; } } @else { @error "Invalid device: #{$device}"; } }