How do I work with SASS' new module system when it comes to variables? - sass

I am working on a project that consists of multiple web portals based on a different target audience. The portals share the same HTML "components" and differ mostly in color, but additional style difference may exist.
Until now, I've used the following folder structure:
sass
├── default
│ ├── components
│ │ └── component-1.scss
│ └───_variables.scss
├── portal-a
│ ├── components
│ │ └── component-1.scss (portal-a specific code)
│ ├── _variables.scss
│ └── app.scss
└── portal-b
├── _variables.scss
└── app.scss
default contains the default styles for all components as well as global variables.
portal-* contains additional portal-specific styling for a component (if any) as well as portal-specific variables like colors, fonts, spacing, etc.
Each portal-* also contains an app.scss that serves as entry point and it's what the final CSS is built from. It contains the following:
#import "../default/_variables";
#import "./_variables";
#import "../default/components/**/*.scss";
#import "./components/**/*.scss";
So basically it includes the default variables first, then the portal-specific variables overwriting the default values, then all scss files from default and finally the portal-specific component stylesheets.
This whole setup works, but I would like to switch to SASS' new component model with #use and #forward, but I am totally lost.
So let's say I have my sass/default/_variables.scss:
$font-size: 16px !default;
$text-color: #000000 !default;
$padding-base: 25px !default;
Then I have sass/portal-a/_variables.scss where I only want to redefine the text color:
$text-color: #ff0000;
I assume I also have to forward the default variables, so sass/portal-a/_variables.scss should eventually contain:
#forward "../default/_variables";
$text-color: #ff0000;
Right? (Please correct me if I am wrong.)
Same deal for portal-b, but with a different value, sass/portal-b/_variables.scss:
#forward "../default/_variables";
$text-color: #0000ff;
So now that I have variables set-up, I want to write the default stylesheet of a component. I create a file sass/default/components/component-1.scss.
[data-component="component-1"] {
font-size: how do I access the font-size variable?;
color: how do I access the text-color variable?;
padding: 2 * how do I access the padding-base variable?;
}
Then I create my entry points from which the final CSS files are going to be built.
sass/portal-a/app.scss and sass/portal-b/app.scss:
#use "_variables"
#use "../default/components/component-1";
That first #use "_variables" should theoretically load the default variables, overwrite the default value for the text color, but then how do I pass everything so component-1.scss can access it?

Related

#use shows undefined variable constantly

I am migrating from libsass to dartscss, so moving from #import to #use. I have around 20 sites and the way I have my sites is to have one scss folder with all of my scss files and then have a site config per site that uses variables to override the default colours.
My site structure
scss/
├─ import.scss
├─ base/
│ ├─ _reset.scss
site1/
├─ scss/
│ ├─ settigns/
│ │ ├─ _config.scss
│ import.scss
In site1/scss/settings/_config.scss I have the following code:
$bgc: red;
And in my site1/scss/import.scss I have:
#use "settings/config" as *;
#use "../../scss/import.scss";
And finally in ../../scss/import.scss I have a simple test call to see if it works.
body {
background-color: $bgc;
}
When I view my site I get undefined variable and $bgc doesn't render. I would like to keep the structure I had before since I have many sites that share the same scss folder and all worked fine before when I used #import.

Do I need to create a "custom.scss" file when creating a new bootstrap project?

I'm following a Kevin Powell bootstrap tutorial and he copies a custom.scss file into a separate folder, however I can't find that file to copy, not sure if it's because I'm using an updated version of bootstrap.
the bootstrap documentation says after install of bootstrap via npm i should have a folder structure like this:
your-project/
├── scss
│ └── custom.scss
└── node_modules/
└── bootstrap
├── js
└── scss
However, upon installing bootstrap into folder it's like this:
your-project/
└── node_modules/
└── bootstrap
├── js
└── scss
No scss folder apart from in bootstrap folder.
Do I need to create a "custom.scss" file ...?
No you don't need to do that, as you could compile your css directly from the bootstrap source files. However, I would only consider this method if you plan use bootstrap out-of-the-box with no customizations, now or in the future. If you choose not to create this file, then you should probably just use a CDN instead.
Should you create a "custom.scss" file?
Yes, this is where you modify bootstrap variables, or extend its components, etc.. You can also choose to import all of bootstrap, or just the parts you need in this file.
The documentation goes over what should be in that file. But you can get started with just the following:
// Custom.scss
// Option A: Include all of Bootstrap
#import "node_modules/bootstrap/scss/bootstrap";

How to override materializecss sass variables in vue?

I'd like to change variables in materialize _variables.scss e.g.
$primary-color: color("materialize-red", "lighten-2") !default;
$primary-color-light: lighten($primary-color, 15%) !default;
$primary-color-dark: darken($primary-color, 15%) !default;
/*...*/
In my Vue 2 main.js I include materialize style like this
require('materialize-css/sass/materialize.scss');
Because of !default I guess I need to include my _variables.scss before including materialize, but I don't know how.
So what's the proper way to set my own variables e.g. $primary-color: color("blue", "lighten-2") (I want to use predefined palette from materialize _colors.scss)?
EDIT 1: I installed vue2 with vue-cli
EDIT 2:
Folder structure:
├── build/
├── config/
├── dist/
├── node_modules/
│ ├── materialize-css
├── src/
│ ├── components
│ ├── router
│ └── main.js
├── package.json
└── index.html
Before changing any default settings in materialized css; first, you need to import the component for which you want to change the settings for. After this you can override the default settings and then you should import materialize. For example if you want to change default color then create a file for example app.scss then write following code:
//please put the paths as per yours project directory structure
#import "materialize-css/sass/components/color";
$primary-color: color("blue", "lighten-2") !default;
#import 'materialize-css/sass/materialize'
Note: app.css must be included in your page. As per my example app.css must be in your project root folder i.e. at same level as that of index.html
Now you can load app.scss or app.css in Vue 2 as
require('../app.scss');
Visit official materialized github repo for viewing complete source.
In matrialize 1.0.0 however,
follow these guildlines to override materialize colors:
Define the value for the variable that you want to override (eg. $primary-color)
Import the materialize.scss library
The definition of the override values must occur before importing the materialize.scss, that means that you can not use the matrial functions such as color()
Example:
// main.scss - the order of the imports is important !!!
#import './_colors';
#import 'materialize-css/sass/materialize.scss';
// _colors.scss
$primary-color: #03a9f4; //light-blue

Load common.sass style on top of a Reacts components

I'm building a react application with SASS for the styles and serving it with webpack-dev-server, a couple of components and some extract of the structure look like that:
├── App.js
├── components
│   ├── Layout.jsx
│   ├── Layout.scss
│   ├── header
│   ├── pages
│   └── footer
└── css
   ├── _vendors.scss
   ├── _variables.scss
   ├── _mixins.scss
   └── utils.scss
Inside main.scss, I have all the #imports, also inside the vendors I have the imports in node_modules dependencies, etc...
Per each component in react have his own scss file.
But, I want the main.scss loaded in the Layout.jsx and use the mixins or imports or placeholder classes inside the scss file per component.
I was trying playing with css-loader and style-loader with includePath's and nothing successful.
It's this possible? It's related on the -loaders of webpack?
ps: Isn't viable have an .html file, this is a library of components.
A good way I found to keep track of styles for various react components is to have a style file for each corresponding component. So Header.react.jsx would have a corresponding Header.sass. Then you just include the style file on top of the react component, like so (using the ES6 syntax):
import './Header.sass';
For this to work with webpack, you need the appropriate loaders:
loaders: [
{
test: /\.sass/,
loader: 'style!css!autoprefixer!sass'
}
]
This is nice for development, because the styles are loaded in javascript and get updated automatically on any change if you're using the hot loader, but in production, you'd want to separate out the css file with all the styles. You can do this with a separate webpack config file for production, which can look something like this:
plugins: [
new ExtractTextPlugin('bundle.css', { allChunks: false })
],
loaders: [
{
test: /\.scss/,
loader: ExtractTextPlugin.extract(
'style-loader',
'css!autoprefixer!sass'
)
}
]
When doing things this way, it's good to include a sass config file and a mixin file, for the variables or mixins you use globally (with the regular sass #import). It's important not to define any actual styles in the files you import, since the styles would be included into all files you include it in, resulting in loads of duplication.
This is good for component libraries (as you put it), since webpack will only include the react components you use in your application, and in turn, it will only pull in the sass files you use.
I found this approach very handy, and used it in a smaller application here. Take a look if I haven't explained it well enough.

How to import scss file in compass only if it exists?

I need to have special scss file that is different for every installation of the project, so I don't want to include it in git archive. But everything should work even if this file doesn't exist.
Is there any way to #import scss file only if it exists, ignoring file not found error?
You'll need to make use of the "import-path" option to do this, where the path you're importing contains the fallback files you want to import (in our case, we want an empty file).
Option 1: Vanilla Sass
File structure
├── fallback
├── _example.scss // <-- our blank file
├── _example.scss // <-- the file for the user to customize (optional)
├── style.scss
In style.scss:
#import "example";
/* the rest of our styles */
When you run your sass command, you would write it like this:
sass --watch ./css:./sass --load-path ./sass/fallback
Note that the fallback directory does not have to be inside your sass directory, it be anywhere on the filesystem you like.
See also: How does SCSS locate partials?
Option 2: Compass Extension
You may find that creating a Compass extension is a little more convenient if you're using this technique in multiple projects. It will automatically setup the load-path for you. You can learn more about creating extensions here: http://compass-style.org/help/tutorials/extensions/
Maybe with sass-globbing and a naming convention for optional files follow a specific order of loading.
Consider the following tree:
stackoverflow-14975341/
├── .gitignore
├── config.rb
├── css/
│   └── screen.css
└── sass/
├── optionals/
│   ├── .gitkeep
│   ├── _01_style.scss
│   └── _03_style.scss
└── screen.scss
with these files:
# config.rb
require 'sass-globbing'
sass_dir = 'sass'
css_dir = 'css'
relative_assets = true
and
// sass/screen.scss
#import "optionals/*";
and
// sass/optionals/_01_style.scss
.optional1 {
background-color: red;
}
and
// sass/optionals/_03_style.scss
.optional3 {
background-color: green;
}
and, for in the .gitignore:
sass/optional/*
Finally, to keep the optional folder, create an empty file named .gitkeep (the file name is not important).
When you compile the stylesheet, Compass generates the screen.css even if the file _02_style.scss is missing.
// css/screen.css
/* line 1, ../sass/optionals/_01_style.scss */
.optional1 {
background-color: red;
}
/* line 1, ../sass/optionals/_03_style.scss */
.optional3 {
background-color: green;
}
It is certainly possible to improve the system based on import additional paths.

Resources