How to make dynamic variables with less in a CSS file? - css

Actually I want to use a CSS variable in less...
:root {
--header: #6B66A4;
}
#header: #6B66A4;
How?

Less compiles the following
:root {
--header: #6B66A4;
}
#header: var(--header);
body {
color: #header;
}
to this CSS being generated at build time:
:root {
--header: #6B66A4;
}
body {
color: var(--header);
}
Of course Less doesn't know anything about what var(--header) means or is - it's just a string to Less.

Related

Using CSS variables in LESS

This might seem basic, but I can't figure out how to use CSS variables in LESS?
variables.css:
.root {
--header-color: white;
--content-color: yellow;
}
styles.less:
#import "../variables.css";
.header {
color: #header-color;
}
I get error "#header-color is undefined".
LESS allows you to use normal CSS code, so use one option could be just use the variable as CSS:
#import "../variables.css";
.header {
color: var(--header-color);
}
Also, you can save the css var to a LESS var:
#import "../variables.css";
#header-color: var(--header-color);
.header {
color: #header-color;
}

Which tool use to merge CSS and SCSS code

Since my code is difficult to read I want to merge some long regular css statements like this:
.aui #content .columns-1-2-equal .row-fluid #column-3 header {
prop1 ...prop2 prop3
}
with a current scss document.
So assuming i have a piece of CSS which looks like the previous statement and I have a scss file containing this for example:
.aui #content {
prop4
.columns-1-2-equal {
prop5
.row-fluid {
#column-3 {
.header {
}
}
}
I want as a result
.aui #content {
prop4
.columns-1-2-equal {
prop5
.row-fluid {
#column-3 {
.header {
// MERGED CODE
prop1 ...prop2 prop3
}
}
}
Is there an automatic way to do it without having to search for the equivalent element in the SCSS tree and copy paste all the properties?
In this case you have two files:
OLD.scss
div {
width: 300px;
}
and
NEW.scss
#import "OLD.scss";
div {
color: red;
}
First you should run sass NEW.scss COMBINED.css it will output:
COMBINED.css
div {
width: 300px;
}
div {
color: red;
}
Then sass-convert COMBINED.css COMBINED.sass and you will get:
COMBINED.sass
div {
width: 300px;
color: red;
}
You don't really have to because it will be compiled automatically. But, I get that it can be difficult to read the code in this very long format. I tested this tool and its basic function. Hope this helps for you.
https://www.css2scss.com/

Sass: Using Ampersand '&' for body tag which has a specific class

Demo: https://codepen.io/moradxd/pen/WJpPyQ
Assume i have this HTML code:
<body class="boxed">
<div class="text-white">
Button
</div>
</dody>
I'm using this sass code as following:
.boxed {
// error with using "Ampersand"
body& {
}
}
But it results a compiling error which says:
Although the result i want is as following:
// This the result i want
body.boxed {
}
I know that i can use it like this, and it will result what i'm looking for:
// I know i can use this
body {
&.boxed {
}
}
But i want to separate the .boxed class code from inside the body css code for orgnization purpose.
So why this is not allowed although the similar code for element and it's parent is working for the following:
// Although this similar code for element and
// it's parent is working
.btn-featured {
.text-white & {
font-size: 30px;
}
}
In fact i hope to know why this not allowed!
Hello morad you need to use #at-root
.boxed {
#at-root body#{&} {
color: red;
}
}
codepen
You need to swap your selectors around for it to work like you've said.
body {
&.boxed {
background: red;
}
}
The issue is that the ampersand connects the previous selector to the current selector. So when you do something like this:
.boxed {
body & {
background: red;
}
}
It's trying to add 'nothing' to the body tag inside an element with the boxed class on it. The best way is to do it how you've already stated.
More info on referencing parent selectors.

Set a SASS variable depending

I'm searching a way to use a particular color depending on a class on the body tag.
I have a main scss file like this
// variables.scss
$bg-main: white;
$color-first: red;
$color-second: green;
And in my other files, I use the colors
// content.scss
.content {
.some-selector: {
// some styles
color: $color-second;
}
a:hover {
// some styles
color: $color-second;
}
}
// and same goes for menu.scss etc.
Now I have a dynamic class on the body, that changes depending on the current selected menu. I would like $color-second to be different for each body classes, and I don't know how to do that. The only solution I found was to move all the $color-second from each files into one single file, like this:
.body-1 {
.content a:hover, .content .some-selector {
color: green;
}
}
.body-2 {
.content a:hover, .content .some-selector {
color: blue;
}
}
.body-1 {
.content a:hover, .content .some-selector {
color: black;
}
}
So I don't need to write the color in each files. This works well, but if I need to set this $color-second to some other selector, I need to put that in this big file.
Is this possible to do this an other way?
I already checked these answers, but it didn't helped me much:
SASS set variable depending on CSS class
Creating or referencing variables dynamically in Sass
Merge string and variable to a variable with SASS
There are multiple ways to do this. The most obvious two which come to mind are mixins and loops:
Mixins
Just put everything you want into a single mixin, and then use it for every body class:
#mixin colored-content($color) {
.content a:hover, .content .some-selector {
color: $color;
}
/* Any other rules which use $color here */
}
.body-1 {
#include colored-content(green);
}
.body-2 {
#include colored-content('#FF0000');
}
.body-3 {
#include colored-content(darken(red, 20));
}
You can extend this example with any number of arguments (for example, $textColor and $bgColor), conditions or rules.
With this approach you will not have SCSS code repetitions, and any updates will be introduced easily.
Loop
Another way is to use a simple loop:
$body_themes: (
"body-1": green,
"body-2": #FF0000,
"body-3": darken(red, 2)
);
#each $body_class, $color in $body_themes {
.#{$body_class} {
.content a:hover, .content .some-selector {
color: $color;
}
/* Any other rules which use $color here */
}
}
It is even shorter, but imho it is less readable.
P.S. It is possible to combine mixins and loops, by the way :)

Name clash between Less mixin and CSS selector

I have this simplified Less script
.placeholder(#color: #333333) {
&::-webkit-input-placeholder { color: #color; }
}
input {
.placeholder();
}
.placeholder {
margin-top: 20px;
}
The output when I run this through my local compiler or winless online less compiler is
input {
margin-top: 20px;
}
input::-webkit-input-placeholder {
color: #333333;
}
.placeholder {
margin-top: 20px;
}
Insted of the desired output
input::-webkit-input-placeholder {
color: #333333;
}
.placeholder {
margin-top: 20px;
}
Is this a bug or am I missing something here?
By the result it looks to me like I can't have CSS-selectors with the same name as mixins with default values.
I'm running into this problem when compiling Bootstrap with my site specific code. In this particular case I can work around it, but as the project grows and I include other projects I can't imaging I have to keep track of any mixins with default values?
Edit: I see now that I should have read the manual and pretty much seen on the first page of the docs that everything can be treated as a mixin.
In Less, everything is technically a mixin irrespective of whether we write it with parantheses (as in with parameters) or without parantheses (as in like a CSS class selector). The only difference between the two is that when the parantheses are present, the properties present within it are not output unless called from within a selector block.
Quoting the Less Website:
It is legal to define multiple mixins with the same name and number of parameters. Less will use properties of all that can apply.
In this case, since the other mixin has a default value for its only parameter, both the properties can apply when called without any parameter and hence there is no way to avoid it from happening.
Workaround Solution: One possible solution to work-around this problem is to enclose all such conflicting rules within a parent selector (like body).
.placeholder(#color: #333333) {
&::-webkit-input-placeholder { color: #color; }
}
input {
.placeholder();
}
body{
.placeholder{
margin-top: 20px;
}
}
Compiled CSS:
input::-webkit-input-placeholder {
color: #333333;
}
body .placeholder {
margin-top: 20px;
}
Option 2: Extracted from the solution posted by seven-phases-max in the Less GitHub Issue thread.
For the particular use-case one of possible workarounds is to isolate conflicting classes in unnamed scope so they won't interfere with external names:
.placeholder(#color: #333333) {
&::-webkit-input-placeholder { color: #color; }
}
input {
.placeholder();
}
& { // unnamed namespace
.placeholder {
background: #ffffff;
}
} // ~ end of unnamed namespace
Note: The above is a straight copy/paste from the GitHub thread without any modifications so as to not tamper with the information.
#mixin placeholder(#color: #333333) {
&::-webkit-input-placeholder { color: #color; }
}
input {
#include placeholder();
}
.placeholder {
margin-top: 20px;
}
that should work.
So if i understood right, you just want to add 20px on top of the placeholder ? Add padding-top to input instead.
input {
padding-top: 20px;
}

Resources