Sass importing without compiling - css

In sass, the way one imports is by using the import command. I will use Zurb Foundation as an example:
#import "foundation";
This will then import the whole foundation.scss file and all it's relative imports to the top of the current file. This means that the entire foundation.scss file will be compiled and outputted along with the contents of the file to the final <name here>.css file.
Though this is good for customisation, such as custom colors and spacing, it becomes a pain when creating libraries and distributing these libraries as individual droplets for other people to slot into their existing projects.
Is there a way to import files as "references", so that mixins and other variables become available in the scope of the current file, but other css statements are ignored? The LESS css preprocessor has a newly implemented import tag similar to this (appropriately named a reference).

Taking a look at Foundation demonstrates a good approach to this:
https://github.com/zurb/bower-foundation/blob/master/scss/foundation/components/_breadcrumbs.scss
Here they have one #import "global"; at the top of the file.
That is followed by a bunch of mixins
At the bottom they have:
#include exports("breadcrumbs") {
#if $include-html-nav-classes {
.breadcrumbs {
#include crumb-container;
#include radius($crumb-radius);
&>* {
#include crumbs;
}
}
}
}
The $include-html-nav-classes is set to true by default in the _global.scss file. It can be overridden in any other file by changing it to false. This allows you to both use the mixins and generate html.
If you don't need to generate any css just include mixins only and it will simplify your situation. I believe that they do this to allow for fast customization and optimization of the outputted css.

Related

How to import part of an scss file

For example I am trying to import .navbar-nav from bootstrap's _navbar.scss and not the whole _navbar.scss file to my compiled css file. Is there a way to do it?
Sorry if this was asked before.
You can try doing an extend:
.your-class{
#extend .navbar-nav;
}
However, this would only work if you had imported the _navbar.scss somewhere else or the bootstrap.scss.
Additional
// main.scss
#import ../wherever bootstrap file is/_navbar.scss;
#import _custom.scss;
// _custom.scss
.your-class{
#extend .navbar-nav;
}
One of the way to import .scss in javascript is
import { navbar-nav } from '_navbar.scss'
When using in your component you can do.
<div className={navbar-nav} />
if you want to import it in your .scss file then you can do.
#import '_navbar.scss'
.class {
#extend .navbar-nav
}
As you are learning Sass here are some explanations which may help:
Better wording helps ...
At first some wording to get a correct understandable communication here and anywhere else you are talking about coding:
SASS don't minify a given CSS, it writes the CSS. Minify means the process that a given CSS code is compressed by a postprocessor to a shorter way to write it, - i.e. comments and spaces will be removed ... But yes: as SASS writes CSS it is able to write code in a minified format.
What you mean is to 'reduce code' or 'avoid not needed code' as you only try to import, use and write! the only needed parts of a given module which is a good practice.
.navbar is a CSS class. SASS don't load CSS classes, it writes CSS classes. It doesn't matter if you 'write the code on your own to a SCSS file' or 'get the code from a framework/module' ... SASS writes the however prepared CSS classes to your CSS file.
What you mean is the SASS includes/imports files with code from a framework/module to write that code/classes to css. So yes: maybe you can say you 'load' that module/scss-file ... but you don't load as css class. (This is as important as 'classes' in coding allways means a special construct of excutable code which does something in your programm. CSS classes don't execute anything, in SASS they are content you want to write/output to css.)
Please: these wordings are important to understand each other and to understand the mechanic of the process how SASS works is going on as well.
Reducing code by importing only selected file is good practice
So, I am not sure if I did understand your question right:
No. You are not able to include/import/load a part of the code of a single scss-file only. If you do #import 'somefile.scss' you always get the whole code of the whole file.
Yes. you are able to include/import/load parts of a given framework/module as you are able to load only the special FILES(!) of a framework/module you need for your project.
Yes. That is a really good practice.
As you mentioned Bootstrap indeed is developed and allows you to do that. But head up. If you import i.e. the part navbar.scss (or other selected elements) it only works if you also load the other files navbar.scss depends on. That are almost variables, functions, mixins and sometimes needed JS components to this element as well. Please note, that importing the files the elements are based on (i.e. vars, functions, mixins) has to be done BEFORE you load the element (i.e. like navbars, grid,...) itself.
A way to organize your project
Yes. A good way to organize your project is to have a single(!!!) file which brings all the code together you write in other partial files yourself or which you import from other framework/modules.
In case of Bootstrap this can be (simplified example):
// ###> file: your 'custom.scss'
// Note: file is without leading underscore
// as this files GENERATES/WRITE the css to custom.css
// Files with underscore as _partial-footer-styling.scss
// are not compiled to write css on their own
// that files are only compiled to css when they are imported to files without underscore
#import 'path/your-own-vars';
// Note: technique importing files
// you don't need to write underscore and '.scss'
// Note: function of this file
// the file '_your-own-vars.scss' is to organize you needed vars special to your project
// it includes your own vars and bootstrap vars as well
// --> the Bootstrap vars in this file will overwrite the vars of Bootstrap which will be included next
#import 'bootstrap-path/functions';
#import 'bootstrap-path/variables';
#import 'bootstrap-path/mixins';
#import 'bootstrap-path/your-selected-component-1';
#import 'bootstrap-path/your-selected-component-2';
#import 'bootstrap-path/your-selected-component-3';
...
#import 'path/partial-your-own-additional-css-special-section';
#import 'path/partial-your-own-additional-css-footer-settings';
....
A detailed explanation how to include and use Bootstrap (partly if you like to do so) to your project is here: https://getbootstrap.com/docs/4.6/getting-started/theming/

Organize application SASS files using Bootstrap

I'm starting to work on a large application styling files. As Bootstrap 4 offers SASS files, I decided to follow that path.
I have built the following files structure:
theme.scss: general definitios for the theme like colors and fonts. Today there is just one but there could be more in the future.
global.scss: includes Bootstrap, some Bootstrap overrides and application componentes -i.e. a field with its label as part of the top border.
site.scss: general application styles.
additional page-specific SCSS files. I.e.: login.scss.
The problem I'm having is that global.scss -the one that imports Bootstrap- is then imported by site.scss as well as other files like page-specific SCSS files. So, Bootstrap styles end up in more than one compiled CSS. Compiled CSS files are what the application actually references.
I've previously used LESS and I could solve this using #import (reference) "bootstrap" instead of just plain #import "bootstrap". With SASS I haven't been able to find any solution to this problem without modifying Bootstrap core files.
Is there any other recommended way to organize the files and avoid this problem? Am I missing something or doing anything wrong?
Here are the files contents (they are large files but I'm posting only enough contents to show the problem I'm having):
theme.scss
$my-primary-color: #04459a;
global.scss
#import "../theme.scss";
$primary: $my-primary-color;
#import "../../third-party/bootstrap/scss/bootstrap.scss";
%field{
// [...]
}
site.scss
#import "global.scss";
div.field {
#extend %field;
}
// [...]
login.scss (or many other)
#import "global.scss";
// [...]
In the application I'm referencing site.css and login.css (in the loign page, of course) and both of them include Bootstrap styles.
I've built something that works for me, not sure if it's the best solution or which drawbacks it has, though.
I took some ideas from this article: My favored SCSS setup with Bootstrap 4. Here's what I've built:
First I created two SASS files for importing Bootstrap (similar to what the article does with bootstrap/_config.scss but splitted):
bootstrap/_sass-componentes.scss
#import "../../terceros/bootstrap/scss/_functions.scss";
#import "../../terceros/bootstrap/scss/_variables";
#import "../../terceros/bootstrap/scss/_mixins";
bootstrap/_config.scss
#import "_sass-componentes.scss";
// Every other bootstrap file I want to include:
#import "../../terceros/bootstrap/scss/_root";
#import "../../terceros/bootstrap/scss/_reboot";
#import "../../terceros/bootstrap/scss/_type";
// [...]
#import "../../terceros/bootstrap/scss/_utilities";
#import "../../terceros/bootstrap/scss/_print";
Then in global.scss I changed the bootstrap.scss import line to import only bootstrap/_sass-componentes.scss
Finally, in site.scss I included global.scss (such as it was before) and then full Bootstrap files trough bootstrap/_config.scss. **
** After importing _config.scss I also import my Bootstrap customizations. For doing them I followed the recomendation of the linked article although they do not apply directly to my own question.

Sass #extend to consider imported css during build

I have a global CSS file that contains all generic CSS.
I want to be able to extend all the classes present in this global CSS file in any of my SCSS files.
Right now it throws an error .xyz class does not exist and build fails. I tried importing this file but still build fails.
Adding !options next to class is one way for the build to pass but is there any other better way?
Bit more context for Vue users. I use VueCli3. I use <style lang="scss"> for writing SCSS and want to use extend here. Vue documentation suggesting adding prependData for adding variables. I imported the global CSS in a SCSS file and imported that file in the prependData but Vue build still fails.
It sounds like you want to globally include a CSS file with content that the SCSS blocks in each component can read. (Variables, style definitions, etc).
#extend works like a variable, meaning SCSS needs the definition style to be available as part of its compilation. So that means getting "SCSS Global Variables" working should solve your Extend problem too.
In that case, you need to tweak how Webpack deals with your components. You can do it manually as described here. Or my preference is to use a Vue Cli plugin called vue-cli-plugin-sass-resources-loader. Make sure that your component <style> section contains lang="SCSS" though I assume you're already doing that.
Using #import CSS file into SCSS file not possible to #extend any class.
But you can follow below steps for extends class from your pure css code.
Convert .css file into .scss.
import that global.scss file into another .scss file.
Then after you can use #extend for extend class in new file.
If your file have more then 1k line of code then it will get trouble for extend class.

How to avoid multiple #imports of SASS variables?

The site I'm working on uses the rails asset pipeline and an application.scss file to import and process different CSS files.
However, some stylesheets are used in specific places, and for those, it makes little sense to import them into the global manifest. But not so importing them requires importing variables.scss, and possibly mixins.scss into the sheet itself (so they'll process correctly), resulting in duplicate code in the final CSS.
Is there a way to basically tell the preprocessor - "trust me, the variable/mixin you're seeing will be defined by the time everything gets processed"?
Otherwise, I don't see how to avoid importing every sheet into a single manifest, which seems bloated.
Thanks.
The short answer to your question is no. The variables need to be defined in a logical order from when they are called in compilation. It's like a "chicken and the egg" scenario.
From what I can ascertain in your description, the project you're working on is not compiling into a unified workflow, but chunking out into modular portions relational to your file structure. IF this is the case, what you can do at the beginning of each file is reference the variables file from the root.
In a normal workflow, you would import your scss files based on your defined hierarchy like so:
sass/style.scss
/* Main Stylesheet */
#import "variables";
#import "mixins";
/* Modular Sections */
#import "layout/header";
#import "layout/body";
#import "layout/footer";
would compile out to one stylesheet style.css with a command sass sass/style.scss:style.css
What I'm assuming your project does is have all the /* Modular Sections */ files compile out into their own CSS files.
layout/header.scss
/* Header Stylesheet */
#import "../variables";
#import "../mixins";
Given a files structure that resembles:
/root
style.scss
variables.scss
mixins.scss
/layouts
header.scss
body.scss
footer.scss
This all seems kinda silly though. I don't know all the parameters that go into your current sass compilation, but I'd recommend using a unified workflow.
You can use Partials so the compiler will not try to interpret variables etc.
Basically, rename the files that you do not want the compiler to interpret -- but will be available when compiled -- with an underscore before the filename.
eg.
_filename.scss
If I understood well you want to avoid copies of the same css in css files caused by using #import in scss. I solved this problems by doing a hierarchical three.
For exemple consider the home.scss file, where you import header.scss and footer.scss.
Both header.scss and footer.scss use specific colors that you import from a file named colors.scss:
// colors.scss
$MidnightBlue: #00478f;
$RedOrange: #ff5d00;
$MistyBlue: #d8e1e7;
$Ebony: #2a231f;
Now you could import colors in header.scss, footer.scss and maybe even in home.scss. The result is that in home.css the code of colors.scss is repeated 3 times.
A solution is importing colors.scss only in header.scss. Then in home.scss the first #import that you specify is #import "header.scss"; and then #import "footer.scss";, thus you can use the colors variables in footer.scss and in home.scss even if you don't import them directly in footer.scss and home.scss. That's because the variables of colors are imported before the footer and compiled before the rest of the code in home.scss.
Now if you check home.css you shouldn't see repeated code
When at first you write the color variables in footer you will receive an error because they are not defined, but it disappear when you import footer in home.scss
If you #import the same SASS file (e.g. variables.sass) in multiple files and then #import those files in the one main.sass file, the resulting main.css file will contain the content of variables multiple times.
A good way of structuring SASS files is to obey the rule of importing each file only once. Iconic architecture is the 7-1 Pattern. You basically decompose your SASS files into atomic parts and then import those in appropriate order only once in the main file.

How can one import only variables and mixins from Sass stylesheets?

I'm using the Zurb Foundation 4 (S)CSS framework, and I'm running into an issue of massively duplicated styles. This is because in every file that I #import 'foundation' in, all styles from Foundation are also imported (rules for body, .row, .button and friends). This leads to long SCSS compile times and a hard to navigate web developer console in Chrome, as all of Zurb's styles are declared four or five times.
To mitigate this, I've created a globals scss file, which contains the overrideable variables that Foundation uses (it's copy-pasted from foundation_and_overrides.scss, then foundation_and_overrides import globals). Importing just the globals.scss file gets rid of duplication only in files that don't make use of Foundation mixins.
It's in the files which make use of Foundation mixins: Can I import only the mixins from an SCSS file, without importing the concrete Foundation styles?
Imports are an all or nothing thing. Everything that's in the file is what you get. If you look through the source of Foundation, though, there are variables you can modify that will suppress emitting styles (eg. in buttons, setting $include-html-button-classes to false will disable the styles). This design pattern is Foundation specific, you cannot expect other libraries to be authored this way.
When you import foundation via #import "foundation", you're importing this file: https://github.com/zurb/foundation/blob/master/scss/foundation.scss. As you can see, it imports other files. You don't have to import this file if you don't need everything: just import the specific file you want (eg. #import 'foundation/components/side-nav' for only the side-nav file).
I had similar issue, where I wanted to simply use a variable from another file, without import of all CSS.
The #use keyword of newer Sass-versions can be used to ensure CSS is not emitted more than once.
The down-sides are:
Only "Dart Sass" supports compiling it (at least, at time of writting).
#use rules must be written before any other rules.
Last but not least, we can not simply replace #import with #use, and need to prefix scope, like:
#use '../my-module';
body {
background-color: my-module.$my-variable;
}
Warning: #extends keyword(s) can not have my-module. prefix, because extensions are not scoped at all (at least, at time of writting).

Resources