61

I have an existing website with lots of old pages and forms laid out with tables which I am trying to gradually transition to CSS. I want to use the Twitter Bootstrap stylesheets - particularly the styles for forms - but only on sections of pages where I have explicitly requested them. For example, I might surround the whole form in a div like so:

<div class="bootstrap">
 <!-- everything in here should have the Bootstrap CSS applied -->
 <form>
   <p><label for="text_input">Label</label><input type="text" id="text_input" /></p>
 </form>
</div>

I want all other forms to remain the same as they are now, because I won't be able to change them all at the same time. Is there a simple way to do this? I could go through every single style in the Bootstrap CSS and add a parent selector (e.g. 'p' would become 'div.bootstrap p'), but that would take a long time and it would be easy to miss styles.

Edit: If such a thing isn't possible, is there a free tool which can extract all the styles from a file, add a prefix and then save them back again?

pwaring
  • 3,032
  • 8
  • 30
  • 46
  • 5
    Have you looked into [less](http://lesscss.org) ? Because you could put brackets around the whole thing and call it a day. – Sherbrow Aug 06 '12 at 16:21
  • 1
    I'd heard of less before, but wasn't aware it could help with this sort of problem. I eventually used SASS (recommended by someone else) which seems to do the same thing. – pwaring Aug 07 '12 at 08:18
  • I just used an online SASS Compiler and Compressor, http://sassmeister.com/ and http://www.shrinker.ch/. – pixelbobby Aug 11 '14 at 02:58
  • There are a few tools that does *not* require compiling , e.g. http://www.css-prefix.com/ , but they really work strangely sometimes (always check the CSS validity ... )... – jave.web Jan 26 '17 at 11:42
  • Another way is to abstract the problem and do it through regular expression using some basic editor e.g. Notepad++ - see: http://stackoverflow.com/questions/11161198/prepend-all-css-selectors – jave.web Jan 26 '17 at 19:07

7 Answers7

46

For Bootstrap 3, it's easier if you use less:

Download the Bootstrap source code and make a style.less file like this:

.bootstrap {
    @import "/path-to-bootstrap-less.less";
    @import "/path-to-bootstrap-responsive-less.less";
}

Finally, you have to compile the less file; there are many alternatives

https://github.com/cloudhead/less.js/wiki/Command-Line-use-of-LESS https://github.com/cloudhead/less.js/wiki/GUI-compilers-that-use-LESS.js

Or use npm to install less then compile the style.less file to style.css:

npm install -g less
lessc style.less style.css
Brendan Nee
  • 5,087
  • 2
  • 33
  • 32
inzurrekt
  • 516
  • 1
  • 4
  • 5
  • 14
    There should be an option on the bootstrap customization page to add an optional prefix. There are many use cases for this. – Jens Feb 02 '14 at 19:37
  • @Jens I looked and couldn't fix a way to add a pre-fix, http://getbootstrap.com/customize/#less-variables – pixelbobby Aug 11 '14 at 02:23
  • @pixelbobby There isn't one. What I actually meant is that it is a good idea to have it and they should add it on the page. For now the only option is compiling it yourself like inzurrekt suggested. – Jens Aug 11 '14 at 13:07
  • ^ Ha, interesting ambiguity. I wonder if it would have been clearer if you'd written "There ought to be an option..." The difference between "ought to" and "should" has always been unclear to me, but I think this is the use case for it! – graemeboy Oct 27 '14 at 12:13
  • For those who like things to be automatic here's a nix derivation to do it all for you (on Linux or macOS): https://gist.github.com/3noch/c9e523b90d91c8984ba833dfc88d087c – Elliot Cameron Nov 03 '16 at 03:39
29

The final fix was to use SASS (recommended by someone off-site), as that allows you to nest elements and then automatically produce the final CSS. Step by step the process is:

  1. Concatenate the two Bootstrap files (bootstrap.css and bootstrap-responsive.css) into bootstrap-all.css.
  2. Create a new SASS file, bootstrap-all.scss, with the content div.bootstrap {.
  3. Append bootstrap-all.css to bootstrap-all.scss.
  4. Close the div.bootstrap selector by appending } to bootstrap-all.scss.
  5. Run SASS on bootstrap-all.scss to produce a final CSS file.
  6. Run YUI Compressor on the final file to produce a minimised version.
  7. Add minimised version to head element and wrap everything I want the styles to apply to in <div class="bootstrap"></div>.
pwaring
  • 3,032
  • 8
  • 30
  • 46
  • Thanks, I might try that a bit later down the line as it's more elegant than my bash+SASS solution. – pwaring Aug 07 '12 at 08:31
  • For step #2 just create a new file with .SCSS? – SearchForKnowledge Oct 09 '14 at 12:26
  • Hi I know this is old, but I ran into this problem recently as well. A alternative solution is to use [bootstrap-sass](https://github.com/twbs/bootstrap-sass) and do something along the lines of: .bootstrap-scope{@import "bootstrap";}. See resulting Codepen [here](http://codepen.io/anon/pen/wBwrPm?editors=010). – ksrb Nov 08 '14 at 23:51
  • 1
    Worked perfectly for me. I know the question in the comments above is old, but for anyone else that finds this question, yes, you just create a file with the .scss extension for Step 2.. – Sherwin Flight Dec 06 '15 at 01:56
  • this answer might work for some stuff, and will inevitably break other stuff. Just imagine that bootstrap applies styles to the HTML and body to fix bugs? well, you just removed those. It is hacky – Toskan Dec 05 '17 at 03:29
  • Fantastic solution! Works like charm. – Jay Nov 01 '20 at 19:48
15

I came up with a CSS solution if you can't use LESS/SASS because of work/other reasons.

  1. I used this site, http://www.css-prefix.com/, and copy/pasted bootstrap.min.css into there. I set prefix ='.bootstrap' and spacer =' '. It will prefix everything with .bootstrap except not perfectly.
  2. If you do a grep for '.bootstrap @media', you will find that the first class to the right of the opening bracket doesn't have .bootstrap as the parent. Add .bootstrap to all these occurrences, about 68 for me.
  3. Then replace all '.bootstrap @media' with '@media'.
  4. Final step is to replace all '.bootstrap @' with '@' (should be about 5 occurrences).

Example:

.bootstrap @media (min-width:768px){.lead{font-size:21px}}

needs to be replaced to

@media (min-width:768px){.bootstrap .lead{font-size:21px}}

Kind of a brute force method, so definitely try the LESS/SASS method above first.

<div>
  No Bootstrap
</div>
<div class="bootstrap">
  Yes Bootstrap
</div>
postelrich
  • 3,274
  • 5
  • 38
  • 65
6

I have an easy solution.

  1. Copy bootstrap css content to this (http://css2sass.herokuapp.com/) online css to scss/sass converter.

  2. Add your tag information (e.g. div.bootstrap{ ) to the start of scss content and close the tag at the end.

  3. Copy the whole scss content to this scss to css converter (https://www.sassmeister.com/) and convert it :)

4

I wasn't satisfied with any of these answers. Using Less to scope the rules created all sorts of defects. Clearfix, for example was all messed up. And rules like button.close became button.bootstrap close instead of what I really wanted: .bootstrap button.close.

I took a different approach. I'm using PostCSS to process the out-of-the-box CSS that is delivered with Bootstrap. I'm using the Scopify plugin to scope every rule with .bootstrap.

This mostly gets there. Of course, there are the html and body rules that become .bootstrap html and .bootstrap body which become non-sensical. No worries... I can just write a PostCSS transform to clean them up:

var elevateGlobalsPlugin = postcss.plugin('elevateGlobals', function(opts) {
    return function(css, result) {
        css.walkRules(function(rule) {
            rule.selector = rule.selector.replace('.bootstrap html', '.bootstrap');
            rule.selector = rule.selector.replace('.bootstrap body', '.bootstrap');
        });
    }
});

Now, I can isolate all Bootstrap styling by adding a class="bootstrap" at the top level.

Brian Genisio
  • 47,787
  • 16
  • 124
  • 167
  • 2
    Brian, can you give a bit more info on your solution? What does the js look like? – tofutim Feb 06 '16 at 01:24
  • @tofutim What are you looking for? This is the extent of the JS that I use in my gruntfile as a plugin to PostCSS. My Gruntfile brings in PostCSS and applies the Scopify plugin, and then the JS above. The output is a version of Bootstrap which has `.bootstrap ` before every rule. – Brian Genisio Feb 07 '16 at 21:37
3

That's tough. You can't Apply different css stylesheet for different parts of the same web page.

I suspect the only way to do this is to make a separate file for your content to take the bootstrap styles, and i-frame it into the page like this:

<iframe src="/content-to-take-bootstrap-styles.html" ></iframe>

then in content-to-take-bootstrap-styles.html reference the bootstrap style-sheet in the header. But then you have all the complications of iframes -- e.g.: the iframe element won't grow to accommodate the length of your content.

Community
  • 1
  • 1
Faust
  • 15,130
  • 9
  • 54
  • 111
  • Thanks for the confirmation (and useful link to other question) - I suspected that was the case. Making an iframe would be a bit too much of an ugly hack, but fortunately I found SASS which seems to have done what I wanted. – pwaring Aug 07 '12 at 08:26
  • 1
    There is now a new "scope" limiter that does allow you to apply different stylesheets to different parts of the page. – Acyra Feb 08 '14 at 09:33
  • @Acyra: that's interesting. So from here: http://css-tricks.com/saving-the-day-with-scoped-css/ it looks like you would need to embed the style-tag inline and surround the appropriate content that's *in scope*. – Faust Feb 08 '14 at 10:59
1

You can use ready to use isolated css for Bootstrap 4.1 (compiled with LESS) -

https://github.com/cryptoapi/Isolate-Bootstrap-4.1-CSS-Themes

It have isolated css for themes -

To use Bootstrap CSS, simply wrap your HTML in a div with the class bootstrapiso, like so:

<div class="bootstrapiso">
<!-- Any HTML here will be styled with Bootstrap CSS -->
</div>

And use any css style from folder css4.1 like so:

<head>
<link rel="stylesheet" href="css4.1/bootstrapcustom.min.css" crossorigin="anonymous">
...
</head>

// https://github.com/cryptoapi/Isolate-Bootstrap-4.1-CSS-Themes

Done!

Jeff
  • 11
  • 1