Say you have the CSS custom property for a color:
--color: 255,0,0
And you want to mix it specially every time with rgb or rgba as the need requires. This is valid CSS:
rgba(var(--color), .3)
...but Sass explodes. I've been trying to see if I could write a mixin or something but I can't figure out how to get around Sass's insistence on using it's own color functions even when they are not necessary.
Got it! This is a bit hacky but this allows you to create a custom function that utilizes the rgba() function with CSS custom properties (as allowed in the spec):
#function swatch($swatch-color, $swatch-alpha:1) {
#return unquote("rgba(var(--#{$swatch-color}), #{$swatch-alpha})");
}
:root {
--green: 0,255,0;
}
.green { color: swatch(green, .1); }
Found the key to the solution in a Sass bug report. This only works because the unquoting and interpolation bypass the default rgba() function.
Perhaps using interpolation rgba(#{--color}, .3)?
Another temporary workaround for this is to use RGB values only in your variables like you are already:
--color: 255, 255, 255;
Then if you use the RGB or RGBA function with capitals, SASS will ignore it and plain CSS is able to parse it. You can then adjust the opacity!
RGB(var(--color));
RGBA(var(--color), .3);
rgba(var(--color), .3) is not valid:
div {
width: 50px;
height: 20px;
outline: 1px dashed black;
}
:root {
--color: red;
}
#correct {
background: var(--color);
}
#incorrect {
background: rgba(var(--color), .3);
}
<div id="correct"></div>
<div id="incorrect"></div>
Related
Any reason why this isn't working?
:root {
--color-white: 0 0% 100%;
}
color: hsla(var(--color-white) 1);
I'm getting:
SCSS processing failed: file "_page.scss", line 5, col 16: Function hsla is missing argument $saturation.
I also tried
color: #{hsla(var(--color-white) 1)};
which still does not work.
Try like below. You need comma with hsla() using the old syntax
:root {
--color-white: 0, 0%, 100%;
}
.box {
color: hsla(#{var(--color-white), 1});
}
Or use the new syntax where you need / before the alpha
:root {
--color-white: 0 0% 100%;
}
.box {
color: hsl(#{var(--color-white) / 100%});
}
Reference: https://www.w3.org/TR/css-color-4/#the-hsl-notation
SASS attempts to compile the styles with a SASS-specific hsla() function. However, hsla() is also a native CSS function, so you can use string interpolation to bypass the SASS function.
:root {
--color-white: 0 0% 100%;
}
div {
/* This is valid CSS, but will fail in a scss compilation */
color: hsla(var(--color-white) 1);
/* This is valid scss, and will generate the CSS above */
color: #{'hsla(var(--color-white) 1)'};
}
Taken from this answer on SO.
hsla() takes four inputs and the punctuation needs to be accurate or none of it will work. No hash tags are needed:
--color: 0, 100%, 50%;
color: hsla(var(--color), 1);
This 100% works (pun intended).
Please, add commas between --color-white's percentages and after passing the var (before '1' in color).
This solution should work:
:root {
--color-white: 0, 0%, 100%;
}
color: hsla(var(--color-white), 1);
It looks like rgb() works without commas, but hsla() needs commas.
See here: http://codepen.io/Aleksgrunwald/pen/abpQQrr
I"m trying to use CSS custom properties in a rgba value. I am able to get the desired result in pure css, but when I test this out in codepen.io or my IDE that are both using scss, I am getting an error of: overloaded function `rgba` given wrong number of arguments . How can I incorporate this in SCSS
Here is a codepen that shows the error: https://codepen.io/tmocodes/pen/xxVdMEq?editors=1100
The below snippet works because it is not using SCSS.
:root {
--color-primary: 29 4 247;
--lighten: 10%;
}
#element {
background-color: rgba(var(--color-primary) / var(--lighten));
color: rgb(var(--color-primary));
}
<h1 id="element">Using CSS Custom Properities with opacity</h1>
To incorporate modern comma-free CSS color syntax with SCSS, I've used this workaround.
The reason this doesn't work is that it conflicts with the Sass rgb/rgba function. You can uppercase one or more letters to make Sass ignore it (being case sensitive). CodePen demo.
$color-primary: 29 4 247;
$color-secondary: 247 4 4;
$lighten: 10%;
#element {
background-color: Rgba($color-primary / $lighten);
color: Rgb($color-primary);
}
#element-2 {
background-color: Rgba($color-secondary / $lighten);
color: Rgb($color-secondary);
}
SCSS preprocessor has to computed the vales before it can be assigned to the css variables.
Following approach might give you hint to approach the solution you are looking for.
rgba require 4 parameters
rgb require 3 parameters.
$blue: rgb(29, 4, 247);
$red: rgb(29, 4, 247);
$lighten: 10%;
:root {
--color-primary: #{blue};
--color-secondary: #{red};
--lighten: #{lighten};
}
#element {
background-color: lighten($blue, $lighten);
color: $blue;
}
#element-2 {
background-color: lighten($red, $lighten);
color: $red;
}
I created the following CodePen, that gives the idea of how to combine scss with css variables.
I add css variable to root because i want to change it dynamically by using JS
#root {
--primary-color: #4c5b73;
}
$primary-color: var(--primary-color) !default;
.my-component {
background-color: transparentize($primary-color, 0.85);
}
I want to use the Basic scss function transparentize
or lighter or darker
But i got this error
Argument `$color` of `transparentize($color, $amount)` must be a color
How can i tell that this is a color type?
Update
I should do this more earlier
https://codepen.io/colton123/pen/bGVbRjP
Instead of declaring the : root variable first, makes the code like this one.
Your code flow is not right. It may gonna help you. You should study this article
$primary-color: #4c5b73;
: root{
--primary-color: #{$primary-color};
}
.my-component {
background-color: transparentize($primary-color, 0.85);
}
You could just add the alpha channel in regular CSS if you define the color using decimal RGB values instead of a hex code:
:root {
--primary-color: 76, 91, 7;
}
body {
background-color: white;
}
.my-component {
background-color: rgba(var(--primary-color), 0.15);
}
<div class="my-component">
Test
</div>
You would use getComputedStyle and getPropertyValue
this solution should get you what you need. :)
Is there a keyword like currentcolor which allows us to get the color of a class in its default state?
For example, I'm trying to create a re-useable button style, and currentcolor keyword helps a lot until I try to create the :hovered state.
.outline-btn {
background-color: transparent;
border: 1px solid currentColor;
padding: 0.5em 1.5em;
}
.rounded-btn {
border-radius: 50px;
}
The default state looks the way we want and changing the color or the font-size would also adjust the rest of the properties.
But we want the :hovered state to invert the colors (white text and orange background in this case)
.outline-btn:hover, .outline-btn:active, .outline-btn:focus {
background-color: currentcolor;
color: white;
}
But since in this state the color becomes white, everything else also turns white.
Is there a way that we can achieve the behavior that we want without having to create multiple classes for the different button styles that we want?
Desired effect on hover:
Also I forgot to mention that I am using SCSS if that helps.
Thanks for your time :)
If you think about it, you're essentially wanting currentColor to act as a variable -- to hold a constant value. The upcoming CSS variables will help with this, but until they're better supported, we have Sass variables.
By defining the colors as variables you can write them out very verbosely and specifically, but only have to change the color in one place when needed.
$btn-color: red;
$btn-bg: transparent;
.outline-btn {
background-color: $btn-bg;
border: 1px solid $btn-color;
padding: 0.5em 1.5em;
color: $btn-outline-color;
&:hover,
&:active,
&:focus {
background-color: $btn-outline-color;
color: $btn-outline-bg;
}
}
You could go a step further and have those variables set to equal previously set variables you're using for the body/html color background, e.g., $bg-bg: $body-bg; $btn-color: $text-color;. I love currentColor as well and this isn't as clean as that, but it might be more appropriate in this case.
You can then build this out as a mixin as user6292372 noted. Something like:
#mixin buttonBuilder($color, $bg) {
background-color: $bg;
border: 1px solid $color;
color: $color;
&:hover {
background-color: $color;
color: $bg;
}
}
...
.outline-btn {
#include button-builder($btn-color, $btn-bg);
}
Then you can easily make multiple variants.
this can't be done with css only
if you use helpers like SCSS or Less you could make yourself a mixin where you only insert the color you want as a parameter.
but you would still have to make several classes (as many as you need different colors) but can reuse your mixin within like this (scss example):
#mixin invertHover($color) {
background-color: transparent;
border: 1px solid $color;
color: transparent;
&:hover {
background-color: $color;
border: 1px solid transparent;
color: $color;
}
}
.blue-box { #include invertHover('blue'); }
.black-box { #include invertHover('#000000'); }
I’ve got a website that’s using a few different ‘main’ colors. The general HTML layout stays the same, only the colors change depending on the content.
I was wondering if I could set a color variable depending on the CSS selector. This way I can theme my website with a few variables and let Sass fill in the colors.
For example:
$color-1: #444;
$color-2: #555;
$color-3: #666;
$color-4: #777;
body.class-1 {
color-default: $color-1;
color-main: $color-2;
}
body.class-2 {
color-default: $color-3;
color-main: $color-4;
}
/* content CSS */
.content {
background: $color-default;
color: $color-main;
}
I was thinking of using a mixin for this, but I was wondering if there’s a better way to do this—with a function maybe? I’m not that great with Sass, so any help would be appreciated.
I think a mixin is the answer. (As I wrote, variables won’t work.)
#mixin content($color-default, $color-main) {
background: $color-default;
color: $color-main;
}
body.class-1 {
#include content(#444, #555);
}
body.class-2 {
#include content(#666, #777);
}
That SCSS compiles to this CSS:
body.class-1 {
background: #444444;
color: #555555; }
body.class-2 {
background: #666666;
color: #777777; }
If you wanted to group the color values together in your SCSS file, you could use variables in conjunction with the mixin:
$color-1: #444;
$color-2: #555;
$color-3: #666;
$color-4: #777;
body.class-1 {
#include content($color-1, $color-2);
}
body.class-2 {
#include content($color-3, $color-4);
}
as sass documentation explain nicely (https://sass-lang.com/documentation/variables):
Sass variables are all compiled away by Sass. CSS variables are included in the CSS output.
CSS variables can have different values for different elements, but Sass variables only have one value at a time.
Sass variables are imperative, which means if you use a variable and then change its value, the earlier use will stay the same. CSS variables are declarative, which means if you change the value, it’ll affect both earlier uses and later uses.
We may take advantage of that using a combination of sass and css variables to achieve what you want:
//theme colors
$red-cosmo: #e01019;
$green-cosmo: #00c398;
$primary-color: var(--primary-color);
body{
--primary-color: #{$red-cosmo};
}
body.univers-ride{
--primary-color: #{$green-cosmo};
}
So when I call my sass variable $primary-color, it will print as my css variable "var(--primary-color)" that will expand as $green-cosmo only if my body has the "univers-ride" class else it will be $red-cosmo the default color.
If you really want to get hacky you could also define your different color schemes in a single variable like $scheme1: class1 #333 #444, where the first value is always the name, and that is followed by all the colors in that scheme.
You can then use #each:
// Define your schemes with a name and colors
$scheme1: class1 #444 #555;
$scheme2: class2 #666 #777;
$scheme3: class4 #888 #999;
// Here are your color schemes
$schemes: $scheme1 $scheme2 $scheme3;
#each $scheme in $schemes {
// Here are the rules specific to the colors in the theme
body.#{nth($scheme, 1)} .content {
background-color: nth($scheme, 2);
color: nth($scheme, 3);
}
}
This will compile to:
body.class1 .content {
background-color: #444444;
color: #555555; }
body.class2 .content {
background-color: #666666;
color: #777777; }
body.class4 .content {
background-color: #888888;
color: #999999; }
Obviously if you don't want to combine body.class1 and .content in your selectors, you could just specify a mixin content($main, $default) and call it inside the #each using nth just like in the above code, but the point is you don't have to write out a rule for each of your classes.
EDIT There are lots of interesting answers on Creating or referencing variables dynamically in Sass and Merge string and variable to a variable with SASS.
You can also create a mixing that use the ampersand parent selector. http://codepen.io/juhov/pen/gbmbWJ
#mixin color {
body.blue & {
background: blue;
}
body.yellow & {
background: yellow;
}
}
UPDATE: its 2017 and variables does works!
#mixin word_font($page) {
#font-face {
font-family: p#{$page};
src: url('../../static/fonts/ttf/#{$page}.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
.p#{$page} {
font-family: p#{$page};
}
}
// Loop and define css classes
#for $i from 1 through 604 {
#include word_font($i);
}
If you don't want to use a variable for each color, you can use one variable for all kinds of colors. In the mixin you can choose the right color with nth. For instance, if you write the index of the color as 1, then you get the first color in the color variable.
$colors: #444, #555, #666, #777;
#mixin content($color-default-num, $color-main-num) {
background: nth($colors, $color-default-num);
color: nth($colors, $color-main-num);
}
body.class-1 {
#include content(1, 2);
}
For me the definite answer to my problem was creating a map of maps and loopig through them as follows:
$pallettes: (
light-theme: (
container-color: red,
inner-color: blue,
),
dark-theme: (
container-color: black,
inner-color: gray,
),
);
#each $pallette, $content in $pallettes {
.main.#{$pallette} {
background-color: map-get($content, container-color);
.inner-div {
background-color: map-get($content, inner-color);
}
}
}
You can simply override your scss variables inside of the class wrapper:
$color1: red;
$color2: yellow;
header { background: $color1; }
.override-class {
$color1: green;
header { background: $color1; }
}
Seems to work for me.