sass mixins and css custom properties - css

aye folks!
i tried to build a sass mixin for css custom properties to make work a little bit easier.
my attempt does look like this:
#mixin mixin($value) {
background: unquote('$')#{$value};
background: var(--#{$value}, unquote('$')#{$value});
}
the output looks like this:
.example {
background: $value;
background: var(--colour, $value);
}
BUT sass doesn't convert my $value into the actual thing. the $value part end up in my final css file and ofc this doesn't work.
i tried to find a solution online but i'm either to dumb to find it or there isn't one. anyone here has an idea what i'm doing wrong?

I have try your code with this example:
#mixin mixin($value) {
background: unquote('$')#{$value};
background: var(--#{$value}, unquote('$')#{$value});
}
.example {
#include mixin(colour)
}
and it works.
The output is:
.example {
background: $colour;
background: var(--colour, $colour);
}
is what you want? Sorry but I don't have the authorization for add comment so I create this answer.
Edit: you can create a different mixin like this:
#mixin mixin($value, $color) {
background: $color;
background: var(--#{$value}, $color);
}
This help you to solve your problem?

Related

Foundation customizing scss classes

I am trying to customize scss of foundation to have a two different classes for topbar. I have limited knowledge of scss therefore changing _settings.scss was very easy first step, which has the problem that it changes global style. I would like to do something like following without messing up global styles.
.my-topbar-first {
$topbar-bg-color: $red;
#extend .top-bar;
}
.my-topbar-second {
$topbar-bg-color: $green;
#extend .top-bar;
}
Whats the elegant way to achieve this?
when you are using $topbar-bg-color: $red; it set the $topbar-bg-color variable to what you have in $red variable.when you are using it again, it messed up the last setting.
so instead,
you have to do like this :
.my-topbar-first {
background-color: $red;
#extend .top-bar;
}
.my-topbar-second {
background-color: $green;
#extend .top-bar;
}
First of all you are duplicating code when extending .top-bar in both class names . A more DRY approach would be like this :
.my-topbar-first,
.my-topbar-second {
#extend .top-bar;
}
.my-topbar-first {
background-color: $red;
}
.my-topbar-second {
background-color: $green;
}
When using #extend or #include they should always be on the first line were you declare your properties , example:
my-topbar-second {
#extend .top-bar;
background-color: $green;
color: $white;
font-size: $top-bar-fontsize;
}
If you have more instances of .top-bar-foo you can actually write a for loop, example :
$class-slug: top-bar;
#for $i from 1 through 2 {
.#{$class-slug}-#{$i} {
background-color: $color-#{$i};
}
}
You get :
.top-bar-1 {
background-color: $color-1;
}
.top-bar-2 {
background-color: $color-2;
}
Hope this helped . If you want to learn more about Scss go on Hugo Giraudel's blog http://hugogiraudel.com/ and learn from the best .

Produce whitespace-free CSS string with SASS #while loop

I'm attempting to write a mixin that repeats a string as part of a selector. My desired output is very whitespace sensitive, but I can't find a way of making SASS compile without introducing said whitespace.
The desired output would be:
body:nth-child(n):nth-child(n){
background: blue;
}
body:nth-child(n){
background: green;
}
body {
background: red;
}
And I would like to achieve it using this invocation:
body {
#include increase-specificity( 2 ){
background: blue;
}
#include increase-specificity{
background: green;
}
background: red;
}
The problem is that the :nth-child(n) string can't accept any whitespace after the current selector (&), or between repetitions, without changing the functional CSS afterwards – and I can't find a way of writing a mixin that fulfils this without causing SASS errors.
This is how I've tried to express the mixin:
#mixin increase-specificity( $depth: 1 ){
&#while($depth > 0){#{'nth-child(n)'}$depth: $depth-1}{
#content;
}
}
And here's a Codepen to show it breaking.
My problems so far are:
SASS won't tolerate the #while loop immediately following & (&#while{…), but I can't think of any other way to avoid whitespace between the compiled strings.
Similarly, I can't find a way of writing a functonal #while loop without being liberal with whitespace: the current syntax falls over when it reaches the end of the the interpolator (#{…}) (don't know why), but removing interpolation causes it to trip up trying to interpret nth-child's parens.
There's so much going on wrong in your code (bad logic, missing whitespace, mismatched brackets, etc.), it's not worth the effort to try and explain why it doesn't work.
#mixin increase-specificity( $depth: 1 ) {
$sel: '';
#while($depth > 0) {
$sel: $sel + ':nth-child(n)';
$depth: $depth - 1;
}
&#{$sel} {
#content;
}
}
body {
#include increase-specificity( 2 ){
background: blue;
}
#include increase-specificity{
background: green;
}
background: red;
}

Less inherit "virtual" class

I am using SASS and there is nice feature: I can create "fake/virtual" class and then use it for extend.
Example:
%myFakeClass
{
color:#fff;
background-color:#000;
}
.myRealClass
{
#extend %myFakeClass;
}
.myRealClass2
{
#extend %myFakeClass;
}
Output:
.myRealClass, .myRealClass2
{
color:#fff;
background-color:#000;
}
The question:
Does LESS has something similar? In other words, I want to create a "virtual class" that I can inherit from, but the "virtual class" itself not exists in output.
Not Directly as of Yet
As of this date (11-22-2013) there is still a feature request that would allow this by doing extending on empty parameter mixins (which do not output css themselves). So eventually something like this would be possible (which mirrors almost exactly what you want):
.myFakeClass() {
color:#fff;
background-color:#000;
}
.myRealClass {
&:extend(.myFakeClass);
}
.myRealClass2 {
&:extend(.myFakeClass);
}
And output as you expect.
Workaround for now
This was mentioned by Bass Jobsen, but not explicitly demonstrated. In LESS 1.5, you build a file for your fake classes, say fakeClasses.less, which for our example has this in it:
.myFakeClass {
color:#fff;
background-color:#000;
}
Then in your file that you want to extend to it, let's say styles.less, you do this:
#import (reference) fakeClasses.less;
.myRealClass {
&:extend(.myFakeClass);
}
.myRealClass2 {
&:extend(.myFakeClass);
}
This will import the fakeClasses.less classes but NOT compile them to css (so they are "fake" within the context of styles.less, but "real" in that they can be extended to), and you will get the output you expect.
.myRealClass, .myRealClass2 {
color:#fff;
background-color:#000;
}
Maybe the following helps you img { &:extend(.img-responsive); } from Why gives Grunt / Recess an error and Lessc not when compiling Bootstrap 3 RC1?
update from How do I create a mixin using less.js that doesn't output in the final stylesheet:
.myFakeClass()
{
color:#fff;
background-color:#000;
}
.myRealClass, .myRealClass2
{
.myFakeClass();
}
since LESS 1.5 you could also place you virtual classes in a separate file and use:
#import (reference) "file.less";
We have another import option - reference. This means that any
variables or mixins or selectors will be imported, but never output.
I'm not entirely sure if #extend works the same as a "mixin", but it looks the same.
.myFakeClass(#textColor: #fff, #bgColor: #000 )
{
color:#textColor;
background-color:#bgColor;
}
.myRealClass
{
.myFakeClass();
}
.myRealClass2
{
.myFakeClass();
}
The out put for this would be the same as what you have above. I added variables in the mixin for easier customization for this mixin.
Example:
.myRealClass3
{
.myFakeClass(#369, #00f);
}
The output for all three classes would be:
.myRealClass, .myRealClass2
{
color:#fff;
background-color:#000;
}
.myRealClass3
{
color:#369;
background-color:#00f;
}
Like I said, I'm not entirely sure if there is a big difference between extending a class in SASS and using a mixin in LESS. Hope this helps either way.
Oh, and just to clarify, if the .myFakeClass() class is in a separate .less file that is imported, it will not show up in your CSS unless it is used. I tested this on a website I'm building. I have:
.box-shadow(#a, #b, etc..) {
box-shadow: #a #b etc..;
-webkit-box-shadow: #a #b etc..;
etc: #a...;
}
The class .box-shadow does not show up in my CSS at all.
Link: http://lucienconsulting.com/gs-news/wp-content/themes/TheStone/css/style.css
However, if you write a mixin like this:
.myMixin{
background: #000;
color: #fff;
}
It will show up like a normal class even if not used. Obviously, it looks just like a normal class and could be used by itself, or as a mixin, like so:
.myClass{
.myMixin;
border: 1px solid #fff;
}
This would compile to:
.myClass{
background: #000;
color: #fff;
border: 1px solid #fff;
}
It works, but .myMixin would also show up in your style sheet in this case.
But, like I said, in my original example, it would not.

Grouping SCSS (Sass) Mixins

converting some CSS to Sass, for example:
.ptn,
.pvn,
.pan{padding-top:0px !important}
to this
#mixin ptn {padding-top:0px !important}
#mixin pvn {padding-top:0px !important}
#mixin pan {padding-top:0px !important}
but wishing i could do something more like this
#mixin ptn,
#mixin pvn,
#mixin pan {padding-top:0px !important}
is something along these lines possible?
thanks!
How about
#mixin nopadding{ padding-top:0px !important }
.ptn,
.pvn,
.pan{ #include nopadding }
?
Sass is about Reusability, so try to keep the code DRY by breaking this up into a new mixin.
Additionally you could write something like this:
#mixin nopadding{ padding-top:0px !important }
#mixin anothermixin{ #include nopadding; ... }
normalselector{ #include anothermixin; }
Alternatively you can use the #extend feature to be a little cleaner, depending on your purposes.
So if you have:
.ptn { padding-top:0px !important; }
You can do this anywhere else in your code (it doesn't require it to go after for scoping purposes, like mixins do):
.pvn { #extend .ptn; /* pvn-specific rules can still go here */ }
.pan { #extend .ptn; /* pan-specific rules can still go here */}
This will output as such:
.ptn, .pvn, .pan { padding-top:0px !important; }
.pvn { /* pvn-specific rules can still go here */ }
.pan { /* pan-specific rules can still go here */ }
This can be a cleaner output than using mixins, which would duplicate the code. This is particularly useful for larger blocks of code, like clear fixes. But mixins do have their place.
Speaking of things having their place… is that !important really necessary? ;-)

One-liner is SASS

In CSS I can do something like this:
.apple { background-image: url('apple.png'); }
.orange { background-image: url('orange.png'); }
.pear { background-image: url('pear.png'); }
but it seems in sass (not scss) the same would take up 6 lines? Is it possible to do a one-liner is sass for rules that only have one property?
This isn't by any means meant to help you condense this code to one line, but to think of it from a different perspective.
In this post on The Sass Way titled "Sass control directives: #if, #for, #each and #while", I cover control directives in Sass. Here's a way to write your code using the #each directive.
$fruit-list: apple orange pear
=fruit
#each $fruit in $fruit-list
&.#{$fruit}
background-image: url(#{$fruit}.png)
.fruit
+fruit
Which outputs:
.fruit.apple {
background-image: url(apple.png);
}
.fruit.orange {
background-image: url(orange.png);
}
.fruit.pear {
background-image: url(pear.png);
}
Using .scss we can make this a one liner, but at the cost of readability of the code:
$fruit-list: apple orange pear;
#mixin fruit { #each $fruit in $fruit-list { &.#{$fruit} { background-image: url(#{$fruit}.png); } } }
.fruit { #include fruit; }
Sass syntax is principally based on indentation and line breaks, so in Sass that would indeed be six lines (two per rule, excluding blank lines):
.apple
background-image: url('apple.png')
.orange
background-image: url('orange.png')
.pear
background-image: url('pear.png')
As far as I've seen you can't condense those to one-liners in Sass.

Resources