Skip to content

Instantly share code, notes, and snippets.

@morewry
Last active October 1, 2015 21:07
Show Gist options
  • Save morewry/9522924 to your computer and use it in GitHub Desktop.
Save morewry/9522924 to your computer and use it in GitHub Desktop.
Sass @include or @extend with generated selectors & override-able rules
// ---------------------------------------
/*
http://codepen.io/morewry/pen/meBtj
Use case for defaults:
providing interface points to override framework defaults with more flexibility and granularity than variables can reasonably provide, ie customize normalizations without editing the stylesheet directly (@content in reverse)
Use case for swapping extend or include:
Optimize generated css, debug source order problems
This provides a workaround to lack of dynamic mixin names and includes to some degree.
*/
$gr-default-method: extend !default;
$gr-default-merge: false !default;
$gr-default-debug: false !default;
// ---------------------------------------
@mixin map-as-css ($map) {
@each $p, $v in $map {
#{$p}: #{$v};
} // each
} // @mixin map-as-css
// ---------------------------------------
@function set-rules ( $name, $rules, $merge ) {
$nooverrides: (not $rules or (type-of($rules) != map) or length($rules) < 1);
$nodefaults: (not variable-exists(default-rules) or (type-of($default-rules) != map) or length(map-get($default-rules, $name)) < 1);
// Get rules to generate
@if $nodefaults and $nooverrides {
@warn "@mixin get-rules didn't find any rules for #{$name}";
}
@if not $nodefaults and $nooverrides {
$rules: map-get($default-rules, $name);
}
@if $merge and not $nooverrides {
$rules: map-merge(map-get($default-rules, $name), $rules);
} // merge overrides
@if not $nooverrides {
$default-rules: map-merge($default-rules, ($name: $rules)) !global;
}
@return $rules;
} // @function set-rules
// ---------------------------------------
@mixin get-rules ( $name, $method: $gr-default-method, $rules: false, $merge: $gr-default-merge, $debug: $gr-default-debug ) {
$rules: set-rules($name, $rules, $merge);
// init rules and placeholder
@if $method == init {
@if length($rules) {
%#{$name} {
@include map-as-css($rules);
} // placeholder
@if $debug {
.#{$name} {
@extend %#{$name};
} // class
} // debug
} // use overrides
} // init
// @extend or @include rules
@else {
@if $method == extend {
@extend %#{$name} !optional;
} // extend
@else {
@include map-as-css($rules);
} // include
} // use
} // @mixin get-rules
// ---------------------------------------
$default-rules: (
test: (
margin: 1em,
padding: 0.25em,
color: #fff,
background-color: #f00,
font-weight: bold
), // test
another: (
border-radius: 25%
) // another
); // $default-rules
/*
Usage:
// ---------------------------------------
$newprops: (
color: #0f0,
background-color: #00f
);
// ---------------------------------------
// init (required for @extend, but not for @include)
@include get-rules($name: "test", $method: init, $rules: $newprops, $merge: true, $debug: true);
// ---------------------------------------
// test @extend
.test-extend { @include get-rules("test", extend); }
// test @include
.test-include { @include get-rules("test", include); }
// test vanilla @extend
.test-vanilla-extend { @extend %test !optional; }
// ---------------------------------------
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment