SASS - Conditionally include styles based on a variable context - css

I am looking for a way to conditionally include content based on a context. The two output files will pull in the same sass files but just process them differently. I would imagine it to work similarly to the #content mixin just without pulling in all the other styles outside of the mixin at the same time. I just need the body of what is included in the mixin. Does anyone have any ideas how I can achieve this?
It is very similar to what https://github.com/at-import/jacket does but without the compass dependency. I have included an example so you can see what kind of thing I am after:
// _styles.scss
h1 {
color: red;
}
h2 {
color: green;
}
#include critical {
.someModule {
background-color: red;
height: 50px;
}
}
These would then be imported into two separate stylesheets like so
// output.scss
#import "styles";
// critical.scss
#import "styles";
But when the SASS compiles you would end up with:
// output.css
h1 {
color: red;
}
h2 {
color: green;
}
// critical.css
.someModule {
background-color: red;
height: 50px;
}
Instead of output.css and critical.css both including the content:
// output.css and critical.css
h1 {
color: red;
}
h2 {
color: green;
}
.someModule {
background-color: red;
height: 50px;
}

Related

How to filter or extract specific CSS ruleset from a .css file and put it in a separate file

Is it possible to extract or filter some specific CSS ruleset from a .css file using webpack (using plugin perhaps) or nodejs, and put it in a separate file (fs node)? If yes how?
e.g.
I want to extract .my_class1 ruleset from all.css and put it in separate file extracted.css
Before Extraction
/* all.css */
.my_class1 {
color: red;
background: red;
}
.my_class2 {
color: green;
background: green;
}
.my_class3 {
color: blue;
background: blue;
}
After Extraction
/* all.css */
.my_class2 {
color: green;
background: green;
}
.my_class3 {
color: blue;
background: blue;
}
/* extracted.css */
.my_class1 {
color: red;
background: red;
}

Merging selector #extend issue

I have a problem about "#extend" directive in SCSS.
.header {
.introduction-group {
text-align: center;
color: $white;
width: 70%;
}
.about {
&__description-group {
#extend .introduction-group;
This code block does not work. However,
.header {
&__introduction-group {
text-align: center;
color: $white;
width: 70%;
}
.about {
&__description-group {
#extend .header__introduction-group;
Second one works. Why?
Thank you.
As mentioned here nested classes won't be applied with #extend. Your second code block targets the specified class including the parent prefix. The first code block doesn't, it only targets the nested class.
I made a small codepen demo to illustrate the problem in a simple way. Make sure you checkout the Sass docs for a more comprehensive explanation!
<h1 class="wrong">Test style gone wrong</h1>
<h1 class="right">Test style gone right</h1>
.test {
.nested {
color: red;
}
&-nested {
color: red;
}
}
.wrong {
#extend .test;
#extend .nested;
}
.right {
#extend .test-nested;
}

CSS: Can you refer to a class within a class?

Let's say I have this class:
.dark-theme {
background-color: black;
}
Can I refer to it within my css file? Something like ...
.some-class {
dark-theme;
padding: 5px;
}
a {
dark-theme;
color: white;
}
I have two solutions to accomplish this.
Solution 1:
Use css variables.
(Not really doing what you asked for but good to know if you're not using any preprocessors)
:root {
--color-bg-dark: black;
}
.some-class {
background-color: var(--color-bg-dark);
}
Solution 2:
Use sass which is a css preprocessor and put your reusable rules in a mixin.
#mixin applyDarkTheme {
background-color: black;
color: white;
// Some other rules
}
.some-class {
#include applyDarkTheme;
}

Why does SASS modify chained selectors of the same name when using extend?

Given the following HTML / SASS code:
<div class="a">hello</div>
%color {
color: blue;
}
.a {
color: red;
}
.a.a {
#extend %color;
}
I was expecting the resulting color to be blue (due to the more specific .a.a selector1) with output something like this:
.a.a {
color: blue;
}
.a {
color: red;
}
But actually, the resulting color is red, with SASS output:
.a {
color: blue;
}
.a {
color: red;
}
I find this quite counter-intuitive!
Why does SASS refactor my .a.a selector to .a?
Just in case you don't believe me, here's a codepen demo (click view compiled css to see the CSS output)
NOTE:
This 'refactoring' of the selector only occurs to the declarations within the extend.
So in the following SASS:
%color {
color: blue;
}
.a.a {
#extend %color;
position: relative;
}
The output is:
.a {
color: blue;
}
.a.a {
position: relative;
}
(Codepen demo)
1See the spec:
Note: Repeated occurrences of the same simple selector are allowed and
do increase specificity.
By the looks of it, the result depends on the parsing engine. If you use DartSass v1.6.2 (default on sassmeister.com), it outputs your expected result:
.a.a {
color: blue;
}
.a {
color: red;
}
Check on sassmeister.com (you can also switch parsing engines there).
LibSass v3.5.2 creates the result you complained about:
.a {
color: blue;
}
.a {
color: red;
}

Call a CSS rule in the statement of another CSS rule?

Can I call a rule in the statement of another rule if CSS?. Something like this:
.myFirstRule
{
color: white;
}
.mySecondRule
{
width: 1000px;
myFirstRule;
}
Thank you.
Sorry about my english
In CSS, no you cannot. You can, however, apply styles to more than one selector at a time, such as:
.myFirstRule, .mySecondRule { color: white; }
Make sure each selector is separated with a comma, and you're good to go.
You can't do this in plain CSS but there are two solutions to your problem:
One: Use multiple selectors
<div class="myFirstRule mySecondRule"></div>
Two: Use SASS (or LESS, I suppose)
.myFirstRule {
color: white;
}
.mySecondRule {
width: 1000px;
.myFirstRule;
}
Alternatively, still with SASS, you could also do this with a mixin:
// Define here
#mixin reusableRule {
color: white;
}
.myFirstRule {
#include reusableRule;
}
.mySecondRule {
width: 1000px;
#include reusableRule;
}
No, you can't do that in pure CSS.. You can use a comma or , to apply a property to multiple selectors
Try this:
.myFirstRule, .mySecondRule {
color:white;
}
.mySecondRule
{
width: 1000px;
}
This is not possible with normal CSS, but you could try using SASS or LESS instead, which both compile to CSS. They allow this behavior through "mixins".
For example in LESS you could do:
.myFirstRule
{
color: white;
}
.mySecondRule
{
width: 1000px;
.myFirstRule;
}
which would generate CSS:
.myFirstRule
{
color: white;
}
.mySecondRule
{
width: 1000px;
color: white;
}

Resources