Conditionally import partials - Compass [duplicate] - sass

This question already has answers here:
How to import scss file in compass only if it exists?
(2 answers)
Closed 7 years ago.
I'm trying to conditionally import a sass partial if it exists to override a set of default styling variables. I'm looking for a means to accomplish the following, given that #import directives cannot be nested:
#if 'partials/theme'{
#import 'partials/theme';
}
Import directives may not be used within control directives or mixins, so what is the proper approach for referencing a partial that may or may not exist?

You can't explicitly use the import directive inside control directives.
"It’s not possible to nest #import within mixins or control directives." - Sass Reference
error sass/screen.scss (Line 9: Import directives may not be used within control directives or mixins.)
If you really need this there are sort of ways of getting around it with the #content directive. But it really depends on what your task really boils down to.
One example which would produce multiple .css file outputs for each theme, you might approach like this:
_config.scss
$theme-a: false !default;
// add content only to the IE stylesheet
#mixin theme-a {
#if ($theme-a == true) {
#content;
}
}
_module.scss
.widget {
#include theme-a {
background: red;
}
}
all.theme-a.scss
#charset "UTF-8";
$theme-a: true;
#import "all";
In another case, to produce multiple theme options in a single .css output you might have to rely on complex looping like this:
//
// Category theme settings
// ------------------------------------------
// store config in an associated array so we can loop through
// and correctly assign values
//
// Use this like this:
// Note - The repeated loop cannot be abstracted to a mixin becuase
// sass wont yet allow us to pass arguments to the #content directive
// Place the loop inside a selector
//
// .el {
// #each $theme in $category-config {
// $class: nth($theme, 1);
// $color-prop: nth($theme, 2);
//
// .#{$class} & {
// border: 1px solid $color-prop;
// }
// }
// }
//
$category-config:
'page-news-opinion' $color-quaternary,
'page-advertising' #e54028,
'page-newspaper-media' $color-secondary,
'page-audience-insights' $color-tertiary,
;
$news-opinion-args: nth($category-config, 1);
$news-opinion-class: nth($news-opinion-args, 1);
$news-opinion-color: nth($news-opinion-args, 2);
$advertising-args: nth($category-config, 2);
$advertising-class: nth($advertising-args, 1);
$advertising-color: nth($advertising-args, 2);
$news-media-args: nth($category-config, 3);
$news-media-class: nth($news-media-args, 1);
$news-media-color: nth($news-media-args, 2);
$audience-args: nth($category-config, 4);
$audience-class: nth($audience-args, 1);
$audience-color: nth($audience-args, 2);

In retrospect, the best solution you would probably use JavaScript to conditionally load in theme assets or modules.

Related

SASS add ampersand to mixin output

I'm trying to use an Angular Material mixin with a custom scope. I want to generate my theme like this:
.material-green-theme.mat-mdc-<selector> {
// content
}
However my compiled CSS turns out to be this:
.material-green-theme .mat-mdc-<selector> {
// content
}
This is my code:
.material-green-theme {
#include mat.slide-toggle-color($green-theme);
}
I've tried adding #at-root among other things to make it connect however I can't get it work; nor can I modify the mixin since it's from the Angular Material package. Is there a way for me to somehow make this work?

Sass, create css class dynamic depending on data

I have this class:
.currency-flag-clp:before {
background-image: url('~currency-flags/dist/square-flags/clp.svg');
}
I want to add that class dynamically to an html element, so I need to add a class like:
.currency-flag-XXXXX:before {
background-image: url('~currency-flags/dist/square-flags/XXXXX.svg');
}
Is there a way with sass to do that? I don't want to define 270 class per value, I just want to create the class depending on my data.
As you want to set an individual class on the element it seems you have access to your currency data when building the page. In that case there may be an alternative more simple approach without SASS.
(1) ALTERNATIVE (NON SASS) SOLUTION - maybe a simpler approach
(a) Write a css variable 'actual-currency-flag-url' for your actual flag-image to a style block in the head of your file based on the actual user setting/currency.
(b) Then use that variable to build the url-path in css.
// add to <head> of page:
// based on your data maybe you can do it by php
// note: don't use slashes when building url(...)
<style>
:root {
--actual-currency-url: url(url-path/flag-[actualCurrency].jpg);
}
</style>
// change class off html element
// from <div class="currency-flag-XXXXX"> to:
<div class="currency-flag">
// now you can do in your separate stylesheet file:
.currency-flag:before {
background-image: var(--actual-currency-url);
}
Writing the style direct to the element is less elegant but works as well of course.
(2) POSSIBLE SASS SOLUTION - building 270 classes in SASS using a mixin
(a) Based on your data: generate a simple suffix-list and use it to build a SASS map with the suffixes of your flags.
(b) Use #each to build all 270 classes at once
// example code in SASS:
$flag-suffixes: (
USD,
AUD,
EUR,
//...
);
#each $suffix in $flag-suffixes {
.currency-flag-#{$suffix}:before {
background-image: url('~currency-flags/dist/square-flags/#{$suffix}.svg');
}
}

SCSS check for CSS custom var property

How do I conditionally apply a mixin if --my-custom-var is present? For example:
.test {
#if var(--my-custom-var) {
#include someExampleMixin()
}
#if var(--another-custom-var) {
#include someExampleMixin()
}
}
I don't care what the value of the --my-custom-var is but just want to check its existence.
Sass has introduced the variable-exists() function already in alpha. Be aware that Sass can only check for Sass variables. Therefor if you'd really want to use CSS variables you need to define the content of your CSS variable inside a Sass variable, for example $sassVar: /* content */; --cssVar: $sassVar;. Be also aware that the #if statement must be inside a #mixin or a #function to work. I posted a working example below, but here is aslo my Codepen Example since Stack doesn't compile Sass.
Note:
I used "null" inside my $var which basically expresses that there
is no content within this variable, you can pass whatever you
want it won't affect the outcome unless you remove or change the actual
variable.
You can use multiple #if statements which I commented out in this example, but there should always follow an #else statement.
$var: null;
:root {
--someVar: $var;
}
#mixin checkForVariable {
#if variable-exists(var){
body {
background-color: red;
}
}
// #if variable-exists() {
// ...
// }
// #if variable-exists() {
// ...
// }
#else {
body {
background-color: blue;
}
}
}
#include checkForVariable;

CSS Modules, Composition in nested class

I am working on a project where there is a main style.scss file for a number of components. I want to restructure the code so as every component has its own folder (index.js, styles.scss). There is a nested class that is using a class from another component and now that I have to separate all the styles, this part is broken. I can't use composition since it is a nested class. What other approaches can I take?
The code looks like this:
// Component A styless.scss
.component-a-class {
}
// Component B styless.scss
.component-b-class{
.component-a-class {
}
}
Use Sass's #import directive to import the external classes. Your code would become something like this:
// ComponentA/styless.scss
.component-a-class {
...
}
// ComponentB/styless.scss
.component-b-class{
#import "../ComponentA/styless.scss"
}
This will inject .component-a-class into the .component-b-class as a nested rule.
Edit: To import a style and also be able to modify one of its properties' values, you have to make use of Sass mixins:
// ComponentA/styless.scss
#mixin component-a-class($width: 100) {
.component-a-class {
width: $width + px;
}
}
#include component-a-class();
// ComponentB/styless.scss
#import "../ComponentA/style.scss";
.component-b-class{
#include component-a-class(500);
}
This will get you what you want, though it isn't ideal. The resulting compiled ComponentB/styless.css file will include everything written in ComponentA/styless.scss because the #import directive is an "all-or-nothing" feature (there is no selective import). The result would look like this:
// ComponentB/styless.css (compiled)
.component-a-class {
width: 100px;
}
.component-b-class .component-a-class {
width: 500px;
}

How do I share variables between different imported files?

I want to use SASS in a modular way. In the code segment below you can see a way I consider organizing some of the layouts of a page.
What I have in mind is the external variables in languages like C.
// file: some_page.scss
//
// I want some variables from the fonts, colors partials
// to be visible to the buttons partial
// Is it possible?
// error: _buttons.scss (Line X: Undefined variable: "$color_blue")
#import "colors"
#import "fonts"
#import "buttons"
// in file: _colors.scss
$color_blue: blue;
// in file: _buttons.scss
.button {
background-color: $color_blue;
}
Yes, that's how it works.
As long as _colors.scss is imported before the other files.
You can check out the port of Twitter Bootstrap to Sass here: https://github.com/thomas-mcdonald/bootstrap-sass it uses variables in a similar fashion.
You need to add a ; at the end of the #import line.

Resources