How to get most out of any CSS framework written in Sass lang?
Ever wondered how to get the most out of every CSS framework out there, that's written in Sass language? I'm here to show you the way.
We're going to use Bootstrap framework, specifically v4.5.3. Why not Bootstrap v5? Because it's still in alpha at the time of this writing and core things are going to change. I'll give it an update to Bootstrap v5, or write a new dedicated post for it when it gets released.
Prerequisite
- Have an NPM project initiated
- Project uses NPM scripts or bundler (e.g. Webpack) for Sass
- Have Bootstrap or any other Sass/Scss framework installed in your project as a dependency
Getting Started
We're not going to pay attention to the JS side of this framework. Let's just assume it's a pure CSS framework that has no other additions.
Let's begin structuring our project. In my projects, I always have a directory for source code, named src
, and inside I have multiple directories that are named by what they represent.
Here's the ASCII tree that represents a project structure, that focuses only on styles
. In a real-world project, there would be many other directories and files, but for sake of this guide, there are no additional files or directories.
.
└── project/
└── src/
└── styles/
├── app/
│ ├── base.scss
│ └── variables.scss
├── vendor/
│ └── bootstrap/
│ ├── core.scss
│ ├── main.scss
│ └── variables.scss
├── app.scss
└── vendor.scss
Let's focus on app.scss
and vendor.scss
files first. They are entry points for your style
assets. Their sole purpose is to import all of the files that are in their corresponding directory, with one exception.
Let's import the files inside of them, even though, the files that we're going to import are empty.
File: app.scss
You'd use this file for your app-specific styles... Everything that you own.
// Bootstrap's Core
@import 'vendor/bootstrap/core';
// App
@import 'app/variables.scss';
@import 'app/base.scss';
I said, in each file, we'll import files from their corresponding directories. The exception is, in our app.scss
I imported bootstrap/core
from vendor
.
- The
core
is the most important file of this separation and that's why we add it once at the top, before all of our app imports - In the
variables
you'd write any additional variables for your app - In the
base
you'd write any base styling (e.g. extending an reset css)
File: vendor.scss
You'd use this file for all of the dependencies... Everything that you install through Npm.
@import 'vendor/bootstrap/main';
Let's fill in the vendor/bootstrap
files now. If you take a look at the Bootstrap's main SCSS file, you'll notice that it contains imports of everything that framework has to offer.
We need to use this to our advantage so that we can get the most out of it.
Instead of trying to confuse you, with copy/pasting and moving pieces, it's the best to take a look at this example: Webpack Config
In a nutshell, we took most important files from Bootstrap and moved them into core
file, so that we can reuse all of its functionalities within our app itself.
What we achieved by the separation?
With all separation, we now take full control over the Bootstrap framework. As I said earlier, it can be any framework written in Sass lang. Doesn't have to be Bootstrap necessarily.
We achieved the following:
- Separation of
app
andvendor
style compilation and bundling - Overriding default Bootstrap variable values. This is now done by writing any of the Bootstrap existing variables in our custom
vendor/bootstrap/variables.scss
file and setting a different value - Removing unnecessary/unused components, simply by commenting out desired
@import
lines from ourvendor/bootstrap/main.scss
file - Using Bootstrap functions, mixins, and variables within files in our app directory
Now everything that we write additionally for our app, can have Bootstrap original feel to it, as you'll be using the same variables, functions, and mixins, directly from Bootstrap.
Learn more through complete example
Since it may be hard to understand everything initially from the context; it may be easier to understand it better from the complete example.
Take a look at my Webpack Config, which implements this logic and more.