How do I limit Bootstrap to just the scope of a div? I need to nest the Bootstrap stylesheet inside an ExtJS app for especific divs and both are clashing since they need the
The only thing I know of that is for sure worse than this script is bootstrap itself, but this is probably still going to be the best answer here for a little while:
prefix="#bs431"; cat bootstrap.css | while IFS='' read -r line; do if echo "$line" | egrep -i '(\{|,)$' | egrep -iv '\@media' | wc -l | egrep -iq '^0$'; then echo "$line"; else echo "$line" | perl -pe 's/^(\s+)?/\1'"$prefix"' /g' | perl -pe 's/, (\.|#|\[|[a-zA-Z]{1})/, '"$prefix"' \1/g'; fi; done | perl -pe 's/'"$prefix"' :root/'"$prefix"'/g' > bootstrap.scoped.css
Expanding on @Andrew Homeyer answer:
I got scoped styling of boostrap working in my Reactjs app by doing the following:
Bootstrap uses Grunt for its build system, with convenient methods for working with the framework. It's how we compile our code, run tests, and more.
Installing Grunt: To install Grunt, you must first download and install node.js (which includes npm). npm stands for node packaged modules and is a way to manage development dependencies through node.js.
Then, from the command line: Install grunt-cli globally with
npm install -g grunt-cli
. Navigate to the root /bootstrap/ directory, then runnpm install
. npm will look at the package.json file and automatically install the necessary local dependencies listed there. When completed, you'll be able to run the various Grunt commands provided from the command line.
less/bootstrap.less
from the downloaded source to the following:.bootstrap-scope {...pasted all @imports here...}
grunt dist
and copied the new dist folder into my projectimport './styling/bootstrap/css/bootstrap.min.css';
.Similar discussion here
Since the result of modifying less/bootstrap.less was not good enough for me (see why at bottom of post), I ended up filtering bootstrap.css :
var css = require('css'), fs = require('fs');
var prefix = '.bootstrap-scope';
var inFile = 'bootstrap.css';
var cssAst = css.parse(fs.readFileSync(inFile, 'utf8'));
prefixNode(cssAst);
console.log(css.stringify(cssAst));
function prefixSelector(sel){
if (sel.match(/^@/)) return sel;
var m = sel.match(/(^| )(body|html)($|\W.*)/i);
if (m)
return m[1] + prefix + m[3];
else
return prefix + ' ' + sel;
}
function prefixNode(node) {
if (node.selectors) {
node.selectors = node.selectors.map(prefixSelector);
} else if (node.stylesheet) {
node.stylesheet.rules.forEach(prefixNode);
} else if (node.rules) {
node.rules.forEach(prefixNode);
}
}
Since bootstrap.css is generated, one can also do it blindly (solution similar to Alexey's, but also handling a few corner cases):
perl -lpe 'BEGIN { $prefix = ".bootstrap-scope" } if (($indent, $s, $sep) = /^(\s*)([^@\s].*?)(\s*[,{])$/) { $s =~ /^(from|to)*$/ or $s =~ s/(^| )(body|html)($|\W.*)/$1$prefix$3/i or $s = "$prefix $s"; $_ = "$indent$s$sep" }' bootstrap.css
As for modifying less/bootstrap.css and calling grunt to generate dist/css/bootstrap.css (Andrew Homeyer's solution), it seems not working nicely (in bootstrap 3 at least) for some cases:
various mixins like .make-grid-columns (from less/mixins.xml) end up badly prefixed. Example:
.bootstrap-scope .col-sm-1,
.col-sm-2,
.col-sm-3,
the usage of "&" in LESS is limited:
.caret {
.btn-default & {
becomes
.btn-default .bootstrap-scope .caret {
instead of what we want:
.bootstrap-scope .btn-default .caret {