How to namespace Bootstrap CSS
Isolating Bootstrap CSS rules
TL;DR? Get the files from GitHub: https://github.com/jonasjancarik/bootstrap-namespaced.
Please note that this guide has not been updated since Bootstrap 4.0.0 (March 2018) so it’s probably outdated. If you encounter any problems, please let me know in the comments or on Twitter.
There is arguably one problem with Bootstrap’s class names: if you want to use Bootstrap alongside other CSS, the simple names can conflict with the rest of your styles because they do not use a clear namespace.
I recently came across this issue while working on a website which is built on Bootstrap, but where the developers changed some of its core classes and cut out other rules altogether, which makes it rather difficult to use Bootstrap reliably for other content.
The only way around it I could think of (short of changing the main template, which would take too long for various reasons) was to inject a regular version of Bootstrap, prefixed with a special class name to avoid conflicts with the bungled up version already included.
Since it took me a while to figure out all the steps (a Stack Overflow thread helped), I decided to write them down in case someone is facing a similar issue. Following this guide may also help you if you want to compile your own custom version of Bootstrap.
Prerequisites
Ubuntu Linux (or similar)
Now you should actually be able to do all of this in Windows or Mac OS — I don’t really see a reason why that should not be possible, but obviously not all the steps and commands below are going to be the same.
On Windows 10, Ubuntu is now included — after enabling it, you can type bash
in the File Explorer address bar and follow along.
Node.js
You can check whether you have Node.js installed by checking the version number:
node -v
If it is missing, you can install v8 with
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -sudo apt install -y nodejs
You can find other install options on the Node.js website.
Ruby
Check which version of Ruby is installed (if any):
ruby -v
You will need Ruby version 2.0 or higher. There are multiple ways to install it.
In Ubuntu, currently the version you install with sudo apt install ruby-full
is 2.3, which is enough. (Make sure to install ruby-full
rather than just ruby
— you will need the dev packages which are part of ruby-full. You can always install ruby-full on top of ruby, though.) Additional install options are listed on the Ruby website.
If you intend to use Ruby more heavily, you may want to look into RVM (Ruby Version Manager). This is how to install the latest stable version of Ruby with RVM:
gpg — keyserver hkp://keys.gnupg.net — recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3\curl -sSL https://get.rvm.io | bash -s stable --rubysource ~/.rvm/scripts/rvm
Bundler
Bundler is used for managing Ruby dependencies. Install it with:
gem install bundler
If you get a permissions error, try running the command with sudo (i.e. sudo gem install bundler
). (If you are using RVM, try rvmsudo instead.)
Setting up Bootstrap
1) Create a working directory and enter it. I called mine bootstrap-ns (for namespace):
mkdir bootstrap-ns && cd bootstrap-ns
2) Clone the current version of Bootstrap with git:
git clone https://github.com/twbs/bootstrap.git
This will download the Bootstrap project (the source files) to a folder named bootstrap within your working directory. (You can of course also just download Bootstrap source and unpack it in this directory.)
We need to enter the folder:
cd bootstrap
3) Install local Bootstrap dependencies with npm:
npm install
4) Install all Ruby dependencies, such as Jekyll and plugins, with this command:
bundle install
Pay attention to any additional instructions displayed: you will likely be asked to enter your account password. If you get stuck with errors regarding the installation of additional gems, make sure you have those Ruby dev packages mentioned above installed.
If you get ‘An error occurred while installing nokogiri’, try running sudo apt install zlib1g-dev
.
Editing Bootstrap source
Now you have a Bootstrap project prepared for compiling from the source files, you can proceed to editing those source files. There will be two main steps:
- creating a new SASS source file which will wrap the usual core Bootstrap CSS within a new class,
- editing a script in package.json to include this file when compiling.
The first step can be done with a simple command. If you want to pick your own name for the wrapping class, simply change .twbs to .something-else. Just make sure you are still in the bootstrap directory.
echo '.twbs { @import "bootstrap"; }' >> scss/bootstrap-ns.scss
Now for the second step, you will need to edit the package.json file to change the CSS compilation scripts to include the -ns files.
This could be done manually using an editor, but we will stick to the command line, using Trent Mick’s json tool. Install it with:
sudo npm install -g json
Now execute the two following commands:
json -I -f package.json -e 'this.scripts["css-compile"]="node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 scss/bootstrap.scss dist/css/bootstrap.css && node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 scss/bootstrap-ns.scss dist/css/bootstrap-ns.css && node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 scss/bootstrap-grid.scss dist/css/bootstrap-grid.css && node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 scss/bootstrap-reboot.scss dist/css/bootstrap-reboot.css"'
and
json -I -f package.json -e 'this.scripts["css-minify"]="cleancss --level 1 --source-map --source-map-inline-sources --output dist/css/bootstrap.min.css dist/css/bootstrap.css && cleancss --level 1 --source-map --source-map-inline-sources --output dist/css/bootstrap-ns.min.css dist/css/bootstrap-ns.css && cleancss --level 1 --source-map --source-map-inline-sources --output dist/css/bootstrap-grid.min.css dist/css/bootstrap-grid.css && cleancss --level 1 --source-map --source-map-inline-sources --output dist/css/bootstrap-reboot.min.css dist/css/bootstrap-reboot.css"'
Compiling
Now that everything is ready, run the Grunt script from the /bootstrap directory (which should still be your current directory):
npm run dist
If you get an error saying ‘npm-run-all: not found’, run sudo npm install -g npm-run-all
to install the missing package.
Now check the dist/css folder:
ls -lh dist/css
It should contain the compiled CSS files, including bootstrap-ns.css, which will be the final file to include in your project (or the minified .min.css version).
Fix the CSS rules for HTML and @page and minify
Since the SASS file we used simply prefixed every rule with .twbs, you will need to change it for the rules concerning the HTML
element by moving the twbs class selector after the tag selector. (I.e. changing .twbs html to html.twbs.)
You can do this manually or with the following command:
sed -i "s/\.twbs html/html.twbs/g" dist/css/bootstrap-ns.css dist/css/bootstrap-ns.min.css
If you’re running this process on a BSD derivative (e.g., macOS), then the sed
command works differently. Use this one (thanks Alex Bauer for the tip!):
sed -i "" "s/\.twbs html/html.twbs/g" dist/css/bootstrap-ns.css dist/css/bootstrap-ns.min.css
Sass doesn’t compile the @page
directive correctly (see here), so what we have right now in bootstrap-ns.css looks like this:
@page {
.twbs {
size: a3;
}
}
You have to remove the .twbs wrapper to make the CSS file valid:
@page {
size: a3;
}
Since the rule was invalid, it was dropped from the minified file. Generate the minified CSS files again with:
npm run css-minify
Keep in mind the corresponding .css.map files now don’t match anymore, so if you want to work with those, you will need to edit them, too.
And it’s done!
All rules in the resulting CSS files (bootstrap-ns.css as well as the minified bootstrap-ns.min.css) should now start with .twbs (except html.twbs of course).
You will later have to add the namespace class to the tags in your HTML (if you want to use Bootstrap for the whole page), e.g.:
<html class="twbs">
...
<body>
...
</body>
...
</html>
What you should keep in mind is that you may still encounter some conflicts when using Bootstrap JS components, because some of the selectors in bootstrap.js are (at least used to be in previous versions) hardcoded.