Skip to content

Instantly share code, notes, and snippets.

@jslegers
Last active March 22, 2022 12:40
Show Gist options
  • Save jslegers/9805919 to your computer and use it in GitHub Desktop.
Save jslegers/9805919 to your computer and use it in GitHub Desktop.
// This code will only work if you use Sass 3.3 (or higher)
// Configuration :
// -----------------------------------------
$screensizes : (
'default' : 0 infinity,
'mobile' : 0 767px,
'phone' : 0 480px,
'tablet' : 481px 767px,
'desktop' : 768px 979px,
'widescreen' : 1200px infinity
);
$default-media-query : 'default';
// Adding some missing string functions :
// -----------------------------------------
@function str-replace($string, $old, $new : '') {
@if type-of($string) != string {
$string : '' + $string;
}
$index: str-index($string, $old);
$str-length : str-length($old);
@while $index and $index > 0 {
$temp : $string;
$string : $new;
@if $index > 1 {
$string : str-slice($temp, 1, $index - 1) + $string;
}
@if $index + $str-length < str-length($temp) + 1 {
$string : $string + str-slice($temp, $index + $str-length);
}
$index: str-index($string, $old);
}
@return $string;
}
@function str-clean($string, $dreplacements: (
'%' : '-perc-',
'(' : '-l-b-',
')' : '-r-r-',
'/' : '-ps-',
'"' : '-dq-',
"'" : '-sq-',
'.' : '-dot-',
' ' : '-nbsp-'
)) {
@each $old, $new in $dreplacements {
$string : str-replace($string, $old, $new);
}
@return $string;
}
// The 'magic' :
// -----------------------------------------
$dynamic-placeholders: ();
$current-media-query : $default-media-query;
@mixin generate-root-placeholder($placeholder, $styles) {
@at-root %#{$placeholder} {
@each $rule, $style in $styles {
#{$rule}: $style;
}
}
$dynamic-placeholders: append($dynamic-placeholders, $placeholder) !global;
}
@mixin extend-root-placeholder($placeholder) {
@extend %#{$placeholder} !optional;
}
@mixin rules($styles) {
@each $rule, $style in $styles {
$value : str-clean($style);
$placeholder : #{$current-media-query}-cascade-#{$rule}-#{$value};
@if not index($dynamic-placeholders, $placeholder) {
@include generate-root-placeholder($placeholder, ($rule : $style));
}
@include extend-root-placeholder($placeholder);
}
}
@mixin ruleset($styles) {
$placeholder : #{$current-media-query}-cascade;
@each $rule, $style in $styles {
$value : str-clean($style);
$placeholder : #{$placeholder}-#{$rule}-#{$value};
}
@if not index($dynamic-placeholders, $placeholder) {
@include generate-root-placeholder($placeholder, $styles);
}
@include extend-root-placeholder($placeholder);
}
@mixin respond-to($media) {
$range : map-get($screensizes, $media);
@if $range == null {
@warn 'Unknown screensize "#{$media}" for @mixin respond-to';
} @else {
$current-media-query : $media !global;
$min-width : nth($range, 1);
$max-width : nth($range, 2);
@if $min-width > 0 {
@if $max-width != infinity {
@media only screen and (min-width: $min-width) and (max-width: $max-width) { @content; }
} @else {
@media only screen and (min-width: $min-width) { @content; }
}
} @else {
@if $max-width != infinity {
@media only screen and (max-width: $max-width) { @content; }
} @else {
@content;
}
}
$current-media-query : $default-media-query !global;
}
}
//------------------------------------------------
// Examples :
// -----------------
// Basic examples without a media query
.s1 {
@include rules((
float : right,
width : 30%,
background : #fff,
));
}
.s2 {
@include rules((
float : right,
width : 100%,
background : #000,
));
}
.s3 {
@include rules((
float : left,
width : 30%,
background : #fff,
));
}
.s4 {
@include rules((
float : left,
width : 40%,
background : 'url(image/cool-background.jpg)',
));
}
// Here are some examples with media queries
// Note that "respond-to(default)" actually has the
// same impact as not using "respond-to" at all.
// It is actually purely optional.
// I added this feature for the sake of
// readability only.
.s5 {
@include respond-to(default) {
@include ruleset((
float : right,
width: 100%
));
@include rules((
background : 'url(image/cool-background.jpg)'
));
}
@include respond-to(mobile) {
@include rules((
width : 40%
));
}
}
.s6 {
@include respond-to(default) {
@include rules((
width: 100%
));
}
@include respond-to(mobile) {
@include ruleset((
float: right,
width: 300px
));
}
@include respond-to(desktop) {
@include rules((
width: 125px
));
}
@include respond-to(widescreen) {
@include rules((
float: none
));
}
}
.s7 {
@include respond-to(default) {
@include rules((
float: left,
width: 100%
));
}
@include respond-to(desktop) {
@include rules((
width: 125px
));
}
@include respond-to(phone) {
@include ruleset((
width: 400px
));
}
@include respond-to(widescreen) {
@include rules((
float: none
));
}
}
@jslegers
Copy link
Author

The output

.s1, .s2 {
  float: right;
}
.s1, .s3 {
  width: 30%;
}
.s1, .s3 {
  background: white;
}

.s2, .s6, .s7 {
  width: 100%;
}
.s2 {
  background: black;
}

.s3, .s4, .s7 {
  float: left;
}

.s4 {
  width: 40%;
}
.s4, .s5 {
  background: "url(image/cool-background.jpg)";
}

.s5 {
  float: right;
  width: 100%;
}
@media only screen and (max-width: 767px) {
  .s5 {
    width: 40%;
  }
}

@media only screen and (max-width: 767px) {
  .s6 {
    float: right;
    width: 300px;
  }
}
@media only screen and (min-width: 768px) and (max-width: 979px) {
  .s6, .s7 {
    width: 125px;
  }
}
@media only screen and (min-width: 1200px) {
  .s6, .s7 {
    float: none;
  }
}

@media only screen and (max-width: 480px) {
  .s7 {
    width: 400px;
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment