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
}
Related
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.
So,
I have appended a home class to body like so:
document.body.classList.add("home")
I want to select appContainer a child element of body class by doing
html body.home #appContainer { ..... }
This works without CSS Modules but was wondering how I can do it with CSS modules. Thanks
You need to use wrap the class that you want to be global into :global(). If your selector uses an element you must write it directly after the element with no space in between, like element:global(.class) which translates into element.class.
Therefore, in your case html body:global(.home) #appContainer is the answer.
For anyone else that comes across this issue, I am using postcss-preset-env and I had to do this:
Worked ✅
.toolTipTest :global .rc-tooltip-arrow {
color: blue;
}
This did not work ❌
.toolTipTest:global(.rc-tooltip-arrow) {
color: blue;
}
And neither did this ❌
.toolTipTest:global(.rc-tooltip-arrow) {
color: blue;
}
// Neither Did this
.toolTipTest {
&:global(.rc-tooltip-arrow) {
color: blue;
}
}
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;
}
Whenever I try to compile Sass code to CSS with either the terminal or the program Koala I get this error message:
Error: Invalid CSS after "body ": expected selector, was "{"
on line 5 of style.sass
Use --trace for backtrace
Here's the piece of code the error seems to be referring to:
body {
background {
color: $background-color
}
}
How can I fix my code to make it compile correctly?
The way your selector reads is that it is looking for the <body> element, and then a <background> element (which isn't a thing that exists in HTML, to my knowledge), and then you are setting the text inside that element to the color in your var $background-color. I think either one of two things:
Either you meant for background to be a class or id, like .background, in which case your code becomes:
body {
.background {
color: $background-color;
}
}
Or, more likely, you are very tired and just got your wires crossed, and mean to be setting the background-color property like this:
body {
background-color: $background-color;
}
Please note that you were also missing an ending semi-colon, which I added.
You cloud try adding a colon after background.
body {
background: {
color: $background-color;
}
}
Sass, unlike Scss, uses indentation instead of curly braces.
body {
background {
color: $background-color;
}
}
becomes
body
background
color: $background-color
Though, I'm quite sure you mean to have background as a property instead of a selector.
body
background-color: $background-color
background must be class name or id or simply background css property.
body {
.background {
color: $background-color;
}
}
body {
#background {
color: $background-color;
}
}
body {
background : $background-color;
}
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 :)