SASS - change value of variable to use it in two classes - css

I have been trying to create a variable called like "$active" and then, it depends of the class where we are, it's changing this value. But it doesn't work. Show you the code
$active : #000 !default;
.class-1 {
$active : red;
}
.class-2 {
$active : green;
}
.class-1, .class-2 {
color: $active;
}
So, in this way, what I though is changing the value depending of the class we are, then, apply this color for the class. The thing is, I have a lot of code under those two classes, I can not assign the color without the comma, otherwise I will repeat to much code.
Also, I discovered something really weird and it can be the key why is not working, in the code, if i write like this:
$active : #000 !default;
.class-1 {
$active : red;
color : $active; // Here it's working, red!
}
.class-2 {
$active : green;
color : $active; // Here it's working, green!
}
.class-1, .class-2 {
color: $active; // No way to make it works! :(
}
Do you have any idea? Any suggestion is welcome, Thanks!
Btw, I already tried with Mixins and functions, but it's the same...
--- EDIT ---
I think I wasn't clear enough, sorry. I just created a pen for this example, with comments and everything to try to be clearer. From my point of view, it happen that I am overriding the variable value not in the global context, but not sure if it's like that...
http://codepen.io/ialex90/pen/RaEyWx

I forked your pen and made a couple of small adjustments.
My approach here is this:
Don't reset $activeColor to a new color, it's just not necessary. What you do instead of set $user and $admin directly, skipping the setting on $activeColor. When you set the background color to the div, set the color as well.
.panel-user {
background-color : darken( $user, 20% );
color: $user;
}
.panel-admin {
background-color : darken( $admin, 20% );
color: $admin;
}
Then in your pen where you are setting colors, change them to inherit. So your saying, "Admin background is a darker shade of lightBlue, and the color is lightBlue. Now text stuff inside of .panel, inherit your color from the parent."
.panel {
a {
color : inherit;
}
}
This should illustrate what I mean, http://codepen.io/maxinacube/pen/bpOXyX?editors=0100
Also, it's best not to get too specific on your selectors. After setting the color on the parent item, the span and .good-bye actually inherit the color by default. So all you really need to force inheriting the style is the a. Of course, this may change depending on what other styles creep up as you develop but it's best to keep things simple so you're not making diesel selectors or using !important to overwrite things in the future.

You could use array of colors, and set individual color while looping this array:
$colors: red, blue, orange;
#for $i from 1 through length($colors) {
.color-#{$i} {
color: nth($colors, $i)
}
}
.color-1, .color-2 {
color: #000;
}
It will compiles in:
.color-1 {
color: red;
}
.color-2 {
color: blue;
}
.color-3 {
color: orange;
}
.color-1, .color-2 {
color: #000;
}

Related

CSS of nested selector is not being applied to div

I utilised the BEM method and my <div> is showing the css from the Block and Modifier, but not the Element
i.e. the css for c-banner(block) and --warning(modifier) is appearing but not __icon(element).
I know that the color of the modifier is appearing because I tried changing it to another color and it appears on the UI.
Eg:
Currently:
&--warning {
color: #D9822B
}
Edited:
&--warning {
color: black
}
Once changed, the icon of --warning will show up with a black color on the UI.
However, the padding-right of __icon doesn't ever get applied.
c-banner {
/* Block CSS Properties */
&__icon {
padding-right: 12px;
&--warning { /* Used for warning purposes */
color: #D9822B;
}
&--primary { /* Used for general information */
color: #137CBD;
}
&--success { /* Used for verified access */
color: #0F9960;
}
&--danger { /* Used as a hard stop */
color: #DB3737;
}
}
}
I'm genuinely perplexed as to why the padding-right of __icon does not get applied but the color of --warning is
All you are missing is:
.c-banner ..... the dot before the classname
Also, for padding to work they have to be inside --warning because you are chaining to form the full selector and there is no selector that ends with __icon
You can style material-icons if you want to affect multiple:
.c-banner {
.material-icons { padding-right: 12px; }
/* can also do [class*="__icon"] but may be less predictable */
&__icon {
/* rest of the scss */
}
}

Themed variables in LESS/SASS

I'm looking to support multiple themes in my app - moreover, I want to be able to dynamically change themes, either by changing a class on the body element, or even have different parts of the app use different themes.
In my previous project, I did it by adding explicit rules every time I need to use a theme-specific variable:
.theme-light & { background-color: #theme-light-background; }
.theme-dark & { background-color: #theme-dark-background; }
However, that approach does not scale well and adds unnecessary bloat to source files.
Now, I'm looking for a more automated approach for this. I.e. the following
.button {
border-radius: 4px;
background-color: #ui-background;
color: #ui-foreground;
border: 1px solid mix(#ui-background, #ui-foreground, 50%);
}
would turn into something like
.button {
border-radius: 4px;
border: 1px solid #808080;
/* normally we wouldn't expect this to appear here, but in our case
both themes have the same border color so we can't tell the difference */
}
.theme-light .button {
background-color: #fff;
color: #000;
}
.theme-dark .button {
background-color: #000;
color: #fff;
}
As far as I can tell, neither LESS nor SASS can do this in a natural way. It seems that it wouldn't be too difficult to implement it as a separate post-processor, that builds stylesheets for every theme, then compares them and scopes the differences into the corresponding "namespaces". I suspect that something like this might already exist, but I can't find anything.
Any suggestions?
Not sure about Less, but in Sass it can be implemented relatively easy by storing theme information into maps and using ability to pass content blocks into mixins using #content. Here is example of how it may look like, quite fast solution but you can get an idea:
// Themes definition
// - First level keys are theme names (also used to construct theme class names)
// - Second level keys are theme settings, can be referred as theme(key)
$themes: (
light: (
background: #fff,
foreground: #000,
),
dark: (
background: #000,
foreground: #fff,
),
);
// Internal variable, just ignore
$_current-theme: null;
// Function to refer to theme setting by name
//
// #param string $name Name of the theme setting to use
// #return mixed
#function theme($name) {
#if ($_current-theme == null) {
#error "theme() function should only be used into code that is wrapped by 'theme' mixin";
}
#if (not map-has-key(map-get($themes, $_current-theme), $name)) {
#warn "Unknown theme key '#{$name}' for theme '#{$_current-theme}'";
#return null;
}
#return map-get(map-get($themes, $_current-theme), $name);
}
// Theming application mixin, themable piece of style should be wrapped by call to this mixin
#mixin theme() {
#each $theme in map-keys($themes) {
$_current-theme: $theme !global;
.theme-#{$theme} & {
#content;
}
}
$_current-theme: null !global;
}
.button {
border-radius: 4px;
#include theme() {
background-color: theme(background);
color: theme(foreground);
}
}
This piece of code will give you this result:
.button {
border-radius: 4px;
}
.theme-light .button {
background-color: #fff;
color: #000;
}
.theme-dark .button {
background-color: #000;
color: #fff;
}
Looks pretty close to what you're trying to achieve. You can play with this snippet at Sassmeister.

CSS and .less: Set a font color if user pick a specific color through web interface

I have a web Interface where user can choose a color for a h1 element.
I store this choice in a variable calling #color1
For a specific color ( #333 ) contrast with background are no good so a would to force a specific color to #fff if user pick #333.
How can I perform it in less ?
I tried this, but it doesn't work:
h1 (#color1:#fff) when (#color1=#333) {
color:#color1;
}
LESS doesn’t handle if / else statements. Instead, it provides guarded mixins (mixin when a parameter exists or equals / is inferior / is superior to something).
In Less you can use a guard mixin like:
#body:#333;
h1 {
color: yellow;
}
h1 when (#body = #000) {
color: blue;
}
h1 when (#body = #333) {
color: red;
}
DEMO
http://codepen.io/alexincarnati/pen/mJihw

How do I have an attribute reference itself in LESS?

I would like to have a property reference its "self", I am not sure how to do this in LESS. Heck I am having a hard time crafting the wording of the question. Basically I would like to accomplish the following:
a:visited {
color: lighten(color, 10%);
}
Where a's color could vary based on its container div.
So I might have the following selectors:
div#blue-text a {
color: #00F;
}
div#black-text a {
color: #000;
}
Once I visit the links, I should have a lighter blue and gray link texts respectively.
Note: this is a very simple scenario, but I have much more complicated needs, and if there is a clean way to do this, then I would be a happy camper.
Basically, since you're going to set the parent's color in LESS as well, you would store the color in a variable and reference it.
Here is an example:
#column1Color: #aaaaaa;
#column2Color: #bbbbbb;
#column3Color: #cccccc;
.columns {
// set the color of the first column
.column:nth-child(1) {
background-color: #column1Color;
a {
color: lighten(#column1Color, 10%);
}
}
// set the color of the second column
.column:nth-child(2) {
background-color: #column2Color;
a {
color: lighten(#column2Color, 10%);
}
}
// set the color of the third column
.column:nth-child(3) {
background-color: #column3Color;
a {
color: lighten(#column3Color, 10%);
}
}
}
LESS would not know what the color of the hyperlink is unless you "told" it. Same goes for the browser, it would not know the color unless it executes all the linked CSS files.
So, what you need (if I understood you correctly) can not be achieved the way you're thinking about it.

SASS checking against a class name

Hi I'm still very new to SASS and no programming guru.
I have ten asides elements that all require different background colours based on their class name.
I've looked through the SASS documentation and I can't figure it out.
I want to say if aside has a class name of x make background colour x if aside has a class name of y make background colour y etc
Is there a nice efficient way of doing this?
Thanks guys and sorry if its a simpleton question.
If you're using colors that don't have "standard" names (or the name of the class isn't going to be the name a color at all, eg. products = blue, addresses = red), a list of lists is what you want:
$colors:
( black #000
, white #FFF
, red #F00
, green #0F0
, blue #00F
);
#each $i in $colors {
aside.#{nth($i, 1)} {
background: nth($i, 2);
}
}
Output:
aside.black {
background: black; }
aside.white {
background: white; }
aside.red {
background: red; }
aside.green {
background: lime; }
aside.blue {
background: blue; }
If you're using colors with standard keywords, this could work:
$colors2: black, white, red, green, blue;
#each $i in $colors2 {
aside.#{$i} { background: $i; }
}
Output (though this only seems to work with --style debug, using --style compress generates errors.. weird):
aside.black {
background: black; }
aside.white {
background: white; }
aside.red {
background: red; }
aside.green {
background: green; }
aside.blue {
background: blue; }
This is simply down to how much typing you want to do. You could make a background mixin and include it within the aside CSS rule, but is that really necessary?
If it is though....
#mixin bg($color) {
background: $color;
}
aside#foo {
#include bg(#fff);
}
"if aside has a class name of x make background colour x if aside has a class name of y make background colour y" translates to the following CSS:
aside.x {background-color: x}
aside.y {background-color: y}
Is there a reason you want to use SASS? Is it to make it dynamic so that you can add any class you want in the future without updating the CSS? (If so that's not possible with SASS because the SASS code compiles to CSS and doesn't change after).
To make that work you'd have to use JS (jQuery):
$('aside').each(function () {
$(this).css('background-color', $(this).attr('class'));
});
Edit: You could use loops in SASS to generate a large number of classes and corresponding background-colors though.

Resources