Can you target/ modify existing classes with SCSS Modules? - sass

I'm converting existing SCSS to SCSS Modules in a React app, and I'm having issues targeting classes specified by an external library (react-datepicker in this case).
Using modules changes the classname to something like ._DateField-module__react-datepicker__fWQOd, but is there any way of targeting the DatePicker styles or is this not possible using modules?
Previous Code
DateField.tsx is just a wrapper for DatePicker:
<div className='date-field'>
<DatePicker/>
</div>
DateField.scss successfully overrides existing styles inside the DatePicker component:
.date-field {
...
...
& .react-datepicker {
background-color: $dark-grey;
color: $white;
}
}

You can use :global to switch to global scope for the respective selector.
.date-field {
...
...
:global .react-datepicker {
background-color: $dark-grey;
color: $white;
}
}
You don't need the & there.
Here's a working CodeSandbox.

Related

How to render SCSS while keeping nesting?

I am creating a SCSS -> HTML plugin and need to first render SCSS -> CSS while keeping the nesting so I can then parse with PostCSS to then create an HTML tree with.
I would like to render SCSS like this
// myMixin.scss
#mixin myMixin {
.myMixin {
padding: 1rem;
background: yellow;
}
}
// main.scss
#import 'myMixin.scss';
$blue: #004AAD;
.button {
.text {
color: $blue;
}
#include myMixin;
}
And the output would look like this:
.button {
.text {
color: #004AAD;
}
.myMixin {
padding: 1rem;
background: yellow;
}
}
Basically, I'd like a way to render everything in SCSS while keeping the original nesting. Is it possible? Thanks.
Nesting is specific to SCSS. Also I don't think #import is best practice, use #use instead.
https://sass-lang.com/documentation/at-rules/use
Here is the thing our client(browsers) only support raw CSS and not SCSS, When you use SCSS it compiles down to raw CSS, And CSS doesn't have inbuilt Nesting feature.

next.js and sass and using :global issues

I am using next.js and having an issue with a scss file using "global".
Getting this error:
Syntax error: Selector ":global .Select-control" is not pure (pure selectors must contain at least one local class or id)
.dropdownColor {
:global {
.Select-button {
border-color: $red-hue-4;
}
}
}
and
:global {
.Select-control {
border-radius: 2px;
border-color: $navy;
}
.Select-clear, .Select-arrow {
display: none;
}
}
Do I have to put this in my global scss file? Does the format change?
If you are using css modules as it appears you are, this will work to change the border color of an element with a global class of .Select-button nested inside your dropdownColor module:
.dropdownColor {
:global(.Select-button) {
border-color: $red-hue-4;
}
}
As the error states, :global must be nested inside a local (module) class or id. So while the above works, your second example does not because you have :global as a top-level item. Either nest it inside a local id or class like I have done above, or extract it out to a global stylesheet.

What is the best SASS practice of writing child selector while parent has hover

I have a doubt of writing child selector when I have a hover event in parent.
say I have HTML like this,
<div class="root">
<div class="root__element">
<div class="root__sub-element" />
</div>
</div>
In sass,
.root {
$root: &;
&__element {
&:hover {
#{$root}__sub-element {color: red;} // question comes here, why
// not using .root_sub-
// element?
}
}
}
what I want is hover event happens in root__element, color change in root__sub-element.
Should I use ampersand to keep SASS or I would directly use '.root__sub-element'?
You should Keep SASS.
I noticed you tagged 'bem' in your question.
As per BEM, your block element class to continue with your prefix of last child class. http://getbem.com/naming/
POINT 1:
If you have another element with the same behavior. the hardcoded class .root__sub-element will break. please consider the following sass code with multiple root classes.
SASS Code :
$roots: root, newroot;
#each $r in $roots {
.#{$r}{
$root: &;
&__element {
&:hover {
#{$root}__sub-element {color: red;}
}
}
}
}
POINT 2:
This is very rare or not suggested practice, but suppose in case your root block class .root changed to .newroot. as per bem, your child classes will change with new prefix.
Here, hardcoded class .root__sub-element will break, you need to changes it to all area manually.
Otherwise:
CSS is:
.newroot__element:hover .root__sub-element {
color: red;
}
Expected CSS:
.newroot__element:hover .newroot__sub-element {
color: red;
}

Using irregular CSS in a .scss file

I have some funky formatting which I am using to override a Polymer component. It's the custom variables mixin. Scss does not like it to compile with. Is it possible to set a chunk that doesn't get compiled the sass way? Similar to jekyll raw html tag.
For example
// tag do not compile with sass //
--my-component-custom-mixin: {
background-color: #000;
color: #fff;
};
// tag finish do not compile with sass //
You could use Sass string interpolation (#{'...'}) to escape the CSS mixin:
SELECTOR {
--CSS-VARIABLE-NAME: #{'CSS-VARIABLE-VALUE'};
}
Example:
my-view1 {
--my-component-custom-mixin: #{'{
background-color: #000;
color: #fff;
}'};
}
demo

Iterate over theme-variable files in SCSS

I want to create different css-themes for a WordPress theme by using theme setup files. The setup (simplified) would be as following:
/themes/_theme1.scss
/themes/_theme2.scss
/components/_file1.scss
/components/_file2.scss
/theme.scss
The idea is to enable easy theming by adding a class to the body of the document like .theme-theme1 or .theme-theme2. In the files _theme#.scss I want to define variables like text colour, font sizes and so on. In _file#.scss the actual styles are defined.
My question now is, how to iterate over the theme setup files while filling up the files.scss.
Sample idea, Background colour:
body {
###foreach themefile###
&.theme# {
background-color: $background-color;
}
###/foreach###
}
I know how to do this with only one theme available in the resulting CSS file, but I want to make ALL themes available in the resulting CSS. Feel free to ask more details as I am not sure if I explain me right.
Is there a way to create this stylesheet via some kind of foreach loops through variables in theme files or does it have to be done with extra scss-rules per theme file?
This is somewhat possible using a combo of #import with a #mixin to generate the styles. This method should produce minimal repeated code.
Here's how we'll setup the files.
- scss
- themes
- _theme1.scss
- _theme2.scss
- _theme.scss
- styles.scss
The _ prefix on some of the files prevent them from being compiled into CSS to keep our build nice and clean. Now let's go through the contents of the files:
_theme1.scss
$theme-name: 'theme1';
$primary-color: red;
$primary-font-size: 24px;
_theme2.scss
$theme-name: 'theme2';
$primary-color: blue;
$primary-font-size: 12px;
This is an oversimplified example but should give the basic idea. Each theme file will contain only variables.
_theme.scss
#mixin themestyle() {
body.#{$theme-name} {
p {
color: $primary-color;
font-size: $primary-font-size;
}
.bordered {
border: 3px solid $primary-color;
}
}
}
The themestyle mixin will contain all the styles for each theme, using the variables from the /themes/_theme*.scss files. The body.#{$theme-name} will create a selector like body.theme1 or body.theme2, depending on the current value of the $theme-name variable.
In this demo I'm styling on a p tag but this could easily be extended to all elements/selectors for your site. The important thing to remember is all styles need to be inside the body.#{$theme-name} selector.
Now the final, and least DRY part. The styles.scss file will import each theme file then call the themestyle mixin to generate the styles for each theme.
styles.scss
#import 'themes/theme';
/* Theme 1 Styles */
#import 'themes/theme1';
#include themestyles();
/* Theme 2 Styles */
#import 'themes/theme2';
#include themestyles();
The repeated #import/#include is required because it's not possible to #import within a loop or mixin, or this could be optimized a bit more.
Once styles.scss is compiled the output will be:
/* Theme 1 Styles */
body.theme1 p {
color: red;
font-size: 24px; }
body.theme1 .bordered {
border: 3px solid red; }
/* Theme 2 Styles */
body.theme2 p {
color: blue;
font-size: 12px; }
body.theme2 .bordered {
border: 3px solid blue; }
These themes can now be implemented by adding a class to the body tag, like <body class="theme1"> or <body class="theme1">.
Here's a Cloud9 project showing the setup.

Resources