Globally add selector to all my CSS selector with Webpack (at build time) - sass

I would like to globally append a specific selector to all CSS selector used in my application.
I'm using React and those Webpack loaders post-css, css-loader, sass-loader and extract-text-webpack-plugin.
I don't want to edit all my classname within jsx files. I just want to append this specific selector at build time.
Is there a loader to achieve this? Or any other solution...
What I actually have:
.myClass {
...
&--blue { ... }
}
What I want after Webpack transpilation:
.specificClass .myClass { ... }
.specificClass .myClass--blue { ... }
Thanks
Gautier
PS: The reason I need this feature is to avoid CSS selector collision with the Website I'm integrating my application. I don't wan't to manually edit all my scss files to append the selector.

this should be solvable by in you main sass file:
.specificClass {
#import 'variables';
#import 'fonts';
// ... do more imports
}

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');
}
}

Webpack, sass, Import css with url

I import a css file with a font-face declared in it with a relative URL.
#import '~materialize-css/dist/css/materialize.min';
.register-container {
#extend .row;
}
I use the raw-loader!sass-loader chain because it's an angular component style.
{
test: /\.scss$/,
include: PathHelper.getPathFromRoot('src', 'app', 'modules'),
loader: 'raw!sass'
},
When I do that the content of the materialize file is being copied. And when I load the page it tries to load the fonts from a wrong directory because the relative path is wrong.
The fonts work because I load them with different loaders chain in a different file. The chain is: css!resolve-url!sass?sourceMap
So the fonts are there but the issue is that the content of the css is copied twice and it loads the fonts multiple times from a front path
Can I do something about it? So that the sass loader will know not to copy the css content?
Might Help?
$font-url: unquote("somefile.css");
#if variable-exists(font-url) {
#import url($font-url);
} #else {
#error "sorry no dice";
}
String Functions
unquote($string)
Removes quotes from a string.
- (Sass::Script::Value::String) unquote($string)
Removes quotes from a string. If the string is already unquoted, this will return it unmodified.
Examples:
unquote("foo") => foo
unquote(foo) => foo

Sass - Create custom control directive (like #if or #for)

I'm wondering whether Sass provides a way to create custom control directive which is the "#" command like #if or #for.
I want to make media query syntax looks simpler like:
#below 800px {
...
}
#above 480px {
...
}
Currenly I'm using mixin for this which make the code longer:
#mixin below($size) {
#media only screen and (max-width: $size) { #content; }
}
#include below(800px) {
...
}
So does Sass support this custom control? I can't seem to find solution online.
Note: I don't want to modify the source code.
Thanks
No. Sass does not allow you to create custom control directives. You would have to modify the Sass parser if you wish to do so or continue using mixins as you are currently already doing.

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