How to namespace Twitter Bootstrap so styles don't conflict
Twitter BootstrapLessTwitter Bootstrap Problem Overview
I want to use Twitter Bootstrap, but only on specific elements, so I need to figure out a way to prefix all Twitter Bootstrap classes with my prefix, or use the less mixins. I'm not experienced with this yet so I don't quite understand how to do this. Here's an example of the HTML that I'm trying to style:
<div class="normal-styles">
<h1>dont style this with bootstrap</h1>
<div class="bootstrap-styles">
<h1>use bootstrap</h1>
</div>
</div>
In this example, Twitter Bootstrap would normal style both h1
s, but I want to be more selective about which areas I apply the Twitter Bootstrap styles.
Twitter Bootstrap Solutions
Solution 1 - Twitter Bootstrap
This turned out to be easier than I thought. Both Less and Sass support namespacing (using the same syntax even). When you include bootstrap, you can do so within a selector to namespace it:
.bootstrap-styles {
@import 'bootstrap';
}
Update: For newer versions of LESS, here's how to do it:
.bootstrap-styles {
@import (less) url("bootstrap.css");
}
Solution 2 - Twitter Bootstrap
@Andrew great answer. You'll also want to note that bootstrap modifies the body {}, mainly to add font. So when you namespace it via LESS/SASS your output css file looks like this: (in bootstrap 3)
.bootstrap-styles body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 1.428571429;
color: #333333;
background-color: white;
}
but obviously there will not be a body tag inside your div, so your bootstrap content will not have the bootstrap font (since all bootstrap inherits font from parent)
To fix, the answer should be:
.bootstrap-styles {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 1.428571429;
color: #333333;
background-color: white;
@import 'bootstrap';
}
Solution 3 - Twitter Bootstrap
Putting @Andrew, @Kevin and @adamj's answers together (plus a few other styles), if you include the following in a file named "bootstrap-namespaced.less", you can simply import 'bootstrap-namespaced.less' into any less file:
// bootstrap-namespaced.less
// This less file is intended to be imported from other less files.
// Example usage:
// my-custom-namespace {
// import 'bootstrap-namespaced.less';
// }
// Import bootstrap.css (but treat it as a less file) to avoid problems
// with the way Bootstrap is using the parent operator (&).
@import (less) 'bootstrap.css';
// Manually include styles using selectors that will not work when namespaced.
@import 'variables.less';
& {
// From normalize.less
// Previously inside "html {"
// font-family: sans-serif; // Overridden below
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
// Previously inside "body {"
margin: 0;
// From scaffolding.less
// Previously inside "html {"
// font-size: 10px; // Overridden below
-webkit-tap-highlight-color: rgba(0,0,0,0);
// Previously inside "body {"
font-family: @font-family-base;
font-size: @font-size-base;
line-height: @line-height-base;
color: @text-color;
background-color: @body-bg;
}
Solution 4 - Twitter Bootstrap
Adding a namespace to bootstrap CSS will break modal functionality as the bootstrap adds a 'modal-backdrop' class directly to the body. A workaround is to move this element after opening the modal, e.g.:
$('#myModal').modal();
var modalHolder = $('<div class="your-namespace"></div>');
$('body').append(modalHolder);
$('.modal-backdrop').first().appendTo(modalHolder);
You can remove the element in a handler for the 'hide.bs.modal' event.
Solution 5 - Twitter Bootstrap
First clone bootstrap from github:
git clone https://github.com/twbs/bootstrap.git
Install requirements:
npm install
Open scss/bootstrap.scss and add your namespace:
.your-namespace {
@import "functions";
...
@import "utilities/api";
}
Compile bootstrap:
npm run dist
Open dist/css/bootstrap.css
and remove the namespace from the html
and body
tag.
Afterwards copy the content of the dist folder into your project and you're all set.
Have fun!
Solution 6 - Twitter Bootstrap
Use the .less version of the files. Determine which less files you require, then wrap those .less files with:
.bootstrap-styles {
h1 { }
}
This will give you the output of:
.bootstrap-styles h1 { }
Solution 7 - Twitter Bootstrap
I did a GIST with Bootstrap 3 all inside a class named .bootstrap-wrapper https://gist.github.com/onigetoc/20c4c3933cabd8672e3e
I started with this tool: http://www.css-prefix.com/ And fix the rest with search and replace in PHPstorm. All fonts @font-face are hosted on maxcdn.
First line example
.bootstrap-wrapper {font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
Solution 8 - Twitter Bootstrap
Namespacing breaks the Modal plugin's backdrop div, since that is always added directly to the <body> tag, bypassing your namespacing element which has the styles applied to it.
You can fix this by changing the plugin's reference to $body
before it shows the backdrop:
myDialog.modal({
show: false
});
myDialog.data("bs.modal").$body = $(myNamespacingElement);
myDialog.modal("show");
The $body
property decides where the backdrop will be added.
Solution 9 - Twitter Bootstrap
To explain better all the steps what Andrew was talking about for those who don't know what Less is. Here is a link that explain pretty well how it is done step by step How to isolate Bootstrap or other CSS libraries
Solution 10 - Twitter Bootstrap
Most simple solution - start to use custom build isolated css classes for Bootstrap.
For example, for Bootstrap 4.1 download files from css4.1 directory -
https://github.com/cryptoapi/Isolate-Bootstrap-4.1-CSS-Themes
and wrap your HTML in a div with the class bootstrapiso :
<div class="bootstrapiso">
<!-- Any HTML here will be styled with Bootstrap CSS -->
</div>
Page template with isolated bootstrap 4 will be
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content="">
<title>Page1</title>
<!-- Isolated Bootstrap4 CSS - -->
<link rel="stylesheet" href="css4.1/bootstrapcustom.min.css" crossorigin="anonymous">
<!-- JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" crossorigin="anonymous"></script>
<script defer src="https://use.fontawesome.com/releases/v5.0.9/js/all.js" crossorigin="anonymous"></script>
</head>
<body>
<div class="bootstrapiso">
<!-- Any HTML here will be styled with Bootstrap CSS -->
</div>
</body>
</html>
Solution 11 - Twitter Bootstrap
As a further note for everyone. To get modals working with a backdrop you can simply copy these styles from bootstrap3
.modal-backdrop {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1040;
background-color: #000;
}
.modal-backdrop.fade {
filter: alpha(opacity=0);
opacity: 0;
}
.modal-backdrop.in {
filter: alpha(opacity=50);
opacity: .5;
}
Solution 12 - Twitter Bootstrap
I faced the same issue and method proposed by @Andrew unfortunately didn't help in my specific case. Bootstrap classes collided with classes from another framework. This is how this project has been incepted https://github.com/sneas/bootstrap-sass-namespace. Feel free to use.
Solution 13 - Twitter Bootstrap
Preconditions
-
You didn't setup a CSS preprocessor.
→ Otherwise try this: https://stackoverflow.com/a/13977230/2911452
-
Your Bootstrap version is older than 4.1.
→ Otherwise try this: https://stackoverflow.com/a/49910653/2911452
-
You're unlikely to update your Bootstrap version. This solution is only practical for legacy parts of your website/application.
-
You can self-host css
Solution
Prefix all css selectors with a class selector:
-
Copy all the CSS from the CDN into your editor (e.g. http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css)
-
Wrap the whole thing with a selector (SCSS style), for example
.bootstrap-styles
:
.bootstrap-styles{
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside /* etc... */
}
-
Use a tool to convert SCSS to CSS. I used https://jsonformatter.org/scss-to-css . (See screenshot at the end)
-
Self-host the resulting CSS file and include it on the pages where you need it
-
Wrap the parts that require Bootstrap styling with
<div class="bootstrap-styles"> ... </div>
→ Bootstrap styles will only be applied to these parts
-
You can optionally minimize the resulting CSS.
Caveats
-
Resulting
.bootstrap-styles html {
selector will obviously not work, as the html tag won't have a parent. You could fix this by changing it into just.bootstrap-styles {
. Same applies tobody
. -
Icons and fonts with a relative path will be broken. You can find these by searching for
url(
.- Option 1. Remove these styles if you don't need them
- Option 2. Update the URls to use am absolute path to the CDN (e.g.
https://netdna.bootstrapcdn.com/bootstrap/3.1.1/fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular
- Option 3. Download the assets from the CDN and self-host these as well.
-
You can't use a dependency management tool like npm. You'll have to go through these steps everytime you want to update Bootstrap (see precondition).
Screenshot
Converting SCSS to CSS