Skip to content

Instantly share code, notes, and snippets.

@hpohlmeyer
Last active August 29, 2015 14:13
Show Gist options
  • Save hpohlmeyer/fde8742dfc8c07f6a463 to your computer and use it in GitHub Desktop.
Save hpohlmeyer/fde8742dfc8c07f6a463 to your computer and use it in GitHub Desktop.
A use case for Sass variable name interpolation
// I am using flat variables, following the SUIT naming convention. Every
// variable should be available in the global space for reference of single
// values, whithout the need to rely on mixins.
//
// I know this can be done with maps and mixins, but that would require to
// ignore the variable naming scheme, I use for every other variable in the
// project.
$--bpMobileRangeMax: 334px;
$--bpMobileRangeMin: null;
$--bpMobileColWidth: 237px;
$--bpMobileMaxWidth: 237px;
$--bpTabletSmallRangeMax: 569px;
$--bpTabletSmallRangeMin: 235px;
$--bpTabletSmallColWidth: 67px;
$--bpTabletSmallMaxWidth: 569px;
$--bpTabletRangeMax: 767px;
$--bpTabletRangeMin: 570px;
$--bpTabletColWidth: 62px;
$--bpTabletMaxWidth: 767px;
$--bpDesktopRangeMax: 1021px;
$--bpDesktopRangeMin: 768px;
$--bpDesktopColWidth: 65px;
$--bpDesktopMaxWidth: 952px;
$--bpDesktopHdRangeMax: null;
$--bpDesktopHdRangeMin: 1022px;
$--bpDesktopHdColWidth: 65px;
$--bpDesktopHdMaxWidth: 1021px;
/**
* Media Query for Breakpoint
*
* @param {string} $name Name of the breakpoint, if second param is defined, it is the min breakpoint value
* @param {string} $name-max Name of the max brakpoint
*
* @example scss
* @include breakpoint(mobile);
* @example - description
* Spans over the mobile breakpoint.
*
* @example scss
* @include breakpoint(mobile, tablet);
* @example - description
* Spans over the mobile breakpoint to the tablet breakpoint and includes all in between.
*/
@mixin breakpoint($name, $name-max: null) {
@if $name-max != null {
@if $--bp#{$name}RangeMin and $--bp#{$name}RangeMax {
@media screen and (min-width: $--bp#{$name}RangeMin) and (max-width: $--bp#{$name}RangeMax) { @content; }
} @else if $--bp#{$name}RangeMin {
@media screen and (min-width: $--bp#{$name}RangeMin) { @content; }
} @else if $--bp#{$name}RangeMax {
@media screen and (min-width: $--bp#{$name}RangeMin) and (max-width: $--bp#{$name}RangeMax) { @content; }
} @else {
@error "There are no min or max ranges defined for #{$name}.";
}
} @else {
@if $--bp#{$name}RangeMin and $--bp#{$name-max}RangeMax {
@media screen and (min-width: $--bp#{$name}RangeMin) and (max-width: $--bp#{$name-max}RangeMax) { @content; }
} @else if $--bp#{$name}RangeMin {
@media screen and (min-width: $--bp#{$name}RangeMin) { @content; }
@warn "No max range defined for #{$name-max}. Max set to infinite.";
} @else if $--bp#{$name-max}RangeMax {
@media screen and (max-width: $--bp#{$name-max}RangeMax) { @content; }
@warn "No min range defined for #{$name}. Min set to infinite.";
}
}
}
@include breakpoint("Mobile", "Desktop") {
body {
max-width: $--bpDesktopMaxWidth;
}
}
// This is the map solution. As you can see, I have to use a second mixin.
// To do it this way gives me zero benefits and forces me to break my
// variable naming convention.
$breakpoints: (
Mobile: (
RangeMax: 334px,
RangeMin: null,
ColWidth: 237px,
MaxWidth: 237px
),
TabletSmall: (
RangeMax: 569px;
RangeMin: 235px;
ColWidth: 67px;
MaxWidth: 569px;
),
Tablet: (
RangeMax: 767px;
RangeMin: 570px;
ColWidth: 62px;
MaxWidth: 767px;
),
Desktop: (
RangeMax: 1021px,
RangeMin: 768px,
ColWidth: 65px,
MaxWidth: 952px
),
DesktopHd: (
RangeMax: null;
RangeMin: 1022px;
ColWidth: 65px;
MaxWidth: 1021px;
)
);
/**
* Media Query for Breakpoint
*
* @param {string} $name Name of the breakpoint, if second param is defined, it is the min breakpoint value
* @param {string} $name-max Name of the max brakpoint
*
* @example scss
* @include breakpoint(mobile);
* @example - description
* Spans over the mobile breakpoint.
*
* @example scss
* @include breakpoint(mobile, tablet);
* @example - description
* Spans over the mobile breakpoint to the tablet breakpoint and includes all in between.
*/
@mixin breakpoint($name, $name-max: null) {
$first-bp: map-get($breakpoints, $name);
$second-bp: null;
@if $name-max != null { $second-bp: map-get($breakpoints, $name-max) };
@if $second-bp == null {
@if map-get($first-bp, RangeMin) and map-get($first-bp, RangeMax) {
@media screen and (min-width: map-get($first-bp, RangeMin)) and (max-width: map-get($first-bp, RangeMax)) { @content; }
} @else if map-get($first-bp, RangeMin) {
@media screen and (min-width: map-get($first-bp, RangeMin)) { @content; }
} @else if map-get($first-bp, RangeMax) {
@media screen and (max-width: map-get($first-bp, RangeMax)) { @content; }
} @else {
@error "There are no min or max ranges defined for #{$name}.";
}
} @else {
@if map-get($first-bp, RangeMin) and map-get($second-bp, RangeMax) {
@media screen and (min-width: map-get($first-bp, RangeMin)) and (max-width: map-get($second-bp, RangeMin)) { @content; }
} @else if map-get($first-bp, RangeMin) {
@media screen and (min-width: map-get($first-bp, RangeMin)) { @content; }
@warn "No max range defined for #{$name-max}. Max set to infinite.";
} @else if map-get($second-bp, RangeMax) {
@media screen and (max-width: map-get($second-bp, RangeMax)) { @content; }
@warn "No min range defined for #{$name}. Min set to infinite.";
}
}
}
/**
* Get a specific value from the breakpoint
*
* @param {string} $breakpoint The name of the breakpoint to search in
* @param {string} $property The name of the property to search for
*/
@function get-breakpoint-value($breakpoint, $property) {
@return map-get(map-get($breakpoints, $breakpoint), $property);
}
@include breakpoint("Mobile", "Desktop") {
body {
max-width: get-breakpoint-value("Desktop", "MaxWidth");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment