New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dynamic variables and mixins #857
Comments
This is a duplicate of #626 |
Not a duplicate. |
Sorry, I read dynamic mixin as dynamic include of a mixin. |
I'm currently doing this : // Definitions
@mixin setComponent($placeholder) {
// Do stuff
%#{$placeholder} {
@content;
}
}
@mixin getComponent($placeholder) {
// Do stuff
@extend %#{$placeholder};
} // Example use
@include setComponent(table-cell) {
padding:4px;
margin:4px;
}
td {
@include getComponent(table-cell);
}
th {
@include getComponent(table-cell);
} // Output
td, th {
padding: 4px;
margin: 4px;
} Basicly, I'm looking for ways to achieve the following :
Both this and #336 seem essential to allow these features and other features I have in mind for the meta-framework I'm building. |
John, The abilities you asking for aren't going to happen any time soon, but as I On Sunday, July 21, 2013, John Slegers wrote:
|
Are there any technical reasons these features aren't going to be implemented? Sass has a lot of meta-programming potential, but access to global variables from mixins as well as the dynamic creation of variables and mixins are pretty essential to allow any such advanced usage of Sass. Dependence on Compass and Compass plugins is not an option for me, as I want my meta-framework to be compatible with implementations of Sass in other languages besides Ruby (like PHPSass) and have as little dependencies as possible. The lack of these very essential features and bizarre unpredictable behavior like #856 are more and more forcing me to consider writing my own pre-processor language to leverage my needs, which I'd rather not do when there's already LESS, Sass and PHP-Crush. |
@jslegers Metaprogramming is one way to accomplish what you're thinking, but there are others. We are already adding a bunch of meta programming abilities from the calling side, but the definition side seems less useful from all the use cases I've seen so far. I'd rather approach this problem from use cases and end-user APIs and capabilities. I'd like to understand why defining a mixin dynamically provides some ability that defining it statically does not and then I'd need to weigh that complexity against the understandability and learnability for new users. For instance, dynamic definitions will almost certainly require the introduction of closures and possibly anonymous functions and mixins. I think these are very advanced concepts that make the language harder to comprehend. |
But if you feel the need to write your own preprocessor, feel free. You may also want to check out Rework; it's a good foundation for writing new css preprocessors and exploring new concepts. We tend to be rather conservative in our language design philosophy. |
What I wanted to achieve, is a way to easily maintain and optimise Cascade Framework. The codebase would consist of four levels :
Major advantages :
There are several ways to implement this, but for every implementation I have in mind I'm missing one or two features in SCSS. The ability to modifiy global variables from within a mixin is the key feature I'm missing. Adding that alone would allow me to implement 95% of the meta-framework's features in a very short time. I'm currently experimenting with writing my own preprocessor language in PHP, although I still consider moving back to SCSS if one or more of the missing features are implemented. Thanks for suggesting Rework, though. It might inspire me :-) |
You keep saying that you can't modify global variables from within mixins, and you keep being incorrect about that. If you would simply try it, you'll see you can, in fact, change global variable values from within mixins. $foo: 'Hello World';
@mixin change-global-variable-foo($var: $foo) {
// If nothing is passed in, $foo remains $foo
$foo: $var;
content: $foo;
}
.bar {
@include change-global-variable-foo; // content: 'Hello World';
@include change-global-variable-foo('Goodbye World'); // content: 'Goodbye World';
@include change-global-variable-foo; // content: 'Goodbye World'; Global variable $foo has been changed
} I'm willing to bet you have your argument variables in your mixin named the same as your global variables. Assuming that is the case, you will not see the global variable change as you are within a local variable namespace. The issue you'd be having there is a misunderstanding about how scoping works. The way I deal with scoping is to have my global namespaced variables have unique names related to the mixins they are for and to have the same names w/o namespacing in the mixin. |
@Snugug Ya, I feel like I'm talking to a wall too, so I'm going to stop for now. I have more productive things to do. |
Even though I've been able to improve my syntax significantly due to various improvements in Sass 3.3, the lack of dynamic mixins remains a problem for my implementations. No matter how much I improve the architecture of the meta-framework I'm building, I keep stumbling on the lack of dynamic mixins as a blocking issue. Just today, I found two use cases for interpolated mixins that I struggle to implement without interpolated mixins. This is the first one : Input:// Polyfill for "opacity"
@mixin opacity($value) {
opacity: $value;
filter: alpha(opacity=$value * 100);
}
// Polyfill for "transform"
@mixin transform($value) {
-ms-transform: $value;
-webkit-transform: $value;
transform: $value;
}
// This mixin will use a polyfill or custom rule definition when available
@mixin rules($styles) {
@each $key, $value in $styles {
if mixin-exists($key) {
@include #{$key}($value);
} @else {
#{$key}: $value;
}
}
}
// The user can use standard CSS3 without caring about browser
// support. For browsers that don't support certain features,
// polyfills will automatically be used when available.
// Polyfills can be modified or deleted at any time without any
// impact on user defined code.
.exampleclass {
@include rules(
width : 100%,
opacity : 0.5,
transform : rotate(7deg)
);
} Output:.exampleclass {
width : 100%;
opacity : 0.5;
filter: alpha(opacity=50);
-ms-transform: rotate(7deg);
-webkit-transform: rotate(7deg);
transform: rotate(7deg);
} This is the second one : Input:// Custom "grid" property
@mixin grid-cell($values) {
@extend %clearfix;
$float : nth($values, 1);
$width : nth($values, 2);
float: $float;
width: $width;
}
// This mixin will use a polyfill or custom rule definition when available
@mixin rules($styles) {
@each $key, $value in $styles {
if mixin-exists($key) {
@include #{$key}($value);
} @else {
#{$key}: $value;
}
}
}
.exampleclass1 {
@include rules(
grid-cell : left 30%,
color : #000
);
}
.exampleclass2 {
@include rules(
grid-cell : right 40%,
color : #fff
);
} Output:.exampleclass1, .exampleclass2 {
display: block;
}
.exampleclass1:before, .exampleclass1:after,
.exampleclass2:before, .exampleclass2:after {
content: "";
display: table;
}
.exampleclass1:after, .exampleclass2:after {
clear: both;
}
.exampleclass1 {
float: left;
width: 30%;
color : #000;
}
.exampleclass2 {
float: right;
width: 40%;
color : #fff;
} See also #626 . |
I too keep hitting this same stumbling block. I know everything is now frozen until LibSass catches up, but this would be a really powerful addition. |
I think I ran into this as well. I'm customizing the Bootstrap grid mixins, and wanted to print out the classes for prototyping: $grid-columns: 12;
$sizes: ( xs, sm, md, lg );
$actions: ( push, pull, offset );
@for $i from 1 to $grid-columns {
@each $size in $sizes {
.col-#{$size}-#{$i} { @include make-#{$size}-column($i); }
@each $action in $actions {
.col-#{$size}-#{$i}-#{$action} {
@include make-#{$size}-column-#{$action}($i);
}
} // each $actions
}
} |
I may be a little late, but just ran into another case of the same issue: // Translate susy columns to content columns.
@for $i from 1 through 24
$translate: 24 / $i // Needs parse logic.
=columns($i) // Or (#{$i}), not sure since none of this will work.
+span($translate) I began with this, and wanted to create a dinamic mixin to add the gridsystem's columns in a content-oriented way, so I would say "this box will have as many susy columns as it takes to make a 3 columns diagram". .foo
+container()
.bar
+columns(3) // This would apply the span(8) susy mixin, in my case. I stopped here because it does not work, but I wanted to improve it to use inside media queries with just one declaration, so you see why classes and placeholders will not work for me. |
I have now run into needing this, any updates in the last 3 years? |
I think modifying SASS syntax is not appropriate solution for these kind of things...now I'm using jinja template engine to generate SASS codes and it works so so fine. If SASS needs meta-programming abilities, implementing a good macro language on top of current syntax is the way to go! |
Dynamic extends work fine. The following works as expected :
Dynamic mixins and variables don't seem to work, though. The following all give an error :
Dynamic extends, mixins and variables increase the meta-programming capabilities of the language significantly. For that reason, I'm most definitely looking forward to the addition of dynamic mixins and/or variables to use them in the meta-framework I'm building.
Are these features planned for a future release? If not, is there a technical reason for that? Or is there maybe a technique you can recommend to achieve the same effect?
The text was updated successfully, but these errors were encountered: