Sass - Converting Hex to RGBa for background opacity - css

I have the following Sass mixin, which is a half complete modification of an RGBa example:
#mixin background-opacity($color, $opacity: .3) {
background: rgb(200, 54, 54); /* The Fallback */
background: rgba(200, 54, 54, $opacity);
}
I have applied $opacity ok, but now I am a stuck with the $color part.
The colors I will be sending into the mixin will be HEX not RGB.
My example use will be:
element {
#include background-opacity(#333, .5);
}
How can I use HEX values within this mixin?

The rgba() function can accept a single hex color as well decimal RGB values. For example, this would work just fine:
#mixin background-opacity($color, $opacity: 0.3) {
background: $color; /* The Fallback */
background: rgba($color, $opacity);
}
element {
#include background-opacity(#333, 0.5);
}
If you ever need to break the hex color into RGB components, though, you can use the red(), green(), and blue() functions to do so:
$red: red($color);
$green: green($color);
$blue: blue($color);
background: rgb($red, $green, $blue); /* same as using "background: $color" */

There is a builtin mixin: transparentize($color, $amount);
background-color: transparentize(#F05353, .3);
The amount should be between 0 to 1;
Official Sass Documentation (Module: Sass::Script::Functions)

SASS has a built-in rgba() function.
rgba($color, $alpha)
e.g.
rgba(#00aaff, 0.5) // Output: rgba(0, 170, 255, 0.5)
An example using your own variables:
$my-color: #00aaff;
$my-opacity: 0.5;
.my-element {
color: rgba($my-color, $my-opacity);
}
// Output: .my-element {color: rgba(0, 170, 255, 0.5);}
To quote the SASS documentation:
The transparentize() function decreases the alpha channel by a
fixed amount, which is often not the desired effect.

you can try this solution, is the best... url(github)
// Transparent Background
// From: http://stackoverflow.com/questions/6902944/sass-mixin-for-background-transparency-back-to-ie8
// Extend this class to save bytes
.transparent-background {
background-color: transparent;
zoom: 1;
}
// The mixin
#mixin transparent($color, $alpha) {
$rgba: rgba($color, $alpha);
$ie-hex-str: ie-hex-str($rgba);
#extend .transparent-background;
background-color: $rgba;
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#{$ie-hex-str},endColorstr=#{$ie-hex-str});
}
// Loop through opacities from 90 to 10 on an alpha scale
#mixin transparent-shades($name, $color) {
#each $alpha in 90, 80, 70, 60, 50, 40, 30, 20, 10 {
.#{$name}-#{$alpha} {
#include transparent($color, $alpha / 100);
}
}
}
// Generate semi-transparent backgrounds for the colors we want
#include transparent-shades('dark', #000000);
#include transparent-shades('light', #ffffff);

If you need to mix colour from variable and alpha transparency, and with solutions that include rgba() function you get an error like
background-color: rgba(#{$color}, 0.3);
^
$color: #002366 is not a color.
╷
│ background-color: rgba(#{$color}, 0.3);
│ ^^^^^^^^^^^^^^^^^^^^
Something like this might be useful.
$meeting-room-colors: (
Neumann: '#002366',
Turing: '#FF0000',
Lovelace: '#00BFFF',
Shared: '#00FF00',
Chilling: '#FF1493',
);
$color-alpha: EE;
#each $name, $color in $meeting-room-colors {
.#{$name} {
background-color: #{$color}#{$color-alpha};
}
}

You can use PostCSS with its postcss-rgb plugin which enables hex support in rgba() rules: arpadHegedus/postcss-rgb

Related

How to export dynamically generated SCSS variables for use in React

I have a _Variables.scss file where I am dynamically generating all my colors. I would like to get access to just one of those colors in my React code, instead of hard coding the value in the code.
My variables file:
$colors-light: (
'color-primary': #EFEFEF,
'color-primary-variant': #D7D7D7,
'color-primary-variant-light': #AAAAAA,
'color-secondary': #23805C,
'color-secondary-variant': #009687,
'text': #4E4E4E,
'text-alt': #FFFFFF
);
$colors-dark: (
'color-primary': #2F302F,
'color-primary-variant': #4E4E4E,
'color-primary-variant-light': #6E6E6E,
'color-secondary': #48BF91,
'color-secondary-variant': #009687,
'color-header': #484e3d,
'text': #FFFFFF,
'text-alt': #222222,
);
/* SASS Functions to create all the CSS variables from the SASS colors above */
#function hexToRGB($hex) {
#return red($hex), green($hex), blue($hex);
}
#mixin generate_colors($colors) {
// Colors
#each $color, $value in $colors {
#if str-slice(#{$value}, 1, 1) == '#' {
--#{$color}: #{$value};
}
#else {
--#{$color}: var(--#{$value});
}
}
// RGB Colors
#each $color, $value in $colors {
#if str-slice(#{$value}, 1, 1) == '#' {
/* stylelint-disable function-name-case */
--RGB-#{$color}: #{hexToRGB($value)};
/* stylelint-enable function-name-case */
}
#else {
--RGB_#{$color}: var(--RGB_#{$value});
}
}
}
/* End of SASS functions */
/* Use the SASS functions and the SASS variables to actually create all the CSS color variables;
e.g. --color-black: #222222 and --RGB-color-black: 34, 34, 34
*/
:root[data-theme='theme-light'] {
#include generate_colors($colors-light);
--color-true-black: #000000;
--RGB-color-true-black: 0, 0, 0;
--color-white: #FFFFFF;
--RGB-color-white: 255, 255, 255;
//--color-orchestrator: #d0ced0;
--color-red: #BB0000;
--RGB-color-red: 187, 0, 0;
--color-red-lighter: #FF2E2E;
--color-pink: #E4BFBF;
--RGB-color-red-lighter: 255, 46, 46;
--color-green: #348D00;
--color-blue: #0000CC;
--RGB-color-blue: 0, 0, 204;
--RGB-color-green: 52, 141, 0;
--label-alpha: 0.3;
}
:root[data-theme='theme-dark'] {
#include generate_colors($colors-dark);
// this does not work
:export {
color-primary: var(--color-primary);
}
--label-alpha: 0.9;
}
In my App.scss file I import Variables and can use them like this:
.answer { color: var(--color-secondary);...
But I am trying to also export them(or just one for now) to use in my React.

SCSS function to change opacity of rgba or hex color [duplicate]

I am designing an app in electron, so I have access to CSS variables. I have defined a color variable in vars.css:
:root {
--color: #f0f0f0;
}
I want to use this color in main.css, but with some opacity applied:
#element {
background: (somehow use var(--color) at some opacity);
}
How would I go about doing this? I am not using any preprocessor, only CSS. I would prefer an all-CSS answer, but I will accept JavaScript/jQuery.
I cannot use opacity because I am using a background image that should not be transparent.
You can't take an existing color value and apply an alpha channel to it. Namely, you can't take an existing hex value such as #f0f0f0, give it an alpha component and use the resulting value with another property.
However, custom properties allow you to convert your hex value into an RGB triplet for use with rgba(), store that value in the custom property (including the commas!), substitute that value using var() into an rgba() function with your desired alpha value, and it'll just work:
:root {
/* #f0f0f0 in decimal RGB */
--color: 240, 240, 240;
}
body {
color: #000;
background-color: #000;
}
#element {
background-color: rgba(var(--color), 0.8);
}
<p id="element">If you can see this, your browser supports custom properties.</p>
This seems almost too good to be true.1 How does it work?
The magic lies in the fact that the values of custom properties are substituted as is when replacing var() references in a property value, before that property's value is computed. This means that as far as custom properties are concerned, the value of --color in your example isn't a color value at all until a var(--color) expression appears somewhere that expects a color value (and only in that context). From section 2.1 of the css-variables spec:
The allowed syntax for custom properties is extremely permissive. The <declaration-value> production matches any sequence of one or more tokens, so long as the sequence does not contain <bad-string-token>, <bad-url-token>, unmatched <)-token>, <]-token>, or <}-token>, or top-level <semicolon-token> tokens or <delim-token> tokens with a value of "!".
For example, the following is a valid custom property:
--foo: if(x > 5) this.width = 10;
While this value is obviously useless as a variable, as it would be invalid in any normal property, it might be read and acted on by JavaScript.
And section 3:
If a property contains one or more var() functions, and those functions are syntactically valid, the entire property’s grammar must be assumed to be valid at parse time. It is only syntax-checked at computed-value time, after var() functions have been substituted.
This means that the 240, 240, 240 value you see above gets substituted directly into the rgba() function before the declaration is computed. So this:
#element {
background-color: rgba(var(--color), 0.8);
}
which doesn't appear to be valid CSS at first because rgba() expects no less than four comma-separated numeric values, becomes this:
#element {
background-color: rgba(240, 240, 240, 0.8);
}
which, of course, is perfectly valid CSS.
Taking it one step further, you can store the alpha component in its own custom property:
:root {
--color: 240, 240, 240;
--alpha: 0.8;
}
and substitute it, with the same result:
#element {
background-color: rgba(var(--color), var(--alpha));
}
This allows you to have different alpha values that you can swap around on-the-fly.
1 Well, it is, if you're running the code snippet in a browser that doesn't support custom properties.
Relative color syntax
With this new CSS ability (css-color-5) which allows color format transformations, it also will also allow adding opacity to any color in any format, for example, to RGB (relative transformations can be done to any other format):
html { --color: blue }
.with-opacity { background: rgb(from var(--color) r g b / 50%) }
(As of writing, not yet available in browsers. Will update once arrives)
👉 Codepen demo
I know the OP isn't using a preprocessor, but I would have been helped if the following information was part of the answer here (I can't comment yet, otherwise I would have commented #BoltClock answer.
If you are using, e.g. scss, the answer above will fail, because scss attempts to compile the styles with a scss-specific rgba()/hsla() function, which requires 4 parameters. However, rgba()/hsla() are also native css functions, so you can use string interpolation to bypass the scss function.
Example (valid in sass 3.5.0+):
:root {
--color_rgb: 250, 250, 250;
--color_hsl: 250, 50%, 50%;
}
div {
/* This is valid CSS, but will fail in a scss compilation */
background-color: rgba(var(--color_rgb), 0.5);
/* This is valid scss, and will generate the CSS above */
background-color: #{'rgba(var(--color_rgb), 0.5)'};
}
<div></div>
Note that string interpolation will not work for non-CSS scss functions, such as lighten(), because the resulting code would not be functional CSS. It would still be valid scss though, so you would receive no error in compilation.
I was in a similar situation, but unfortunately the given solutions did not work for me, as the variables could be anything from rgb to hsl to hex or even color names.
I solved this issue now, by applying the background-color and the opacity to a pseudo :after or :before element:
.container {
position: relative;
}
.container::before {
content: "";
width: 100%;
height: 100%;
position: absolute;
left: 0;
background-color: var(--color);
opacity: 0.3;
}
The styles might need to be changed a little, depending on the element the background should be applied to.
Also it might not work for all situations, but hopefully it helps in some cases, where the other solutions can't be used.
Edit:
I just noticed, that this solution obviously also impacts the text color, as it creates an element in front of the target element and applies a transparent background color to it.
This might be a problem in some cases.
you can use linear-gradient to hack the color:
background: linear-gradient(to bottom, var(--your-color) -1000%, var(--mixin-color), 1000%)
$(() => {
const setOpacity = () => {
$('#canvas').css('--opacity', $('#opacity-value').val())
}
const setColor = () => {
$('#canvas').css('--color', $('#color-value').val());
}
$('#opacity-value').on('input', setOpacity);
$('#color-value').on('input', setColor);
setOpacity();
setColor();
})
#canvas {
width: 100px;
height: 100px;
border: 2px solid #000;
--hack: 10000%;
background: linear-gradient( to bottom, var(--color) calc((var(--opacity) - 1) * var(--hack)), transparent calc(var(--opacity) * var(--hack)));
}
#container {
background-image: linear-gradient(45deg, #b0b0b0 25%, transparent 25%), linear-gradient(-45deg, #b0b0b0 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #b0b0b0 75%), linear-gradient(-45deg, transparent 75%, #b0b0b0 75%);
background-size: 20px 20px;
background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
padding: 10px;
display: inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
<div id="canvas"></div>
</div>
<hr/>
<input type="range" id="opacity-value" min="0" max="1" step="0.1" value="0.5" />
<input type="color" id="color-value" />
If you use dark and light mode, i use this sample. I prefer separate between colors and rgb colors variable assignment. So i use two each loop. I realise this solution is not dry code. If you want to dry code could you use one loop.
$colors-light: (
white: #fff,
black: #0c0d0e,
orange: #f48024,
green: #5eba7d,
blue: #0077cc,
red: #d1383d,
red-100: #e2474c,
red-200: red,
);
$colors-dark: (
black: #fff,
white: #2d2d2d,
orange: #dd7118,
green: #5eba7d,
blue: #0077cc,
red: #aa1c21,
red-100: #c9292e,
red-200: red,
);
#function hexToRGB($hex) {
#return red($hex), green($hex), blue($hex);
}
#mixin generate_colors($colors) {
// Colors
#each $color, $value in $colors {
#if str-slice(#{$value}, 1, 1) == "#" {
--#{$color}: #{$value};
} #else {
--#{$color}: var(--#{$value});
}
}
// RGB Colors
#each $color, $value in $colors {
#if str-slice(#{$value}, 1, 1) == "#" {
--RGB_#{$color}: #{hexToRGB($value)};
} #else {
--RGB_#{$color}: var(--RGB_#{$value});
}
}
}
:root {
#include generate_colors($colors-light);
}
[data-theme="dark"] {
#include generate_colors($colors-dark);
}
dry code
#mixin generate_colors($colors) {
// Colors, RGB Colors
#each $color, $value in $colors {
#if str-slice(#{$value}, 1, 1) == "#" {
--#{$color}: #{$value};
--RGB_#{$color}: #{hexToRGB($value)};
} #else {
--#{$color}: var(--#{$value});
--RGB_#{$color}: var(--RGB_#{$value});
}
}
}
css Output
:root {
--white: #fff;
--RGB_white: 255, 255, 255;
--black: #0c0d0e;
--RGB_black: 12, 13, 14;
--orange: #f48024;
--RGB_orange: 244, 128, 36;
--green: #5eba7d;
--RGB_green: 94, 186, 125;
--blue: #0077cc;
--RGB_blue: 0, 119, 204;
--red: #d1383d;
--RGB_red: 209, 56, 61;
--red-100: #e2474c;
--RGB_red-100: 226, 71, 76;
--red-200: var(--red);
--RGB_red-200: var(--RGB_red);
}
[data-theme="dark"] {
--black: #fff;
--RGB_black: 255, 255, 255;
--white: #2d2d2d;
--RGB_white: 45, 45, 45;
--orange: #dd7118;
--RGB_orange: 221, 113, 24;
--green: #5eba7d;
--RGB_green: 94, 186, 125;
--blue: #0077cc;
--RGB_blue: 0, 119, 204;
--red: #aa1c21;
--RGB_red: 170, 28, 33;
--red-100: #c9292e;
--RGB_red-100: 201, 41, 46;
--red-200: var(--red);
--RGB_red-200: var(--RGB_red);
}
body {
background-color: var(--white);
}
.colors {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-box-pack: start;
-ms-flex-pack: start;
justify-content: flex-start;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
margin: 50px 0 0 30px;
}
.box {
width: 100px;
height: 100px;
margin-right: 5px;
}
.black {
background-color: var(--black);
}
.white {
background-color: var(--white);
}
.orange {
background-color: var(--orange);
}
.green {
background-color: var(--green);
}
.blue {
background-color: var(--blue);
}
.red {
background-color: var(--red);
}
.red-200 {
background-color: var(--red-200);
}
.black-rgba {
background-color: rgba(var(--RGB_black), 0.5);
}
.white-rgba {
background-color: rgba(var(--RGB_white), 0.5);
}
.orange-rgba {
background-color: rgba(var(--RGB_orange), 0.5);
}
.green-rgba {
background-color: rgba(var(--RGB_green), 0.5);
}
.blue-rgba {
background-color: rgba(var(--RGB_blue), 0.5);
}
.red-rgba {
background-color: rgba(var(--RGB_red), 0.5);
}
.red-rgba-200 {
background-color: rgba(var(--RGB_red-200), 0.5);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div>
<input type="checkbox" id="dark-switch" name="theme" />
<label for="dark-switch">Dark / Light</label>
</div>
<div class="color-box">
<div class="colors">
<div class="box red-200"></div>
<div class="box black"></div>
<div class="box white"></div>
<div class="box orange"></div>
<div class="box green"></div>
<div class="box blue"></div>
<div class="box red"></div>
</div>
<br>
<h1>RGBA</h1>
<div class="colors">
<div class="box red-rgba-200"></div>
<div class="box black-rgba"></div>
<div class="box white-rgba"></div>
<div class="box orange-rgba"></div>
<div class="box green-rgba"></div>
<div class="box blue-rgba"></div>
<div class="box red-rgba"></div>
</div>
</div>
<script>
const dark_switch = document.getElementById("dark-switch");
dark_switch.addEventListener("change", (e) => {
e.target.checked
? document.documentElement.setAttribute("data-theme", "dark")
: document.documentElement.setAttribute("data-theme", "light");
});
</script>
</body>
</html>
This is indeed possible with CSS. It's just a bit dirty, and you'll have to use gradients. I've coded a small snippet as example, take note that for dark backgrounds, you should use the black opacity, as for light- the white ones.:
:root {
--red: rgba(255, 0, 0, 1);
--white-low-opacity: rgba(255, 255, 255, .3);
--white-high-opacity: rgba(255, 255, 255, .7);
--black-low-opacity: rgba(0, 0, 0, .3);
--black-high-opacity: rgba(0, 0, 0, .7);
}
div {
width: 100px;
height: 100px;
margin: 10px;
}
.element1 {
background:
linear-gradient(var(--white-low-opacity), var(--white-low-opacity)) no-repeat,
linear-gradient(var(--red), var(--red)) no-repeat;
}
.element2 {
background:
linear-gradient(var(--white-high-opacity), var(--white-high-opacity)) no-repeat,
linear-gradient(var(--red), var(--red)) no-repeat;
}
.element3 {
background:
linear-gradient(var(--black-low-opacity), var(--black-low-opacity)) no-repeat,
linear-gradient(var(--red), var(--red)) no-repeat;
}
.element4 {
background:
linear-gradient(var(--black-high-opacity), var(--black-high-opacity)) no-repeat,
linear-gradient(var(--red), var(--red)) no-repeat;
}
<div class="element1">hello world</div>
<div class="element2">hello world</div>
<div class="element3">hello world</div>
<div class="element4">hello world</div>
SCSS / SASS
Advantage: You can just use Hex color values, instead to use the 8 Bit for every channel (0-255).
This is how I did it with the initial idea of: https://codyhouse.co/blog/post/how-to-combine-sass-color-functions-and-css-variables
Edit: You could also modify the alpha function to just use #{$color-name}-rgb and omit the generated *-r, *-g, *-b CSS variables.
Result
body {
--main-color: rgb(170, 68, 204);
--main-color-rgb: 170,68,204;
--main-color-r: 170;
--main-color-g: 68;
--main-color-b: 204;
}
.button-test {
// Generated from the alpha function
color: rgba(var(--main-color-r), var(--main-color-g), var(--main-color-b), 0.5);
// OR (you wrote this yourself, see usage)
color: rgba(var(--main-color-rgb), 0.5);
}
Usage:
body {
#include defineColorRGB(--main-color, #aa44cc);
}
.button-test {
// With alpha function:
color: alpha(var(--main-color), 0.5);
// OR just using the generated variable directly
color: rgba(var(--main-color-rgb), 0.5);
}
Mixin and functions
#mixin defineColorRGB($color-name, $value) {
$red: red($value);
$green: green($value);
$blue: blue($value);
#{$color-name}: unquote("rgb(#{$red}, #{$green}, #{$blue})");
#{$color-name}-rgb: $red,$green,$blue;
#{$color-name}-r: $red;
#{$color-name}-g: $green;
#{$color-name}-b: $blue;
}
// replace substring with another string
// credits: https://css-tricks.com/snippets/sass/str-replace-function/
#function str-replace($string, $search, $replace: '') {
$index: str-index($string, $search);
#if $index {
#return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
}
#return $string;
}
#function alpha($color, $opacity) {
$color: str-replace($color, 'var(');
$color: str-replace($color, ')');
$color-r: var(#{$color+'-r'});
$color-g: var(#{$color+'-g'});
$color-b: var(#{$color+'-b'});
#return rgba($color-r, $color-g, $color-b, $opacity);
}
You can set specific variable/value for each color - the original and the one with opacity:
:root {
--color: #F00;
--color-opacity: rgba(255, 0, 0, 0.5);
}
#a1 {
background: var(--color);
}
#a2 {
background: var(--color-opacity);
}
<div id="a1">asdf</div>
<div id="a2">asdf</div>
If you can't use this and you are ok with javascript solution, you can use this one:
$(function() {
$('button').click(function() {
bgcolor = $('#a2').css('backgroundColor');
rgb_value = bgcolor.match(/\d+,\s?\d+,\s?\d+/)[0]
$('#a2').css('backgroundColor', 'rgba(' + rgb_value + ', 0.5)');
});
});
:root {
--color: #F00;
}
#a1 {
background: var(--color);
}
#a2 {
background: var(--color);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="a1">asdf</div>
<div id="a2">asdf</div>
<button>Click to change opacity</button>
:root{
--color: 255, 0, 0;
}
#element{
background-color: rgba(var(--color), opacity);
}
where you replace opacity with anything between 0 and 1
First time posting here..
A simple JavaScript solution
Here's a simple JavaScript function that can add transparency to named color CSS colors like 'red'
Although .setFillColor() is depreciated it is still implemented in some browsers (blink & webkit). If setFillColor() ever gets dropped completely hopefully we'll have Relative color syntax by then.
function addTransparency(color, alpha) {
const ctx = document.createElement('canvas').getContext('2d');
ctx.setFillColor(color, alpha);
return ctx.fillStyle;
}
Usage with CSS variables
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Add Transparency to a Color</title>
<style>
:root {
--color: lime;
--alpha: 0.5;
}
.test {
background-color: var(--color);
}
</style>
</head>
<body class='test'>
<script>
try{"use strict"
/* Use the getComputedStyle() method to get the current value of the CSS variable --color and the --alpha variable. */
const color = getComputedStyle(document.documentElement).getPropertyValue('--color')||'white'; //added fallback to color white
const alpha = getComputedStyle(document.documentElement).getPropertyValue('--alpha')||1; //added fallback to solid color value of 1
/* Call the addTransparency() function with the color and alpha values as arguments, and store the result in a variable. */
const transparentColor = addTransparency(color, alpha);
/* Use the setProperty() method of the CSSStyleDeclaration interface to set the value of the --color CSS variable to the value of the transparentColor variable. */
document.documentElement.style.setProperty('--color', transparentColor);
function addTransparency(color, alpha) {
const ctx = document.createElement('canvas').getContext('2d');
ctx.setFillColor(color, alpha);
return ctx.fillStyle;
}
}catch(e){document.write(e);}
</script>
</body>
</html>
Ah page refreshed and I lost everything I typed, posting the draft that saved.
If you love hex colors like me there is another solution.
The hex value is 6 digits after that is the alpha value.
00 is 100% transparency 99 is about 75% then it uses the alphabet 'a1-af' then 'b1-bf' ending with 'ff' which is 100% opaque.
:root {
--color: #F00;
}
#element {
background: var(--color)f6;
}
For using rgba() with general css variable, try this:
Declare your color inside :root, but don't use rgb() as other answers do. just write the value
:root{
--color : 255,0,0;
}
Use --color variable using var() as other answers
#some-element {
color : rgba(var(--color),0.5);
}
In CSS you should be able to either use rgba values:
#element {
background: rgba(240, 240, 240, 0.5);
}
or just set the opacity:
#element {
background: #f0f0f0;
opacity: 0.5;
}

Can I add alpha transparency to a CSS color variable? [duplicate]

I am designing an app in electron, so I have access to CSS variables. I have defined a color variable in vars.css:
:root {
--color: #f0f0f0;
}
I want to use this color in main.css, but with some opacity applied:
#element {
background: (somehow use var(--color) at some opacity);
}
How would I go about doing this? I am not using any preprocessor, only CSS. I would prefer an all-CSS answer, but I will accept JavaScript/jQuery.
I cannot use opacity because I am using a background image that should not be transparent.
You can't take an existing color value and apply an alpha channel to it. Namely, you can't take an existing hex value such as #f0f0f0, give it an alpha component and use the resulting value with another property.
However, custom properties allow you to convert your hex value into an RGB triplet for use with rgba(), store that value in the custom property (including the commas!), substitute that value using var() into an rgba() function with your desired alpha value, and it'll just work:
:root {
/* #f0f0f0 in decimal RGB */
--color: 240, 240, 240;
}
body {
color: #000;
background-color: #000;
}
#element {
background-color: rgba(var(--color), 0.8);
}
<p id="element">If you can see this, your browser supports custom properties.</p>
This seems almost too good to be true.1 How does it work?
The magic lies in the fact that the values of custom properties are substituted as is when replacing var() references in a property value, before that property's value is computed. This means that as far as custom properties are concerned, the value of --color in your example isn't a color value at all until a var(--color) expression appears somewhere that expects a color value (and only in that context). From section 2.1 of the css-variables spec:
The allowed syntax for custom properties is extremely permissive. The <declaration-value> production matches any sequence of one or more tokens, so long as the sequence does not contain <bad-string-token>, <bad-url-token>, unmatched <)-token>, <]-token>, or <}-token>, or top-level <semicolon-token> tokens or <delim-token> tokens with a value of "!".
For example, the following is a valid custom property:
--foo: if(x > 5) this.width = 10;
While this value is obviously useless as a variable, as it would be invalid in any normal property, it might be read and acted on by JavaScript.
And section 3:
If a property contains one or more var() functions, and those functions are syntactically valid, the entire property’s grammar must be assumed to be valid at parse time. It is only syntax-checked at computed-value time, after var() functions have been substituted.
This means that the 240, 240, 240 value you see above gets substituted directly into the rgba() function before the declaration is computed. So this:
#element {
background-color: rgba(var(--color), 0.8);
}
which doesn't appear to be valid CSS at first because rgba() expects no less than four comma-separated numeric values, becomes this:
#element {
background-color: rgba(240, 240, 240, 0.8);
}
which, of course, is perfectly valid CSS.
Taking it one step further, you can store the alpha component in its own custom property:
:root {
--color: 240, 240, 240;
--alpha: 0.8;
}
and substitute it, with the same result:
#element {
background-color: rgba(var(--color), var(--alpha));
}
This allows you to have different alpha values that you can swap around on-the-fly.
1 Well, it is, if you're running the code snippet in a browser that doesn't support custom properties.
Relative color syntax
With this new CSS ability (css-color-5) which allows color format transformations, it also will also allow adding opacity to any color in any format, for example, to RGB (relative transformations can be done to any other format):
html { --color: blue }
.with-opacity { background: rgb(from var(--color) r g b / 50%) }
(As of writing, not yet available in browsers. Will update once arrives)
👉 Codepen demo
I know the OP isn't using a preprocessor, but I would have been helped if the following information was part of the answer here (I can't comment yet, otherwise I would have commented #BoltClock answer.
If you are using, e.g. scss, the answer above will fail, because scss attempts to compile the styles with a scss-specific rgba()/hsla() function, which requires 4 parameters. However, rgba()/hsla() are also native css functions, so you can use string interpolation to bypass the scss function.
Example (valid in sass 3.5.0+):
:root {
--color_rgb: 250, 250, 250;
--color_hsl: 250, 50%, 50%;
}
div {
/* This is valid CSS, but will fail in a scss compilation */
background-color: rgba(var(--color_rgb), 0.5);
/* This is valid scss, and will generate the CSS above */
background-color: #{'rgba(var(--color_rgb), 0.5)'};
}
<div></div>
Note that string interpolation will not work for non-CSS scss functions, such as lighten(), because the resulting code would not be functional CSS. It would still be valid scss though, so you would receive no error in compilation.
I was in a similar situation, but unfortunately the given solutions did not work for me, as the variables could be anything from rgb to hsl to hex or even color names.
I solved this issue now, by applying the background-color and the opacity to a pseudo :after or :before element:
.container {
position: relative;
}
.container::before {
content: "";
width: 100%;
height: 100%;
position: absolute;
left: 0;
background-color: var(--color);
opacity: 0.3;
}
The styles might need to be changed a little, depending on the element the background should be applied to.
Also it might not work for all situations, but hopefully it helps in some cases, where the other solutions can't be used.
Edit:
I just noticed, that this solution obviously also impacts the text color, as it creates an element in front of the target element and applies a transparent background color to it.
This might be a problem in some cases.
you can use linear-gradient to hack the color:
background: linear-gradient(to bottom, var(--your-color) -1000%, var(--mixin-color), 1000%)
$(() => {
const setOpacity = () => {
$('#canvas').css('--opacity', $('#opacity-value').val())
}
const setColor = () => {
$('#canvas').css('--color', $('#color-value').val());
}
$('#opacity-value').on('input', setOpacity);
$('#color-value').on('input', setColor);
setOpacity();
setColor();
})
#canvas {
width: 100px;
height: 100px;
border: 2px solid #000;
--hack: 10000%;
background: linear-gradient( to bottom, var(--color) calc((var(--opacity) - 1) * var(--hack)), transparent calc(var(--opacity) * var(--hack)));
}
#container {
background-image: linear-gradient(45deg, #b0b0b0 25%, transparent 25%), linear-gradient(-45deg, #b0b0b0 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #b0b0b0 75%), linear-gradient(-45deg, transparent 75%, #b0b0b0 75%);
background-size: 20px 20px;
background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
padding: 10px;
display: inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
<div id="canvas"></div>
</div>
<hr/>
<input type="range" id="opacity-value" min="0" max="1" step="0.1" value="0.5" />
<input type="color" id="color-value" />
If you use dark and light mode, i use this sample. I prefer separate between colors and rgb colors variable assignment. So i use two each loop. I realise this solution is not dry code. If you want to dry code could you use one loop.
$colors-light: (
white: #fff,
black: #0c0d0e,
orange: #f48024,
green: #5eba7d,
blue: #0077cc,
red: #d1383d,
red-100: #e2474c,
red-200: red,
);
$colors-dark: (
black: #fff,
white: #2d2d2d,
orange: #dd7118,
green: #5eba7d,
blue: #0077cc,
red: #aa1c21,
red-100: #c9292e,
red-200: red,
);
#function hexToRGB($hex) {
#return red($hex), green($hex), blue($hex);
}
#mixin generate_colors($colors) {
// Colors
#each $color, $value in $colors {
#if str-slice(#{$value}, 1, 1) == "#" {
--#{$color}: #{$value};
} #else {
--#{$color}: var(--#{$value});
}
}
// RGB Colors
#each $color, $value in $colors {
#if str-slice(#{$value}, 1, 1) == "#" {
--RGB_#{$color}: #{hexToRGB($value)};
} #else {
--RGB_#{$color}: var(--RGB_#{$value});
}
}
}
:root {
#include generate_colors($colors-light);
}
[data-theme="dark"] {
#include generate_colors($colors-dark);
}
dry code
#mixin generate_colors($colors) {
// Colors, RGB Colors
#each $color, $value in $colors {
#if str-slice(#{$value}, 1, 1) == "#" {
--#{$color}: #{$value};
--RGB_#{$color}: #{hexToRGB($value)};
} #else {
--#{$color}: var(--#{$value});
--RGB_#{$color}: var(--RGB_#{$value});
}
}
}
css Output
:root {
--white: #fff;
--RGB_white: 255, 255, 255;
--black: #0c0d0e;
--RGB_black: 12, 13, 14;
--orange: #f48024;
--RGB_orange: 244, 128, 36;
--green: #5eba7d;
--RGB_green: 94, 186, 125;
--blue: #0077cc;
--RGB_blue: 0, 119, 204;
--red: #d1383d;
--RGB_red: 209, 56, 61;
--red-100: #e2474c;
--RGB_red-100: 226, 71, 76;
--red-200: var(--red);
--RGB_red-200: var(--RGB_red);
}
[data-theme="dark"] {
--black: #fff;
--RGB_black: 255, 255, 255;
--white: #2d2d2d;
--RGB_white: 45, 45, 45;
--orange: #dd7118;
--RGB_orange: 221, 113, 24;
--green: #5eba7d;
--RGB_green: 94, 186, 125;
--blue: #0077cc;
--RGB_blue: 0, 119, 204;
--red: #aa1c21;
--RGB_red: 170, 28, 33;
--red-100: #c9292e;
--RGB_red-100: 201, 41, 46;
--red-200: var(--red);
--RGB_red-200: var(--RGB_red);
}
body {
background-color: var(--white);
}
.colors {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-box-pack: start;
-ms-flex-pack: start;
justify-content: flex-start;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
margin: 50px 0 0 30px;
}
.box {
width: 100px;
height: 100px;
margin-right: 5px;
}
.black {
background-color: var(--black);
}
.white {
background-color: var(--white);
}
.orange {
background-color: var(--orange);
}
.green {
background-color: var(--green);
}
.blue {
background-color: var(--blue);
}
.red {
background-color: var(--red);
}
.red-200 {
background-color: var(--red-200);
}
.black-rgba {
background-color: rgba(var(--RGB_black), 0.5);
}
.white-rgba {
background-color: rgba(var(--RGB_white), 0.5);
}
.orange-rgba {
background-color: rgba(var(--RGB_orange), 0.5);
}
.green-rgba {
background-color: rgba(var(--RGB_green), 0.5);
}
.blue-rgba {
background-color: rgba(var(--RGB_blue), 0.5);
}
.red-rgba {
background-color: rgba(var(--RGB_red), 0.5);
}
.red-rgba-200 {
background-color: rgba(var(--RGB_red-200), 0.5);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div>
<input type="checkbox" id="dark-switch" name="theme" />
<label for="dark-switch">Dark / Light</label>
</div>
<div class="color-box">
<div class="colors">
<div class="box red-200"></div>
<div class="box black"></div>
<div class="box white"></div>
<div class="box orange"></div>
<div class="box green"></div>
<div class="box blue"></div>
<div class="box red"></div>
</div>
<br>
<h1>RGBA</h1>
<div class="colors">
<div class="box red-rgba-200"></div>
<div class="box black-rgba"></div>
<div class="box white-rgba"></div>
<div class="box orange-rgba"></div>
<div class="box green-rgba"></div>
<div class="box blue-rgba"></div>
<div class="box red-rgba"></div>
</div>
</div>
<script>
const dark_switch = document.getElementById("dark-switch");
dark_switch.addEventListener("change", (e) => {
e.target.checked
? document.documentElement.setAttribute("data-theme", "dark")
: document.documentElement.setAttribute("data-theme", "light");
});
</script>
</body>
</html>
This is indeed possible with CSS. It's just a bit dirty, and you'll have to use gradients. I've coded a small snippet as example, take note that for dark backgrounds, you should use the black opacity, as for light- the white ones.:
:root {
--red: rgba(255, 0, 0, 1);
--white-low-opacity: rgba(255, 255, 255, .3);
--white-high-opacity: rgba(255, 255, 255, .7);
--black-low-opacity: rgba(0, 0, 0, .3);
--black-high-opacity: rgba(0, 0, 0, .7);
}
div {
width: 100px;
height: 100px;
margin: 10px;
}
.element1 {
background:
linear-gradient(var(--white-low-opacity), var(--white-low-opacity)) no-repeat,
linear-gradient(var(--red), var(--red)) no-repeat;
}
.element2 {
background:
linear-gradient(var(--white-high-opacity), var(--white-high-opacity)) no-repeat,
linear-gradient(var(--red), var(--red)) no-repeat;
}
.element3 {
background:
linear-gradient(var(--black-low-opacity), var(--black-low-opacity)) no-repeat,
linear-gradient(var(--red), var(--red)) no-repeat;
}
.element4 {
background:
linear-gradient(var(--black-high-opacity), var(--black-high-opacity)) no-repeat,
linear-gradient(var(--red), var(--red)) no-repeat;
}
<div class="element1">hello world</div>
<div class="element2">hello world</div>
<div class="element3">hello world</div>
<div class="element4">hello world</div>
SCSS / SASS
Advantage: You can just use Hex color values, instead to use the 8 Bit for every channel (0-255).
This is how I did it with the initial idea of: https://codyhouse.co/blog/post/how-to-combine-sass-color-functions-and-css-variables
Edit: You could also modify the alpha function to just use #{$color-name}-rgb and omit the generated *-r, *-g, *-b CSS variables.
Result
body {
--main-color: rgb(170, 68, 204);
--main-color-rgb: 170,68,204;
--main-color-r: 170;
--main-color-g: 68;
--main-color-b: 204;
}
.button-test {
// Generated from the alpha function
color: rgba(var(--main-color-r), var(--main-color-g), var(--main-color-b), 0.5);
// OR (you wrote this yourself, see usage)
color: rgba(var(--main-color-rgb), 0.5);
}
Usage:
body {
#include defineColorRGB(--main-color, #aa44cc);
}
.button-test {
// With alpha function:
color: alpha(var(--main-color), 0.5);
// OR just using the generated variable directly
color: rgba(var(--main-color-rgb), 0.5);
}
Mixin and functions
#mixin defineColorRGB($color-name, $value) {
$red: red($value);
$green: green($value);
$blue: blue($value);
#{$color-name}: unquote("rgb(#{$red}, #{$green}, #{$blue})");
#{$color-name}-rgb: $red,$green,$blue;
#{$color-name}-r: $red;
#{$color-name}-g: $green;
#{$color-name}-b: $blue;
}
// replace substring with another string
// credits: https://css-tricks.com/snippets/sass/str-replace-function/
#function str-replace($string, $search, $replace: '') {
$index: str-index($string, $search);
#if $index {
#return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
}
#return $string;
}
#function alpha($color, $opacity) {
$color: str-replace($color, 'var(');
$color: str-replace($color, ')');
$color-r: var(#{$color+'-r'});
$color-g: var(#{$color+'-g'});
$color-b: var(#{$color+'-b'});
#return rgba($color-r, $color-g, $color-b, $opacity);
}
You can set specific variable/value for each color - the original and the one with opacity:
:root {
--color: #F00;
--color-opacity: rgba(255, 0, 0, 0.5);
}
#a1 {
background: var(--color);
}
#a2 {
background: var(--color-opacity);
}
<div id="a1">asdf</div>
<div id="a2">asdf</div>
If you can't use this and you are ok with javascript solution, you can use this one:
$(function() {
$('button').click(function() {
bgcolor = $('#a2').css('backgroundColor');
rgb_value = bgcolor.match(/\d+,\s?\d+,\s?\d+/)[0]
$('#a2').css('backgroundColor', 'rgba(' + rgb_value + ', 0.5)');
});
});
:root {
--color: #F00;
}
#a1 {
background: var(--color);
}
#a2 {
background: var(--color);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="a1">asdf</div>
<div id="a2">asdf</div>
<button>Click to change opacity</button>
:root{
--color: 255, 0, 0;
}
#element{
background-color: rgba(var(--color), opacity);
}
where you replace opacity with anything between 0 and 1
First time posting here..
A simple JavaScript solution
Here's a simple JavaScript function that can add transparency to named color CSS colors like 'red'
Although .setFillColor() is depreciated it is still implemented in some browsers (blink & webkit). If setFillColor() ever gets dropped completely hopefully we'll have Relative color syntax by then.
function addTransparency(color, alpha) {
const ctx = document.createElement('canvas').getContext('2d');
ctx.setFillColor(color, alpha);
return ctx.fillStyle;
}
Usage with CSS variables
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Add Transparency to a Color</title>
<style>
:root {
--color: lime;
--alpha: 0.5;
}
.test {
background-color: var(--color);
}
</style>
</head>
<body class='test'>
<script>
try{"use strict"
/* Use the getComputedStyle() method to get the current value of the CSS variable --color and the --alpha variable. */
const color = getComputedStyle(document.documentElement).getPropertyValue('--color')||'white'; //added fallback to color white
const alpha = getComputedStyle(document.documentElement).getPropertyValue('--alpha')||1; //added fallback to solid color value of 1
/* Call the addTransparency() function with the color and alpha values as arguments, and store the result in a variable. */
const transparentColor = addTransparency(color, alpha);
/* Use the setProperty() method of the CSSStyleDeclaration interface to set the value of the --color CSS variable to the value of the transparentColor variable. */
document.documentElement.style.setProperty('--color', transparentColor);
function addTransparency(color, alpha) {
const ctx = document.createElement('canvas').getContext('2d');
ctx.setFillColor(color, alpha);
return ctx.fillStyle;
}
}catch(e){document.write(e);}
</script>
</body>
</html>
Ah page refreshed and I lost everything I typed, posting the draft that saved.
If you love hex colors like me there is another solution.
The hex value is 6 digits after that is the alpha value.
00 is 100% transparency 99 is about 75% then it uses the alphabet 'a1-af' then 'b1-bf' ending with 'ff' which is 100% opaque.
:root {
--color: #F00;
}
#element {
background: var(--color)f6;
}
For using rgba() with general css variable, try this:
Declare your color inside :root, but don't use rgb() as other answers do. just write the value
:root{
--color : 255,0,0;
}
Use --color variable using var() as other answers
#some-element {
color : rgba(var(--color),0.5);
}
In CSS you should be able to either use rgba values:
#element {
background: rgba(240, 240, 240, 0.5);
}
or just set the opacity:
#element {
background: #f0f0f0;
opacity: 0.5;
}

How do I apply opacity to a CSS color variable?

I am designing an app in electron, so I have access to CSS variables. I have defined a color variable in vars.css:
:root {
--color: #f0f0f0;
}
I want to use this color in main.css, but with some opacity applied:
#element {
background: (somehow use var(--color) at some opacity);
}
How would I go about doing this? I am not using any preprocessor, only CSS. I would prefer an all-CSS answer, but I will accept JavaScript/jQuery.
I cannot use opacity because I am using a background image that should not be transparent.
You can't take an existing color value and apply an alpha channel to it. Namely, you can't take an existing hex value such as #f0f0f0, give it an alpha component and use the resulting value with another property.
However, custom properties allow you to convert your hex value into an RGB triplet for use with rgba(), store that value in the custom property (including the commas!), substitute that value using var() into an rgba() function with your desired alpha value, and it'll just work:
:root {
/* #f0f0f0 in decimal RGB */
--color: 240, 240, 240;
}
body {
color: #000;
background-color: #000;
}
#element {
background-color: rgba(var(--color), 0.8);
}
<p id="element">If you can see this, your browser supports custom properties.</p>
This seems almost too good to be true.1 How does it work?
The magic lies in the fact that the values of custom properties are substituted as is when replacing var() references in a property value, before that property's value is computed. This means that as far as custom properties are concerned, the value of --color in your example isn't a color value at all until a var(--color) expression appears somewhere that expects a color value (and only in that context). From section 2.1 of the css-variables spec:
The allowed syntax for custom properties is extremely permissive. The <declaration-value> production matches any sequence of one or more tokens, so long as the sequence does not contain <bad-string-token>, <bad-url-token>, unmatched <)-token>, <]-token>, or <}-token>, or top-level <semicolon-token> tokens or <delim-token> tokens with a value of "!".
For example, the following is a valid custom property:
--foo: if(x > 5) this.width = 10;
While this value is obviously useless as a variable, as it would be invalid in any normal property, it might be read and acted on by JavaScript.
And section 3:
If a property contains one or more var() functions, and those functions are syntactically valid, the entire property’s grammar must be assumed to be valid at parse time. It is only syntax-checked at computed-value time, after var() functions have been substituted.
This means that the 240, 240, 240 value you see above gets substituted directly into the rgba() function before the declaration is computed. So this:
#element {
background-color: rgba(var(--color), 0.8);
}
which doesn't appear to be valid CSS at first because rgba() expects no less than four comma-separated numeric values, becomes this:
#element {
background-color: rgba(240, 240, 240, 0.8);
}
which, of course, is perfectly valid CSS.
Taking it one step further, you can store the alpha component in its own custom property:
:root {
--color: 240, 240, 240;
--alpha: 0.8;
}
and substitute it, with the same result:
#element {
background-color: rgba(var(--color), var(--alpha));
}
This allows you to have different alpha values that you can swap around on-the-fly.
1 Well, it is, if you're running the code snippet in a browser that doesn't support custom properties.
Relative color syntax
With this new CSS ability (css-color-5) which allows color format transformations, it also will also allow adding opacity to any color in any format, for example, to RGB (relative transformations can be done to any other format):
html { --color: blue }
.with-opacity { background: rgb(from var(--color) r g b / 50%) }
(As of writing, not yet available in browsers. Will update once arrives)
👉 Codepen demo
I know the OP isn't using a preprocessor, but I would have been helped if the following information was part of the answer here (I can't comment yet, otherwise I would have commented #BoltClock answer.
If you are using, e.g. scss, the answer above will fail, because scss attempts to compile the styles with a scss-specific rgba()/hsla() function, which requires 4 parameters. However, rgba()/hsla() are also native css functions, so you can use string interpolation to bypass the scss function.
Example (valid in sass 3.5.0+):
:root {
--color_rgb: 250, 250, 250;
--color_hsl: 250, 50%, 50%;
}
div {
/* This is valid CSS, but will fail in a scss compilation */
background-color: rgba(var(--color_rgb), 0.5);
/* This is valid scss, and will generate the CSS above */
background-color: #{'rgba(var(--color_rgb), 0.5)'};
}
<div></div>
Note that string interpolation will not work for non-CSS scss functions, such as lighten(), because the resulting code would not be functional CSS. It would still be valid scss though, so you would receive no error in compilation.
I was in a similar situation, but unfortunately the given solutions did not work for me, as the variables could be anything from rgb to hsl to hex or even color names.
I solved this issue now, by applying the background-color and the opacity to a pseudo :after or :before element:
.container {
position: relative;
}
.container::before {
content: "";
width: 100%;
height: 100%;
position: absolute;
left: 0;
background-color: var(--color);
opacity: 0.3;
}
The styles might need to be changed a little, depending on the element the background should be applied to.
Also it might not work for all situations, but hopefully it helps in some cases, where the other solutions can't be used.
Edit:
I just noticed, that this solution obviously also impacts the text color, as it creates an element in front of the target element and applies a transparent background color to it.
This might be a problem in some cases.
you can use linear-gradient to hack the color:
background: linear-gradient(to bottom, var(--your-color) -1000%, var(--mixin-color), 1000%)
$(() => {
const setOpacity = () => {
$('#canvas').css('--opacity', $('#opacity-value').val())
}
const setColor = () => {
$('#canvas').css('--color', $('#color-value').val());
}
$('#opacity-value').on('input', setOpacity);
$('#color-value').on('input', setColor);
setOpacity();
setColor();
})
#canvas {
width: 100px;
height: 100px;
border: 2px solid #000;
--hack: 10000%;
background: linear-gradient( to bottom, var(--color) calc((var(--opacity) - 1) * var(--hack)), transparent calc(var(--opacity) * var(--hack)));
}
#container {
background-image: linear-gradient(45deg, #b0b0b0 25%, transparent 25%), linear-gradient(-45deg, #b0b0b0 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #b0b0b0 75%), linear-gradient(-45deg, transparent 75%, #b0b0b0 75%);
background-size: 20px 20px;
background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
padding: 10px;
display: inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
<div id="canvas"></div>
</div>
<hr/>
<input type="range" id="opacity-value" min="0" max="1" step="0.1" value="0.5" />
<input type="color" id="color-value" />
If you use dark and light mode, i use this sample. I prefer separate between colors and rgb colors variable assignment. So i use two each loop. I realise this solution is not dry code. If you want to dry code could you use one loop.
$colors-light: (
white: #fff,
black: #0c0d0e,
orange: #f48024,
green: #5eba7d,
blue: #0077cc,
red: #d1383d,
red-100: #e2474c,
red-200: red,
);
$colors-dark: (
black: #fff,
white: #2d2d2d,
orange: #dd7118,
green: #5eba7d,
blue: #0077cc,
red: #aa1c21,
red-100: #c9292e,
red-200: red,
);
#function hexToRGB($hex) {
#return red($hex), green($hex), blue($hex);
}
#mixin generate_colors($colors) {
// Colors
#each $color, $value in $colors {
#if str-slice(#{$value}, 1, 1) == "#" {
--#{$color}: #{$value};
} #else {
--#{$color}: var(--#{$value});
}
}
// RGB Colors
#each $color, $value in $colors {
#if str-slice(#{$value}, 1, 1) == "#" {
--RGB_#{$color}: #{hexToRGB($value)};
} #else {
--RGB_#{$color}: var(--RGB_#{$value});
}
}
}
:root {
#include generate_colors($colors-light);
}
[data-theme="dark"] {
#include generate_colors($colors-dark);
}
dry code
#mixin generate_colors($colors) {
// Colors, RGB Colors
#each $color, $value in $colors {
#if str-slice(#{$value}, 1, 1) == "#" {
--#{$color}: #{$value};
--RGB_#{$color}: #{hexToRGB($value)};
} #else {
--#{$color}: var(--#{$value});
--RGB_#{$color}: var(--RGB_#{$value});
}
}
}
css Output
:root {
--white: #fff;
--RGB_white: 255, 255, 255;
--black: #0c0d0e;
--RGB_black: 12, 13, 14;
--orange: #f48024;
--RGB_orange: 244, 128, 36;
--green: #5eba7d;
--RGB_green: 94, 186, 125;
--blue: #0077cc;
--RGB_blue: 0, 119, 204;
--red: #d1383d;
--RGB_red: 209, 56, 61;
--red-100: #e2474c;
--RGB_red-100: 226, 71, 76;
--red-200: var(--red);
--RGB_red-200: var(--RGB_red);
}
[data-theme="dark"] {
--black: #fff;
--RGB_black: 255, 255, 255;
--white: #2d2d2d;
--RGB_white: 45, 45, 45;
--orange: #dd7118;
--RGB_orange: 221, 113, 24;
--green: #5eba7d;
--RGB_green: 94, 186, 125;
--blue: #0077cc;
--RGB_blue: 0, 119, 204;
--red: #aa1c21;
--RGB_red: 170, 28, 33;
--red-100: #c9292e;
--RGB_red-100: 201, 41, 46;
--red-200: var(--red);
--RGB_red-200: var(--RGB_red);
}
body {
background-color: var(--white);
}
.colors {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-box-pack: start;
-ms-flex-pack: start;
justify-content: flex-start;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
margin: 50px 0 0 30px;
}
.box {
width: 100px;
height: 100px;
margin-right: 5px;
}
.black {
background-color: var(--black);
}
.white {
background-color: var(--white);
}
.orange {
background-color: var(--orange);
}
.green {
background-color: var(--green);
}
.blue {
background-color: var(--blue);
}
.red {
background-color: var(--red);
}
.red-200 {
background-color: var(--red-200);
}
.black-rgba {
background-color: rgba(var(--RGB_black), 0.5);
}
.white-rgba {
background-color: rgba(var(--RGB_white), 0.5);
}
.orange-rgba {
background-color: rgba(var(--RGB_orange), 0.5);
}
.green-rgba {
background-color: rgba(var(--RGB_green), 0.5);
}
.blue-rgba {
background-color: rgba(var(--RGB_blue), 0.5);
}
.red-rgba {
background-color: rgba(var(--RGB_red), 0.5);
}
.red-rgba-200 {
background-color: rgba(var(--RGB_red-200), 0.5);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div>
<input type="checkbox" id="dark-switch" name="theme" />
<label for="dark-switch">Dark / Light</label>
</div>
<div class="color-box">
<div class="colors">
<div class="box red-200"></div>
<div class="box black"></div>
<div class="box white"></div>
<div class="box orange"></div>
<div class="box green"></div>
<div class="box blue"></div>
<div class="box red"></div>
</div>
<br>
<h1>RGBA</h1>
<div class="colors">
<div class="box red-rgba-200"></div>
<div class="box black-rgba"></div>
<div class="box white-rgba"></div>
<div class="box orange-rgba"></div>
<div class="box green-rgba"></div>
<div class="box blue-rgba"></div>
<div class="box red-rgba"></div>
</div>
</div>
<script>
const dark_switch = document.getElementById("dark-switch");
dark_switch.addEventListener("change", (e) => {
e.target.checked
? document.documentElement.setAttribute("data-theme", "dark")
: document.documentElement.setAttribute("data-theme", "light");
});
</script>
</body>
</html>
This is indeed possible with CSS. It's just a bit dirty, and you'll have to use gradients. I've coded a small snippet as example, take note that for dark backgrounds, you should use the black opacity, as for light- the white ones.:
:root {
--red: rgba(255, 0, 0, 1);
--white-low-opacity: rgba(255, 255, 255, .3);
--white-high-opacity: rgba(255, 255, 255, .7);
--black-low-opacity: rgba(0, 0, 0, .3);
--black-high-opacity: rgba(0, 0, 0, .7);
}
div {
width: 100px;
height: 100px;
margin: 10px;
}
.element1 {
background:
linear-gradient(var(--white-low-opacity), var(--white-low-opacity)) no-repeat,
linear-gradient(var(--red), var(--red)) no-repeat;
}
.element2 {
background:
linear-gradient(var(--white-high-opacity), var(--white-high-opacity)) no-repeat,
linear-gradient(var(--red), var(--red)) no-repeat;
}
.element3 {
background:
linear-gradient(var(--black-low-opacity), var(--black-low-opacity)) no-repeat,
linear-gradient(var(--red), var(--red)) no-repeat;
}
.element4 {
background:
linear-gradient(var(--black-high-opacity), var(--black-high-opacity)) no-repeat,
linear-gradient(var(--red), var(--red)) no-repeat;
}
<div class="element1">hello world</div>
<div class="element2">hello world</div>
<div class="element3">hello world</div>
<div class="element4">hello world</div>
SCSS / SASS
Advantage: You can just use Hex color values, instead to use the 8 Bit for every channel (0-255).
This is how I did it with the initial idea of: https://codyhouse.co/blog/post/how-to-combine-sass-color-functions-and-css-variables
Edit: You could also modify the alpha function to just use #{$color-name}-rgb and omit the generated *-r, *-g, *-b CSS variables.
Result
body {
--main-color: rgb(170, 68, 204);
--main-color-rgb: 170,68,204;
--main-color-r: 170;
--main-color-g: 68;
--main-color-b: 204;
}
.button-test {
// Generated from the alpha function
color: rgba(var(--main-color-r), var(--main-color-g), var(--main-color-b), 0.5);
// OR (you wrote this yourself, see usage)
color: rgba(var(--main-color-rgb), 0.5);
}
Usage:
body {
#include defineColorRGB(--main-color, #aa44cc);
}
.button-test {
// With alpha function:
color: alpha(var(--main-color), 0.5);
// OR just using the generated variable directly
color: rgba(var(--main-color-rgb), 0.5);
}
Mixin and functions
#mixin defineColorRGB($color-name, $value) {
$red: red($value);
$green: green($value);
$blue: blue($value);
#{$color-name}: unquote("rgb(#{$red}, #{$green}, #{$blue})");
#{$color-name}-rgb: $red,$green,$blue;
#{$color-name}-r: $red;
#{$color-name}-g: $green;
#{$color-name}-b: $blue;
}
// replace substring with another string
// credits: https://css-tricks.com/snippets/sass/str-replace-function/
#function str-replace($string, $search, $replace: '') {
$index: str-index($string, $search);
#if $index {
#return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
}
#return $string;
}
#function alpha($color, $opacity) {
$color: str-replace($color, 'var(');
$color: str-replace($color, ')');
$color-r: var(#{$color+'-r'});
$color-g: var(#{$color+'-g'});
$color-b: var(#{$color+'-b'});
#return rgba($color-r, $color-g, $color-b, $opacity);
}
You can set specific variable/value for each color - the original and the one with opacity:
:root {
--color: #F00;
--color-opacity: rgba(255, 0, 0, 0.5);
}
#a1 {
background: var(--color);
}
#a2 {
background: var(--color-opacity);
}
<div id="a1">asdf</div>
<div id="a2">asdf</div>
If you can't use this and you are ok with javascript solution, you can use this one:
$(function() {
$('button').click(function() {
bgcolor = $('#a2').css('backgroundColor');
rgb_value = bgcolor.match(/\d+,\s?\d+,\s?\d+/)[0]
$('#a2').css('backgroundColor', 'rgba(' + rgb_value + ', 0.5)');
});
});
:root {
--color: #F00;
}
#a1 {
background: var(--color);
}
#a2 {
background: var(--color);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="a1">asdf</div>
<div id="a2">asdf</div>
<button>Click to change opacity</button>
:root{
--color: 255, 0, 0;
}
#element{
background-color: rgba(var(--color), opacity);
}
where you replace opacity with anything between 0 and 1
First time posting here..
A simple JavaScript solution
Here's a simple JavaScript function that can add transparency to named color CSS colors like 'red'
Although .setFillColor() is depreciated it is still implemented in some browsers (blink & webkit). If setFillColor() ever gets dropped completely hopefully we'll have Relative color syntax by then.
function addTransparency(color, alpha) {
const ctx = document.createElement('canvas').getContext('2d');
ctx.setFillColor(color, alpha);
return ctx.fillStyle;
}
Usage with CSS variables
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Add Transparency to a Color</title>
<style>
:root {
--color: lime;
--alpha: 0.5;
}
.test {
background-color: var(--color);
}
</style>
</head>
<body class='test'>
<script>
try{"use strict"
/* Use the getComputedStyle() method to get the current value of the CSS variable --color and the --alpha variable. */
const color = getComputedStyle(document.documentElement).getPropertyValue('--color')||'white'; //added fallback to color white
const alpha = getComputedStyle(document.documentElement).getPropertyValue('--alpha')||1; //added fallback to solid color value of 1
/* Call the addTransparency() function with the color and alpha values as arguments, and store the result in a variable. */
const transparentColor = addTransparency(color, alpha);
/* Use the setProperty() method of the CSSStyleDeclaration interface to set the value of the --color CSS variable to the value of the transparentColor variable. */
document.documentElement.style.setProperty('--color', transparentColor);
function addTransparency(color, alpha) {
const ctx = document.createElement('canvas').getContext('2d');
ctx.setFillColor(color, alpha);
return ctx.fillStyle;
}
}catch(e){document.write(e);}
</script>
</body>
</html>
Ah page refreshed and I lost everything I typed, posting the draft that saved.
If you love hex colors like me there is another solution.
The hex value is 6 digits after that is the alpha value.
00 is 100% transparency 99 is about 75% then it uses the alphabet 'a1-af' then 'b1-bf' ending with 'ff' which is 100% opaque.
:root {
--color: #F00;
}
#element {
background: var(--color)f6;
}
For using rgba() with general css variable, try this:
Declare your color inside :root, but don't use rgb() as other answers do. just write the value
:root{
--color : 255,0,0;
}
Use --color variable using var() as other answers
#some-element {
color : rgba(var(--color),0.5);
}
In CSS you should be able to either use rgba values:
#element {
background: rgba(240, 240, 240, 0.5);
}
or just set the opacity:
#element {
background: #f0f0f0;
opacity: 0.5;
}

Sass - What's the difference between map-get and simple variable?

I'm new with Sass stuff and I've been reading about different ways to use variables, this principle I'm trying to apply is just for colors, some of the solutions I've found were something like this (map-get):
$colors: (
lighestGray: #F8F8FA,
lightGray: #A5ACBA,
light: #FFFFFF,
dark: #000000,
link: #428bca,
linkHover: #555,
navBlue: #7AC243,
navGreen: #009CDC,
);
Then you use it on your class like this:
.my-class {
color: map-get($colors, dark);
}
And the other way is to use:
$color-black: #000000;
Then you use it like this:
.my-class {
color: $color-black;
}
My question is, which option is better? or map-getfunction has another purpose?, has Sass a pattern for this or it depends on each web-developer?.
Thanks for helping me out!.
Regards.
The differences is that when you use $map variables, they are best designed for using through iterations or using #each.
Sample case:
SCSS
// Map variable
$icons: (
facebook : "\f0c4",
twitter : "\f0c5",
googleplus : "\f0c6",
youtube : "\f0c7"
);
// Mixin doing the magic
#mixin icons-list($map) {
#each $icon-name, $icon in $map {
#if not map-has-key($map, $icon-name) {
#warn "'#{$icon-name}' is not a valid icon name";
}
#else {
&--#{$icon-name}::before {
content: $icon;
}
}
}
}
// How to use it
.social-link {
background-color: grey;
#include icons-list($icons);
}
CSS
// CSS Output
.social-link {
background-color: grey;
}
.social-link--facebook::before {
content: "";
}
.social-link--twitter::before {
content: "";
}
.social-link--googleplus::before {
content: "";
}
.social-link--youtube::before {
content: "";
}
This code was taken from my own answer in the following post but the answer is a case use of #each :)
Hope this help you
Example making a theme with css variables with fallback color
see codepen css variables
// VARS (FOR FALLBACK)
// -------------------
$theme-base: #70c1ac;
$theme-base-aa: adjust-color($theme-base, $blue: 125);
// PROCESSED THEME
$theme-color: $theme-base;
$theme-color-dark: darken($theme-color, 20%);
$theme-color-light: lighten($theme-color, 20%);
$theme-color-mixed: mix(#fff, $theme-color, 75%);
$theme-color-trans: transparentize($theme-color, .4);
// PROCESSED SECONDARY
$theme-color-aa: $theme-base-aa;
$theme-color-aa-dark: darken($theme-color-aa, 20%);
$theme-color-aa-light: lighten($theme-color-aa, 20%);
$theme-color-aa-mixed: mix(#fff, $theme-color-aa, 75%);
$theme-color-aa-trans: transparentize($theme-color-aa, .4);
$theme-colors: (
"aa-dark": $theme-color-aa-dark,
"aa-light": $theme-color-aa-light,
"aa-mixed": $theme-color-aa-mixed,
"aa-trans": $theme-color-aa-trans,
aa: $theme-color-aa,
dark: $theme-color-dark,
light: $theme-color-light,
mixed: $theme-color-mixed,
theme: $theme-color,
trans: $theme-color-trans,
);
#mixin themeColor ($prop, $color: null) {
#if ($color) {
#{$prop}: map-get($theme-colors, $color);
#{$prop}: var(--theme-color-#{$color})
} #else {
#{$prop}: map-get($theme-colors, theme);
#{$prop}: var(--theme-color);
}
}
#mixin setThemeColors($base1: "", $base2: "") {
// BASE THEME COLORS
$color-base: $theme-base;
$color-aa: $theme-base-aa;
#if ($base1) {
$color-base: $base1;
$color-aa: $base2;
}
// PROCESSED THEME COLORS
$color-aa-dark: darken($color-aa, 20%);
$color-aa-light: lighten($color-aa, 20%);
$color-aa-mixed: mix(#fff, $color-aa, 75%);
$color-aa-trans: transparentize($color-aa, .5);
$color-aa: $color-aa;
$color-dark: darken($color-base, 20%);
$color-light: lighten($color-base, 20%);
$color-mixed: mix(#fff, $color-base, 75%);
$color-trans: transparentize($color-base, .5);
// CSS VARIABLES
--theme-color-aa-dark: #{$color-aa-dark};
--theme-color-aa-light: #{$color-aa-light};
--theme-color-aa-trans: #{$color-aa-trans};
--theme-color-aa: #{$color-aa};
--theme-color-dark: #{$color-dark};
--theme-color-light: #{$color-light};
--theme-color-mixed: #{$color-mixed};
--theme-color-trans: #{$color-trans};
--theme-color: #{$color-base};
}
:root {
#include setThemeColors($theme-base, $theme-base-aa);
}
body {
#include themeColor("background","mixed");
font-size: 2rem;
}
ul {
list-style: none; /* Remove default bullets */
}
ul li::before {
content: "\2022"; /* Add content: \2022 is the CSS Code/unicode for a bullet */
#include themeColor("color","dark");
font-weight: bold; /* If you want it to be bold */
display: inline-block; /* Needed to add space between the bullet and the text */
width: 1.2em; /* Also needed for space (tweak if needed) */
margin-left: -.8em; /* Also needed for space (tweak if needed) */
}
li {
#include themeColor("color", "light");
#include themeColor("background", "aa-dark");
}
Why pick one when you can have them both.
_variables.scss
$color0 : white;
$color1 : red;
$color2 : green;
$color3 : blue;
_lists.scss
#use "variables";
#use "sass:map";
#use "sass:meta";
#use "sass:list";
#function dynamic($variable){
$i: 0;
$list: ();
#while(variable-exists($variable + $i)){
$list: list.append($list, map.get(meta.module-variables(variables), $variable + $i));
$i: $i + 1;
}
#return $list;
}
$colors: dynamic('color'); // white red green blue
Import both into your scss files and use the list when you need to loop and the variables for shorthand when applying styles.
map-get is used for getting css value from more kind of object.
suppose you have $param where you have defined multiple properties and now you want to assign. you can use it in following ways -
color: map-get($params, "color");
Where else simple variable holds only single value
map-get to get css value from object holding multiple values whereas
variable to hold single value

Resources