Skip to content

Instantly share code, notes, and snippets.

@tylerpaige
Last active August 6, 2020 15:09
Show Gist options
  • Save tylerpaige/63dc3cf5fdb8e8a98175e6c5c883e0d3 to your computer and use it in GitHub Desktop.
Save tylerpaige/63dc3cf5fdb8e8a98175e6c5c883e0d3 to your computer and use it in GitHub Desktop.
/*
This mixin requires some global variables to be set up in the following pattern
*/
$breakpoints: (
xs: 15rem, //240px
sm: 30rem, //480px
md: 48rem, //768px
lg: 62rem, //992px
xl: 75rem //1200px
);
$breakpoint-names: map-keys($breakpoints);
$narrowest-breakpoint: nth($breakpoint-names, 1);
$widest-breakpoint: nth($breakpoint-names, -1);
/*
Wraps the enclosed styles in a media query that targets a given breakpoint
based on the viewport width. Optionally allows fine-tuned control over the
bounds of the media query.
@param {string|number} $breakpoint The name of the breakpoint [xs, sm, md, lg, xl] *or* a number which should be used for the media query
@param {string} $scope How to structure the media query ['andWider', 'andNarrower', 'only']
example:
.my-selector {
color: red;
@include breakpoint(md, only) {
color: blue;
}
@include breakpoint(lg, andWider) {
color: green;
}
@include breakpoint(24rem) {
color: purple;
}
}
*/
@mixin breakpoint($breakpoint, $scope: "and-wider") {
$lower-bound: null;
$upper-bound: null;
// NOTE: additional logic in this boolean because `1col` reads as a number
$is-custom-breakpoint: not(str-index(#{$breakpoint}, "col")) and
type-of($breakpoint) == number;
// First get the upper and lower bounds of our media query.
@if $is-custom-breakpoint {
@if $scope == "and-narrower" {
$upper-bound: $breakpoint;
} @else {
$lower-bound: $breakpoint;
}
} @else if map-has-key($breakpoints, $breakpoint) {
@if $scope == "and-narrower" {
// NOTE: 0.0625rem == 1px when the default font size is 16px
$upper-bound: map-get(
$breakpoints,
nth($breakpoint-names, index($breakpoint-names, $breakpoint) + 1)
) -
0.0625rem;
} @else if ($scope == "only" and $breakpoint != $widest-breakpoint) {
// NOTE: 0.0625rem == 1px when the default font size is 16px
$lower-bound: map-get($breakpoints, $breakpoint);
$upper-bound: map-get(
$breakpoints,
nth($breakpoint-names, index($breakpoint-names, $breakpoint) + 1)
) -
0.0625rem;
} @else if ($breakpoint != $narrowest-breakpoint) {
$lower-bound: map-get($breakpoints, $breakpoint);
}
} @else {
@warn "Breakpoint '#{$breakpoint}' not found.";
}
// Then, depending on the presence of both/either upper and lower bounds, construct the media query.
@if $lower-bound and $upper-bound {
@media screen and (min-width: $lower-bound) and (max-width: $upper-bound) {
@content;
}
} @else if $lower-bound {
@media screen and (min-width: $lower-bound) {
@content;
}
} @else if $upper-bound {
@media screen and (max-width: $upper-bound) {
@content;
}
} @else {
@content;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment