I would like to use the "&" parent selector in LESS in combination with a nested #import statement to override variable definitions within a specific scope. Consider the following files
style.less:
#import 'component-variables.less';
#import (multiple) 'component.less';
.#{contrastWrapperClass}, .#{contrastWrapperClass}&{
#componentBackgroundColor:#00ff00;
#import (multiple) 'component.less';
}
component-variables.less:
#contrastWrapperClass: componentContrast;
#componentBackgroundColor: #ff0000;
component.less:
.component {
background-color: #componentBackgroundColor;
}
I would expect this to compile to
.component {
background-color:#ff0000;
}
.componentContrast .component,
.componentContrast.component {
background-color:#00ff000;
}
it actually compiles to:
.component {
background-color:#ff0000;
}
.componentContrast .component,
.componentContrast .component {
background-color:#00ff000;
}
In this example, the goal would be to switch the background-color for any .component element that also has the "componentContrast" class or is a child of an element with the "componentContrast" class.
Related
How would I nest classes like this in SCSS using #import?
.example.test {
color: red;
}
This can be done in SCSS without the use of #import like this:
.example {
&.test {
color: red;
}
}
But how would I do it using #import? Let's say we have a file called rules.scss with the following content:
.test {
color: red;
}
If I were to do
.example {
#import 'rules.scss';
}
Would output
.example .test {
color: red;
}
How would I #import rules.scss with the classes nested together, for example, the follow CSS:
.example.test {
color: red;
}
EDIT per your edit:
first rename the file rules.scss to _rules.scss (note the leading underscore)
Then...
.example {
#import "rules";
}
Here is the SASS/SCSS #import documentation:
Please be aware that #import is in the process of being removed:
The Sass team discourages the continued use of the #import rule. Sass
will gradually phase it out over the next few years, and eventually
remove it from the language entirely. Prefer the #use rule instead.
(Note that only Dart Sass currently supports #use. Users of other
implementations must use the #import rule instead.)
I have an Angular project with different components. I have a base _colors.scss that contains all of my color variables. These colors are broken up as "themes". However, the color variable does not take effect if the variable is called from within a child element. Is there a way to make sure the variable is accessible to all of the nested classes within the parent theme class?
My _colors.scss file :
.brand-one { $color-primary: red }
.brand-two { $color-primary: blue }
.brand-three { $color-primary: green }
My Angular component's scss file:
#import '../assets/scss/colors';
.brand-one {
.header{
background: $color-primary;
}
}
brand-two {
.header {
background: $color-primary;
}
brand-three {
.header {
background: $color-primary;
}
But this is is not working. Is there any special selector like the ~ I can use perhaps?
I don't think you should declare variables inside a class?
colours.scss
$color-brand-one: red;
Component
#import '../assets/scss/colors';
.brand-one {
.header{
background: $color-brand-one;
}
}
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;
}
In Less, I can write:
.outer {
.inner {
color: red;
}
}
.test {
.outer .inner;
}
But when I write:
.outer {
&-inner {
color: red;
}
}
.test {
.outer-inner;
}
When I remove the .test, the .outer-inner output properly, but when I add it back, the compiler says
.outer-inner is undefined.
Is there anyway to re-use the styles of .outer-inner?
Calling a mixin whose selector is formed by concatenation is currently not possible with Less. However the same is possible for selectors formed at compilation time using interpolation (also referred to as dynamically formed selectors).
The below (interpolated/dynamically formed selector) would work fine.
#selector: .box;
#{selector}{
color: red;
.child{
color:blue;
}
}
.demo{
.box; /* will create both parent & child */
}
.container{
&.box{
background: black;
}
}
.demo2{
.container.box;
}
whereas, the following example will not work.
.container{
&-box{
color: blue;
}
}
.demo2{
.container-box; /* this will not work */
}
Currently, one work-around to the scenario in question is to create two separate Less files.
In the first file (test.less) add the below code and compile it into a CSS file.
.outer {
&-inner {
color: red;
}
}
In the second file, import the CSS created from the first file with the (less) directive and then call/re-use the mixin.
#import (less) "test.css";
.test {
.outer-inner;
}
Note: As mentioned in comments by seven-phases-max, this issue is similar to this item. However both these issues are not the same as extend will not work with both interpolated selector (dynamically formed) and concatenated selector.
Option 2: Another option would be to write a dummy mixin or a separate detached ruleset with common properties and make use of it like below.
#dummy: {color: red}; // detached ruleset
.outer{
&-inner{
#dummy();
}
}
.test{
#dummy();
}
or
.dummy() {color: blue}; // dummy mixin and would produce no extra selector in output as it has parentheses.
.outer{
&-inner{
.dummy;
}
}
.test{
.dummy;
}
Is there a way to write this css:
div.some-class{
...
}
span.some-class{
...
}
as something like this using scss?
.some-class{
&div{
...
}
&span{
...
}
}
I tried the above, but it returns an error.
I know there's a real desire to have your code grouped together in nice neat little blocks like that, but it just isn't possible. The error you get when you compile the code is quite clear:
>>> Change detected at 14:46:18 to: test.scss
error sass/test.scss (Line 2: Invalid CSS after " &": expected "{", was "div{"
"div" may only be used at the beginning of a compound selector.)
Of course, if you reverse it so that it is div&, then you get this error:
>>> Change detected at 14:48:01 to: test.scss
error sass/test.scss (Line 2: Invalid CSS after " div": expected "{", was "&{"
"&" may only be used at the beginning of a compound selector.)
Your only option is to not nest at all.
.some-class {
...
}
div.some-class {
...
}
span.some-class {
...
}
It depends what you're trying to do.
The example you show will be interpreted as .some-classdiv and .some-classspan which will result in a compilation error. Essentially the ampersand represents the parent selector.
If div.some-class and span.some-class don't share the same styles, the first block you have is still the most effective way to write it.
If they share some of the same styles, you could write a mixin.
// Shared Styles
#mixin some-class {
background: #f00;
color: #fff;
}
div.some-class {
#include some-class;
... other styles
}
span.some-class {
#include some-class;
... other styles
}
You could also #extend an existing class:
.some-class {
background: #f00;
color: #fff;
}
div.some-class {
#extend .some-class;
... other styles
}
span.some-class {
#extend .some-class;
... other styles
}
If you extend an existing class, the class must be a root class included in the file (i.e. it can't be a nested class).
That said, since both elements have the class some-class, you could just as easily define regular CSS:
.some-class {
background: #f00;
color: #fff;
}
div.some-class {
... other styles
}
span.some-class {
... other styles
}