Skip to content

Instantly share code, notes, and snippets.

@rogerioyokoi
Last active November 15, 2022 05:59
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rogerioyokoi/15dba8b7bc2bf46fe27c6061ab6209a2 to your computer and use it in GitHub Desktop.
Save rogerioyokoi/15dba8b7bc2bf46fe27c6061ab6209a2 to your computer and use it in GitHub Desktop.
A Sass(scss) breakpoints managment system.
@use 'sass:map';
@use 'sass:list';
@use 'sass:meta';
@use 'sass:math';
///
/// Convert Pixels to REM
///
@function to-rem($size, $context) {
@return (math.div(strip-unit($size), $context)) * 1rem;
}
///
/// Convert Pixel To EM
///
@function to-em($size, $context) {
@return (math.div(strip-unit($size), $context)) * 1em;
}
///
/// Generic function to return a conversion
///
@function to($size, $unit, $context: 16) {
@if $unit == "rem" {
@return to-rem($size, $context);
}
@if $unit == "em" {
@return to-em($size, $context);
}
}
///
/// Validate variable is a map
///
@function is-map($value) {
@return meta.type-of($value) == 'map';
}
///
/// @access private
/// Breakpoints default map configuration
///
$breakpoints: (
xs: 0,
sm: 600px,
md: 900px,
lg: 1200px,
xl: 1566px,
) !default;
///
/// @access private
/// Get a minimum value of breakpoint name;
/// @param {String} $name Name of breakpoint
/// @return {String | Null} Returns the minimum value of breakpoint or null if is 0
///
@function get-breakpoint-min($name) {
$min: map.get($breakpoints, $name);
@return if($min != 0, $min, null);
}
///
/// @access private
/// Get a maximun value of breakpoint name;
/// @param {String} $name Name of breakpoint
/// @param {Map} $bps Use default breakpoints map
/// @return {String | Null} Returns the maximun value of breakpoint or null if is 0
///
@function get-breakpoint-max($name) {
$max: map.get($breakpoints, $name);
@return if($max != null and $max > 0, $max - .02, null);
}
///
/// @access private
/// Search and returns the last breakpoint if exists
/// @param {String} $name Name of current breakpoint
/// @return {String} the name of last breakpoint or null if not exists
///
@function get-breakpoint-next($name) {
$keys: map.keys($breakpoints);
$index: list.index($keys, $name);
@if not $index {
@error "breakpoint `#{$name}` not found";
}
@return if($index < length($keys), nth($keys, $index + 1), null);
}
///
/// @access public
/// Add or Update a breakpoint value on map
/// @param {String} $name Name of breakpoint
/// @param {Pixel} $value Value in pixels of breakpoint
/// @returns {Map} Of updated breakpoints;
///
@function add-or-update-breakpoint($name, $value) {
@if not $name and not $value {
@error '$name and $value is required to add or update $breakpoints map';
}
@return map.set($breakpoints, $name, $value);
}
///
/// @access public
/// Remove a breakpoint value on map
/// @param {String} $name Name of breakpoint
/// @returns {Map} Of updated breakpoints;
///
@function remove-breakpoint($name) {
@if not $name {
@error '$name is required to remove value of $breakpoints map';
}
@return map.remove($breakpoints, $name);
}
/**
* MIXINS
*/
///
/// @access private
/// Private mixin to validate to insert media queries
/// @param {Pixel} $min Minimum size of media queries
/// @param {Pixel} $max Maximum size of media queries
/// @returns {@Content} Callback content;
///
@mixin set-valid-breakpoint($min: null, $max: null) {
@if $min != null and $max != null {
@media (min-width: #{to($min, em)}) and (max-width: #{to($max, em)}) {
@content;
}
} @else if $max == null {
@media screen and (min-width: #{to($min, em)}) {
@content;
}
} @else if $min == null {
@media screen and (max-width: #{to($max, em)}) {
@content;
}
} @else {
@content;
}
}
/// Set breakpoint up size based on breakpoint name
/// @param {String} $name Name of breakpoint
/// @returns {@Content} Callback content;
@mixin set-breakpoints-up($name) {
$min: get-breakpoint-min($name);
@include set-valid-breakpoint($min, null){
@content;
}
}
///
/// Set breakpoint down size based on breakpoint name
/// @param {String} $name Name of breakpoint
/// @returns {@Content} Callback content;
///
@mixin set-breakpoints-down($name) {
$max: get-breakpoint-max($name);
@include set-valid-breakpoint(null, $max){
@content;
}
}
///
/// Set breakpoint between a breakpoint name and the next breakpoint
/// @param {String} $name Name of breakpoint
/// @returns {@Content} Callback content;
///
@mixin set-breakpoints-only($name) {
$min: get-breakpoint-min($name);
$next: get-breakpoint-next($name);
$max: get-breakpoint-max($next);
@include set-valid-breakpoint($min, $max){
@content;
}
}
///
/// Set breakpoint between two breakpoints in breakpoint map
/// @param {String} $minName Name of breakpoint of minimum size
/// @param {String} $maxName Name of breakpoint of maximum size
/// @returns {@Content} Callback content;
///
@mixin set-breakpoint-between($minName, $maxName) {
$min: get-breakpoint-min($minName);
$max: get-breakpoint-max($maxNname);
@include set-valid-breakpoint($min, $max){
@content;
}
}
///
/// Set a custom breakpoint bases in custom sizes
/// @param {Pixel} $minSize Minimum size of this breakpoint
/// @param {Pixel} $maxSize Maximum size of this breakpoint
/// @returns {@Content} Callback content;
///
@mixin set-custom-breakpoint($minSize, $maxSize) {
@include set-valid-breakpoint($minSize, $maxSize){
@content;
}
}
///
/// @access private
/// Set a map of breakpoints in :root
///
@mixin set-breakpoints-root() {
:root {
@each $name, $size in $breakpoints {
--breakpoint-#{$name}: #{util.to($size, em)};
}
}
}
///
/// @access private
/// Set a breakpoint utility class
///
@mixin set-breakpoints-utility-classes() {
@each $name, $value in $breakpoints {
$min: get-breakpoint-min($name);
$next: get-breakpoint-next($name);
$max: get-breakpoint-max($next);
@include set-breakpoints-only($name) {
.hide-#{$name}-only {
display: none;
}
.show-#{$name}-only {
display: block;
}
}
@if $min {
@include set-breakpoints-down($name) {
.hide-#{$name}-down {
display: none;
}
}
}
@if $next {
@include set-breakpoints-down($next) {
.show-#{$name}-down {
display: none;
}
}
}
@if $name != xs {
@include set-breakpoints-up($name) {
.hide-#{$name}-up {
display: none;
}
.show-#{$name}-up {
display: block;
}
}
}
}
}
///
/// Run mixins of breakpoints configurations
///
@mixin breakpoints-init() {
@include set-breakpoints-root;
@include set-breakpoints-utility-classes;
}
///
/// Set new breakpoints map configurations
/// @param {Map} $bps New breakpoints map
/// @return {Void}
///
@mixin breakpoint-configure($bps: null) {
@if not is-map($bps) {
@error 'Breakpoints configure mixin expects a map of breakpoints';
}
$breakpoints: $bps !global;
}
/**
* MIXINS
*/
{
"sass": {
"compiler": "dart-sass/1.32.12",
"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