// ----
// Sass (v3.4.5)
// Compass (v1.0.1)
// ----
// Sass: Creating custom scope & scope-based default value in Sass
//
// A use case using mixin.
// This is pseudo code so you need implement some code.
//
// Other ideas: https://github.com/whizark/xass#ideas
// --------------------------------------------------------------------------------
// The FILO stack to keep scope & the property values
$-scope: (
// <scope-id>: (
// <name>: <value>,
// ...
// ),
// ...
);
// Setter function
@function set($name, $value) {
// 1. Get the $-scope value by current scope ID
// 2. Set the $value to the $name property in the current scope
// 3. Merge back the value(1) to $-scope
@return $value;
}
// Getter function
@function get($name, $default: null) {
$value: null;
// 1. Get the $-scope value by current scope ID
// 2. Get the value of $name property
// 3. (Returns $default value,
// if the $name doesn't exist in the current scope.
// Or follow the scope-chain.)
@return $value;
}
// The mixin to create new scope
@mixin scope() {
// 1. Create a new scope ID
// 2. Push the scope ID and empty Map into $-scope
// 3. Do something
// e.g. call constructor function by using call()
// or set default values etc.
@content;
// 4. Pop the current scope ID and Map(2) from $-scope
}
// --------------------------------------------------------------------------------
// Use case
// Component Definition
@mixin button(
$font-size : get('font-size', 16px), // THE SCOPE-BASED DEFAULT VALUES.
$color : get('color', #00f), // The current scope value is used,
$line-height: get('line-height', 1.4) // if an argument is omitted.
) {
// Computes the vertical padding based on font-size & line-height.
$padding : 16px;
$line-height-px : ($font-size * $line-height);
$line-height-space: ($line-height-px - $font-size) / 2;
$vertical-padding : $padding - $line-height-space;
// Declarations
display : inline-block;
font-size : $font-size;
padding : $vertical-padding $padding;
background : $color;
line-height: $line-height;
}
@mixin another-mixin( // This mixin only accept $color,
$color: get('color', #f0f) // but you can pull the value from the current scope.
) {
color: $color;
}
// Actual Usage
// 1. Create new scope.
@include scope() {
// SCOPE BEGIN
// THE SCOPE CAN BE NESTED.
// 2. Set Property
$font-size : set('font-size' , 13px); // The base font-size;
$color : set('color' , #f00); // The base(primary) color;
$line-height: set('line-height', 1.6); // The base line-height;
// 3. Call method(s)/mixin(s)
// You don't have to pass arguments.
.button {
@include button();
}
.another-mixin {
@include another-mixin();
}
// @include other-mixins(); with/WITHOUT arguments.
// ...
// SCOPE END
// The current scope values are popped.
}