I have a problem with scsslint in this variable
ColorVariable: Color literals like blue should only be used in
variable declarations; they should be referred to via variable
everywhere else.
I have this sass palette:
$color-palettes: (
blue: (
light : lighten($grey, 6%),
base : $grey,
),
);
//using sass palettes
p {
color: palette(blue);
}
//wrong way
p {
color:blue;
}
// right way by scsslint I totally agree
// creating the variable
$blue:#0055FF;
p {
color:$blue;
}
the problem is I am passing the value palette(blue); and this make scsslint complain about blue.
I know I can change the scss-lint.yml to false ans solve that
ColorVariable:
enabled: false
but the problem I want avoid bad practices like:
p {
color:blue;
}
p {
color:white;
}
so in that case what the best I should do? to Keep Using the validation in my file jumping some classes that ColorVariable?
Thanks.
Related
I want to export "$var" like variables defined as "--var" variables from a Scss file to be used in other files with some scss functions such as "darken()", but it says its not a color.
I'm coding a Vue/Vite website and implementing a theme-change button, that will write data at the HTML tag, and use it to define the theme.
<html lang="en" data-theme="dark"> ... </html>
The base.scss looks like this:
[data-theme="dark"] {
--primary: #c6c7df;
--secondary: #c95d63;
--text-light: #e2ebf5;
}
[data-theme="light"] {
--primary: #26298d;
--secondary: #c95d63;
--text-light: #2c3e50;
}
$primary: var(--primary);
$secondary: var(--secondary);
$text-light: var(--text-light);
I can use the "$var"-like variable at the end of the file, but when I use it inside a "darken($primary, 10%)" function, it gives the following error:
Error: $color: var(--primary) is not a color.
I know it's because I defined it as a CSS variable but if I define the variable inside the "[theme] {}" thing, it doesn't get innitialized and throws the error "Undefined variable"
I know it's a niche question, and I could use something like this, but I wish I could just export it as a scss variable.
Thank you very much.
Of course we cannot make a CSS variable lighten or darken. Think about, What will happen to the Name of CSS variable in the output?
So we have to define all CSS variables and assign desired colors, Before using them.
Solution
For this purpose, you can automatically create the list of CSS variables by #each and create a manual function by #function for easy use. This way gives us a standard css output and the best experience in Sass coding.
// Theme defines area:
$theme-colors:(
"primary": #940fe0,
"secondary": #e49f38,
"warning": #ffe600,
"info": #165ad6
);
$darken-percent: 20%;
$lighten-percent: 20%;
// Functions area:
:root {
#each $name, $color in $theme-colors {
$lighten: lighten($color, $lighten-percent);
$darken: darken($color, $darken-percent);
--color-#{$name}: #{$color};
--color-#{$name}-light: #{$lighten};
--color-#{$name}-dark: #{$darken};
}
}
#function cl($name, $color-tone) {
#if not map-get($theme-colors, $name+''){
#error "`#{$name}` is not defined in Colors Theme";
}
#if $color-tone == d {
#return var(--color-#{$name}-dark);
}
#if $color-tone == l {
#return var(--color-#{$name}-light);
}
#else{
#return var(--color-#{$name});
}
}
// Our custom function usage:
// Use 'b' to return Base color. Ex: cl(primary,b)
// Use 'l' to return Lighten color. Ex: cl(primary,l)
// Use 'd' to return Darken color. Ex: cl(primary,d)
.test {
color: cl(primary,b);
color: cl(warning,l);
}
Compiled css result:
:root {
--color-primary: #940fe0;
--color-primary-light: #bf61f4;
--color-primary-dark: #550980;
--color-secondary: #e49f38;
--color-secondary-light: #f0ca92;
--color-secondary-dark: #a06916;
--color-warning: #ffe600;
--color-warning-light: #fff066;
--color-warning-dark: #998a00;
--color-info: #165ad6;
--color-info-light: #6395ef;
--color-info-dark: #0c337a;
}
.test {
color: var(--color-primary);
color: var(--color-warning-light);
Currently, I've a list of colors (for example):
#colors: {
base: #716aca;
brand: #716aca;
danger: #c14549;
warning: #ffb822;
success: #34bfa3;
primary: #5867dd;
black: #000000;
}
I have each function that iterates over all the colors and makes all the possible rule colors that we can use:
each(#colors, .(#value, #key, #index) {
.rules-here-#{key} {
attribute: #value;
}
}
What I can't make work is something like this:
.getColor(#color);
Where I would use on other places, like:
div.system-warning-notification {
background-color: .getColor('base');
color: .getColor('danger');
}
I have no idea if this is even possible. I have been losing my mind over this for over a week now without any progress.
If that isn't possible, can I generate the variables so I can access them like:
#color-base: #716aca;
Without having to manually create them?
Thank you very much and I hope I asked this right. I am new here.
Consider the following SCSS:
$color-black: #000000;
body {
--color: $color-black;
}
When it is compiled with node-sass version 4.7.2, it produces following CSS:
body {
--color: #000000;
}
When I compile the same SCSS with version 4.8.3 or higher, it produces following:
body {
--color: $color-black;
}
What am I missing? I checked release logs, but could not found anything useful. Also, I wonder if this change is genuine why does it have only minor version change? Should it not be a major release?
Also, what is my alternative? Should I use Interpolation?
Just use string interpolation:
$color-black: #000000;
body {
--color: #{$color-black};
}
Apparently the old behaviour is not intended and violated the language specs of SASS:
CSS variables mixed with SCSS variables don't emit proper CSS in 4.8+
CSS variables aren't properly compiled
Assigning SASS variables to CSS Variables (Custom Properties) no longer works
scss and css
I found a workaround to mapping the scss variables to css variables.
See Terry's answer for better use
Scss:
// sass variable map
$colors: (
color-black: #FFBB00
);
// loop over each name, color
:root {
// each item in color map
#each $name, $color in $colors {
--#{$name}: #{$color};
}
}
Css:
:root {
--color-black: #FFBB00;
}
I had an issue with older sass versions.
Trying to compile a list of variables coming from an array, it would get stuck with the double dash. Here's my solution in case it helps someone
$var-element:'--';
:root {
#each $color in $color-variables {
#{$var-element}#{nth($color, 1)}: #{nth($color, 2)};
}
}
Say I have three separate color schemes that are used on various pages in a site. Each color has a a light, medium and dark tint defined, and the color scheme is defined by a class in the body. Assume that the "red" color scheme is the default. Like this:
Color Definitions:
#red-lt: #121;
#red-md: #232;
#red-dk: #343;
#green-lt: #454;
#green-md: #565;
#green-dk: #676;
#blue-lt: #787;
#blue-md: #898;
#blue-dk: #909;
Basic Default Style Example
body { background-color: #red-dk;
#container { background-color: #red-md;
p { color: #red-dk; }
}
}
Different Color Scheme Style Example
body.green { background-color: #green-dk;
#container { background-color: #green-md;
p { color: #green-dk; }
}
}
I'd like to use variables so that I don't have to re-write all of the color variations for each scheme, so that I can just write something like this:
body.[color-var] { background-color: #[color-var]-dk;
#container { background-color: #[color-var]-md;
p { color: #[color-var]-dk; }
}
}
…but I can't quite wrap my head around how to accomplish that. Help…?
Use interpolation and escaping, parentheses in the selector and parametric mixins to get the desired effect:
Dynamic variables by interpolation: In a string, "#{variable}" is replaced with the value of the variable. They can also be nested: Given #{#{var}-foo} and #var: bar;, the result is "barfoo".
The resulting value is quoted. To remove these quotes, prefix ~.
Dynamic selectors by Selector interpolation: body.#{var} turns into body.bar.
Example:
#red-md: #232;
#red-dk: #343;
.setColor(#color) {
body.#{color} { background-color: ~"#{#{color}-dk}";
#container { background-color: ~"#{#{color}-md}";
p { color: ~"#{#{color}-md}"; }
}
}
}
.setColor(~"red"); // Escape to prevent "red" turning "#FF0000"
//.setColor(~"blue"); etc..
Turns into:
body.red {
background-color: #334433;
}
body.red #container {
background-color: #223322;
}
body.red #container p {
color: #223322;
}
Note: When the answer was originally written, selector interpolation did not exist. See the previous revision for the solution if you're working with an old LESS compiler (before LESS 1.3.1a). Support for the old method will be dropped in LESS 1.4.0.
If those values really follow a predictable format like that, seems like a perfect case for a parametric mixin:
Less:
#red: #232;
#green: #565;
#blue: #898;
.theme (#color) {
background-color: #color - #111;
#container {
background-color: #color;
p { color: #color + #111; }
}
}
body.red {
.theme(#red);
}
Compiled CSS:
body.red{background-color:#112211;}
body.red #container{background-color:#223322;}
body.red #container p{color:#334433;}
I know this question is pretty old, but for those that come to this post my answer maybe can help
I`m not really sure for what you want to use this, but one of my suggestion is based on #ScottS answer. On my real world, I need to create a web app, where it would show several brands and each brand have their own text color, background and so on... so I started to chase a way to accomplish this in LESS, what I could easily do on SASS and the result is below:
LESS
// Code from Seven Phase Max
// ............................................................
// .for
.for(#i, #n) {.-each(#i)}
.for(#n) when (isnumber(#n)) {.for(1, #n)}
.for(#i, #n) when not (#i = #n) {
.for((#i + (#n - #i) / abs(#n - #i)), #n);
}
// ............................................................
// .for-each
.for(#array) when (default()) {.for-impl_(length(#array))}
.for-impl_(#i) when (#i > 1) {.for-impl_((#i - 1))}
.for-impl_(#i) {.-each(extract(#array, #i))}
// Brands
#dodge : "dodge";
#ford : "ford";
#chev : "chev";
// Colors
#dodge-color : "#fff";
#ford-color : "#000";
#chev-color : "#ff0";
// Setting variables and escaping than
#brands: ~"dodge" ~"ford" ~"chev";
// Define our variable
.define(#var) {
#brand-color: '#{var}-color';
}
// Starting the mixin
.color() {
// Generating the loop to each brand
.for(#brands); .-each(#name) {
// After loop happens, it checks what brand is being called
.define(#name);
// When the brand is found, match the selector and color
.brand-#{name} & {
color: ##brand-color;
}
}
}
.carColor {
.color();
}
Te result will be:
CSS
.brand-dodge .carColor {
color: "#fff";
}
.brand-ford .carColor {
color: "#000";
}
.brand-chev .carColor {
color: "#ff0";
}
This is very tricky and I had to use several elements to get what I needed, first used a set of mixins provided by Seven Phase Max and you can find it here and than, the #ScottS answer was the piece that was missing fro my puzzle... hope this helps you and others that need to create a set of Variables to be part of another variable and create a more dynamic less file.
You can copy my entire code and test at http://lesstester.com/
Try this
#red-lt: #121;
#red-md: #232;
#red-dk: #343;
#green-lt: #454;
#green-md: #565;
#green-dk: #676;
#blue-lt: #787;
#blue-md: #898;
#blue-dk: #909;
#color: 'red-lt';
div{
background: ##color;
border: 1px solid lighten(##color,20%);
}
To my knowledge, variable variable names are not supported in LESS. You could however restructure your declarations in a more semantic manner:
/* declare palette */
#red-lt: #121;
#red-md: #232;
#red-dk: #343;
#green-lt: #454;
#green-md: #565;
#green-dk: #676;
#blue-lt: #787;
#blue-md: #898;
#blue-dk: #909;
/* declare variables based on palette colors */
#lt: #red-lt;
#md: #red-md;
#dk: #red-dk;
/* ...and only use them for main declarations */
body { background-color: #dk;
#container { background-color: #md;
p { color: #dk; }
}
}
This should let you switch between palettes quite painlessly by avoiding explicit color references.
I have a very wierd question, I dont know wether if its possible in css or not
Suppose I have say 3 different css classes as shown below, as you can see I have a common property of all these classes, I want to declare this color somewhere else and pass a reference to it here, so if next time I want to change the color I can simply change at one place rather than changing in all the 5 classes.
I know that you can use body{}, or a wrapper for this but that would affect the colors of the entire site right ? Is there a way to do this ?
Is this even possible ?
.abc {
color:red;
}
.abc2 {
color:red;
}
.abc3 {
color:red;
}
.abc4 {
color:red;
}
.abc5 {
color:red;
}
The bad news: you can't do it in CSS.
The good news: you can write in a meta-CSS language like LESS, which then processes a LESS file to pure CSS. This is called a "mixin".
In LESS:
#errorColor: red;
.error-color {
color: #errorColor;
}
#error-1 {
.error-color;
}
.all-errors {
.error-color;
}
More info: http://lesscss.org/#-mixins
if you want to declare all of them at a time, you can use:
.abc, .abc2, .abc3, .abc4, .abc5 {
color:red;
}
Or you can declare an additional class & add to all the .abc, .abc2.... & make its color:red;.
This can not be done with CSS, but that is still a very popular thing to do by using a CSS preprocessor such as LESS, SASS, SCSS, or Stylus.
A preprocessor will let you define a variable (say $red = #F00). It will replace the variable in your CSS document with the variable value for you, allowing you to write very DRY and module CSS.
This functionality is referred to as "CSS variables", which is part of the future spec, but not yet implemented on any browsers.
For now, the best way to do this in pure CSS is to declare an additional class for the desired "global", and then add that class to all relevant items.
.abc_global { color: red; }
.abc1 { /* additional styling */ }
.abc2 { /* additional styling */ }
<div class="abc1 abc_global"></div>
<div class="abc2 abc_global"></div>
With LESS
You are able to define that red color once:
.myRedColor {
color:red;
}
Now you can call that red on any CSS styles. Even NESTED styles! It's a wicked tool!
.abc1 {
.myRedColor;
}
.abc2 {
.myRedColor;
}
.abc3 {
.myRedColor;
}
.abc4 {
.myRedColor;
}
NESTED EXAMPLE:
.abc {
.itsEasyAsOneTwoThree{
.myRedColor;
}
}
Now all of our "itsEasyAsOneTwoThree" classes that are properly nested inside of an "abc" class will be assigned the red style. No more remembering those long #867530 color codes :) How cool is that?!
You can also use PostCSS with the plugin postcss-preset-env and support custom properties/variables, then use the :root selector to add global css variables.
:root {
--color-gray: #333333;
--color-white: #ffffff;
--color-black: #000000;
}