importing outside style to scss main page - sass

I have a main.scss file that I want to import colors into from a _colors file.
I have defined a body color in the color file, when I try to import it, I see no changes in the webpage. They are both in the same scss folder but neither #include or #import seem to make a difference. I have tried with and without the underscore in my import statement, both single and double quotes and both import and include keywords. Please tell me what stupid mistake I am making that will rectify this problem as I have researched the problem and think I have been able to copy the examples with no success.
_colors.scss
body {
$background-color: maroon;
}
main.scss
#include 'colors';

Partials are used with #use directive. Then,
_colours.scss
body{
background-color: maroon;
}
style.scss
#use "_colours";
The reuse of code is done through the #mixin directive.
_colours.scss
#mixin body--background{
background-color:maroon;
}
style.scss
#use "_colours.scss" as so;
body{
#include so.body--background;
}
But, if you want to just define just colours use variables instead. Example below,
_colours.scss
$maroon=maroon;
$lightblue=//et cetera.
style.scss
#use "_colours";
body{
background-color:$maroon;
}

If you have a main.scss file which will be the file that gets compiled, and you want to import variables, mixins etc from another partial file, such as _colors.scss. You could do so by loading the members from the partial _colors.scss into main.scss with a #use at-rule. This allows loaded members from the module to be referenced with dot-notation throughout your main.scss stylesheet.
Let's say your _colors.scss file looked like this:
$bodyColor: maroon;
$someOtherColor: #f06;
/* adding a mixin for demo */
#mixin highlight($c, $bg) {
color: $c;
background: $bg;
}
/* some extra styles pertaining to _color.scss */
.some-styles {
color: $someOtherColor;
}
Note: The syntax for #use is #use <url> as <namespace>;.
You could load the variables/mixins etc into main.scss with a #use rule and reference the namespace throughout your program:
#use "./colors" as c;
body {
background-color: c.$bodyColor;
}
.highlighted {
#include c.highlight(#fff, #f06);
}
or without defining a namespace like:
#use "./colors" as *;
body {
background-color: $bodyColor;
}
.highlighted {
#include highlight(#fff, #f06);
}
You certainly can include a body {} declaration inside _colors.scss and load it the same way as discussed above, but I think your wanting to place the body style block inside main.scss and simply reference loaded variables from _color.scss. If you have a directory of many partials and want to load them into main.scss without writing separate #use rules for each load, then introduce a index file with #forward rules to load an entiry directory of partials into main.scss using a single #use rule.

Related

How to migrate cases that make use of #content and #import with #content and #forward in SASS

I'm migrating a codebase from using #import to #use and #forward. Most of it is okay but I'm unsure what to do in a case where #import is used with #content.
Considering the following mixing that the only goal is to wrap styles in a class:
#mixin alternative-styles {
.parent-class {
#content;
}
}
The mixin is then used with #import to wrap all those styles in a .parent-class:
#include alternative-styles {
#import 'components';
}
I assumed replacing it with a #forward wouldn't work but have it a try anyway in this way:
#include alternative-styles {
#forward 'components';
}
This threw the following error:
Error: This at-rule is not allowed here.
╷
22 │ #forward 'components';
│ ^^^^^^^^^^^^^^^^^^^^^
╵
I have found that the sass-migration tool solves the issue this way:
#use 'sass:meta';
#use 'mixins';
#include mixins.alternative-styles {
#include meta.load-css('components');
}
The components.scss files has multiple #forward statements to keep all component references in one place like this:
// components.scss
#forward 'components/buttons';
#forward 'components/text';
After the sass compiler runs it results in an empty block:
.parent-class {
}
Is there any way to achieve wrapping a bunch of styles in a class that supports the #use and #forward rules?
I found that the meta.load-css mixin actually does work after creating a separate prototype with the same structure:
#use 'sass:meta';
#use 'mixins';
#include mixins.alternative-styles {
#include meta.load-css('components');
}
More details on using meta.load-css for this case can be found in this GitHub issue: https://github.com/sass/sass/issues/3095
The reason I got the empty .parent-class block was because I was making use of asynchronous compiling with the gulp-sass package. Replacing sass().on(...) with sass.sync().on(...) solved the issue.

sass : import only a part

I have 2 scss files, I want to use one mixin from the first into the second, but without importing the rest of the file ( I have a few url() who don't react well into this file
someDir/F1.scss
#mixin somemixin($width, $height) {
}
.someClass {
#include somemixin(17px, 10px);
background-image: url('./someUrl');
}
anotherDir/anotherAnotherDir/F2.scss
#import '../../someDir/F1';
.someOtherClass {
#include somemixin(17px, 10px);
background-image: url('./someOtherUrl');
}
How can I do it?
You can instead try #use module instead of #import and make only mixins public or decide on what you want to make public from file 1.
Check it here
https://sass-lang.com/documentation/at-rules/use

Why does my code duplicate the css of a file?

In Sass I have some components (navbar, footer) and some #mixins (fonts) and a function to control the fonts.
I #import the location of the fonts and do #include in the function of the fonts, in this function I just choose the font I want to use.
The problem is that as I separated as "partials" the components (navbar and footer) they have the same sources and I gave #import in those sources in each .scss.
And with that it generates duplicate code in my generated .scss file. I'd like to know what good practices are for this and if I'm doing it right and how do I avoid these duplicates in .scss?
Since I can't see your code, I am not sure how you imported your resources exactly. However, if you are only generating one .css file, a good practice is to import everything on the file that will be compiled and not on each partial.
Let's imagine you have the following structure :
styles
├─ components
│ ├─ _footer.scss
│ └─ _navbar.scss
├─ settings
│ ├─ _functions.scss
│ └─ _mixins.scss
└─ styles.scss
In this example, styles.sccs is the only one that will be compiled, it will be used only to import all partials (the order matters):
// Settings
#import './settings/mixins';
#import './settings/functions';
// Components
#import './components/footer';
#import './components/navbar';
You then can use any mixins or functions in your components and everything is only imported once.
I'm not sure this answers your question – but to prevent duplicates in Sass I would create a mixin to check if an #include has already been made
SCSS
// Global list to keep track of what mixins has been included
$include-once: ();
// Mixin helper to be used inside other mixins we would like
// not to produce duplicate content
#mixin once($mixin-name) {
// check if mixin name exists in our list
#if not index($include-once, $mixin-name) {
// add mixin name to list (using the global flag)
$include-once: append($include-once, $mixin-name) !global;
// print out the content of the mixin
#content;
}
}
// Use example
#mixin font {
// wrap content in the include once wrapper passing the name of the mixin
#include once(font){
// make sure font import is not nested
#at-root {
#import url("https://fonts.googleapis.com/css?family=Open+Sans");
}
}
}
// Test
.foo { #include font; color: red; }
.bar { #include font; color: green; }
.baz { #include font; color: blue; }
CSS Output
#import url("https://fonts.googleapis.com/css?family=Open+Sans")
.foo {
color: red;
}
.bar {
color: green;
}
.baz {
color: blue;
}
I'm sort of late to the game, but I experienced this issue and having partials or using #include did not work. What did it for me was using i.e. css-nano-webpack-plugin https://www.npmjs.com/package/cssnano-webpack-plugin. I'm using webpack v5, so could not get it to work using the webpack mini-css-extract-plugin https://www.npmjs.com/package/mini-css-extract-plugin.
Please bear in mind that the below snippet minimizes and minifies the css PER scss file. So, repetitions between files may still make it in the .css output file.
So, include it in your webpack config like so (source is the npmjs cssnano-webpack-plugin site)
const CssnanoPlugin = require('cssnano-webpack-plugin');
module.exports = {
module: {
loaders: [
{
test: /.s?css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader'
]
}
]
},
optimization: {
minimizer: [
new CssnanoPlugin()
]
}
};
´´´

Include `.scss` file in another `.scss` file?

How can I Include .scss file in another .scss file?
I was trying to write this in a file:
app.scss:
#include('buttons');
#include('dropzone');
body {
background: $primaryColor;
overflow-x: hidden; /*Clip the left/right edges of the content inside the <div> element - if it overflows the element's content area: */
height: 100%; /* Cover all (100%) of the container for the body with its content */
padding-top: 70px;
} /* more css code here */
and it returns an error : invalid css after #import
I try to include 2 other scss files inside the main scss file, so it will be all compiled to one css file eventually. How is it possible?
You can import it like this;
#import "../../_variables";
#import "../_mixins";
#import "_main";
#import "_login";
#import "_exception";
#import "_utils";
#import "_dashboard";
#import "_landing";
According to your directories and it will do what you want.
You can include a partial by doing this:
#import "partial";
The imported file needs an underscore, so sass will recognize it to be included: _partial.scss
You can use #use rule for it. This rule loads another Sass file as a module, which means you can refer to its variables, mixins, and functions in your Sass file with a namespace based on the filename. Using a file will also include the CSS it generates in your compiled output!
// _base.scss
$font-stack: Helvetica, sans-serif;
$primary-color: #333;
body {
font: 100% $font-stack;
color: $primary-color;
}
see how to using #use 'base'; in the styles.scss file
// styles.scss
#use 'base';
.inverse {
background-color: base.$primary-color;
color: white;
}
you don't need to include the file extension.
#osherdo You have no need to add !important for overwriting bootstrap CSS.
body
{
background: #4d94ff; /* Use to override Bootstrap css settings. */
}
First of you need to verify from where bootstrap is rendering on the page and what is the weight of the bootstrap CSS file. After that you can place your 'css/app.css' file after bootstrap then it will work. Then you can easily overwrite the entire bootstrap CSS.
Ok, so it appears to be that my app.scss file collide with Bootstrap.css file.
Because I wanted the app.scss background property to apply, instead of the bootstrap css file. I've added !important in this property to override bootstrap style.:
body
{
background: #4d94ff !important; /* Used to override Bootstrap css settings. */
}
Also, gulpfile.js has been updated to suite my needs accordingly:
var elixir = require('laravel-elixir');
elixir(function (mix) {
mix.sass('app.scss', 'resources/assets/css')
.styles([
'app.css'
], 'public/css/app.css');
mix.version([
'css/app.css'
]);
});
And that's how I fixed it.

Sass::Engine.new causes Sass::SyntaxError on #import

I'm writing my own static site generator in ruby and I'm in the process of adding Sass compiler to my code.
def compile_sass
# system 'sass _sass/styles.scss styles.css'
options = {
syntax: :scss,
style: :compressed
}
render = Sass::Engine.new(File.read('_sass/styles.scss'), options).render
File.write('style.css', render)
end
But problem occurs when the styles.scss file has #import in it. Causing
(sass):1: File to import not found or unreadable: variables. (Sass::SyntaxError)
Both SCSS files are located in _sass folder, main script in root, and compile_sass is located in _generator. But when I uncomment the system call and comment the rest, everything works as expected.
styles.scss
#import 'variables';
html {
background-color: red;
}
_variables.scss
body {
background-color: blue;
}
I tried almost everything, checked how to import stuff, looked at the documentation, but I can't find anything that would helped me find and define the problem.
Turns out I had to load all _sass/*.scss files into Sass::Engine like this:
Sass::Engine::DEFAULT_OPTIONS[:load_paths].tap do |load_paths|
load_paths << '_sass'
end

Resources