I recently started integrating Twitter's excellent Bootstrap framework into a hobby project of mine, but hit a snag: Bootstrap uses a lot of fairly common CSS classnames (e.g. "row", "container", etc)... and many of these clashed with classes that I had already defined in my own code, resulting in a fine mess.
The obvious solution was to modify the Bootstrap CSS so that everything in there uses a common prefix... however, the creator of Bootstrap made it clear that no prefixing of Bootstrap CSS classes would be implemented. Fair enough, it's their library, their call - and I suppose writing "row" instead of something like "tb-row" makes more sense if you just start out. But it does make implementing Bootstrap into an existing project harder than it needs to be, and I really did not want to rename my own CSS classes.
An alternative: Namespacing
One way to avoid the CSS name conflicts would be to wrap the Bootstrap CSS classes into a new top-level namespace using the Bootstrap Less source code and then wrapping your Bootstrap-sensitve page elements into a suitable container (as suggested in this stackoverflow answer). Not really what I was aiming for - having an option to merely define a "$prefix" variable in Bootstrap source and recompiling would've been far nicer. But, alas, things are not that simple: the CSS classes are referenced heavily in the Bootstrap Javascript source files, negating the usefulness of such a "prefix" Less variable.
Solution: Prefixing via post-processing script
To address this issue I whipped up a quick Python script that edits the Bootstrap CSS and Javascript files and adds a prefix to any CSS classnames it finds. The prefix defaults to "tb-" (for "Twitter Bootstrap"), but can be easily changed (see the docs below).
Using it is simple: just supply it with the path to your Bootstrap installation (it expects the default Bootstrap directory structure to be in place). The script will then output modified versions of the CSS and Javascript files it finds, with a ".prefixed" tag added to the filename.
Finally, include these "prefixed" files in your project instead of the original Bootstrap CSS and Javascript files - now you can (and must) refer to all Bootstrap CSS classes by adding the "tb-" prefix to the name, e.g. "row" becomes "tb-row", etc.
The "bootstrap_namespace_prefixer.py" script is available from GitHub, or you can download it by clicking here.
Please note: this script works for me. YMMV, but let me know if something goes wrong and I'll take a look at it.
Documentation
The script expects a Bootstrap directory structure like the following:
/bootstrap - top-level bootstrap dir; this is the path that must be supplied to the script
/bootstrap/css - directory containing CSS files for Boostrap
/bootstrap/js - directory containing Bootstrap Javascript files
Call the script as follows:
$ python bootstrap_namespace_prefixer.py /path/to/boostrap/dirThe script will output the following files:
/bootstrap/css/bootstrap.prefixed.css - CSS with the added prefix
/bootstrap/css/bootstrap.min.prefixed.css - Minified CSS with the added prefix
/bootstrap/js/bootstrap.prefixed.js - Javascript using the prefixed classes
/bootstrap/js/bootstrap.min.prefixed.js - Minified Javascript using the prefixed classes
To change the classname prefix to something other than "tb-", edit the bootstrap_namespace_prefixer.py file and set the CSS_CLASS_PREFIX constant to whatever you want to use as a prefix.
Hello,
ReplyDeletethe Script is great! But it has a bug
In the file bootstrap.min.prefixed.css it will add the prefix to the both png files:
background-image:url("../img/glyphicons-halflings.sf_png");
background-image:url("../img/glyphicons-halflings-white.sf_png")}
The prefix was: sf_
thanks
Glad you find the script useful, and many thanks for pointing out the bug! I've pushed a fix to the github repository.
DeleteGreat tool, thanks a lot!
ReplyDeleteI think I found two possible bugs:
1) Prefix is not added to CSS styles defined that uses attribute selectors like
.tb-btn-large [class^="icon-"]
this should by replaced by
.tb-btn-large [class^="tb-icon-"]
2) Wrongly added prefix for filter-styles; for example:
filter: progid:DXImageTransform.Microsoft.gradient
is replaced by
filter: progid:DXImageTransform.tb-Microsoft.tb-gradient
Thanks for reporting these! I've included a fix for them in the latest version on github.
DeleteThanks for this post, really need to prefix the css (I searched another way to prefix with a kind of namespace as :
ReplyDelete@namespace tbootstrap
//All css of bootstrap
@end
and use it like : <_balise_ identifier_type='@bootstrap-name'> (for example)
I wrote crap, it doesn't exist as I wish :D
Hi,
ReplyDeleteI think I found another bug/problem. Your script does not prefix CSS-classes where addClass or removeClass calls in the JavaScript files are generated dynamically which breaks the functionality of the "Responsive navbar".
To fix the problem, the following (additional) replacements needs to be done by the prefix-script:
- this.$element[method]('in') => this.$element[method]('tb-in')
- $this[$(target).hasClass('tb-in') ? 'addClass' : 'removeClass']('collapsed') => $this[$(target).hasClass('tb-in') ? 'addClass' : 'removeClass']('tb-collapsed')
Best regards,
Jan
Thanks again for the report!
DeleteThe script actually does prefix CSS classes when JQuery's addClass and removeClass methods are dynamically generated, but the case you mention is different: the "collapsed" CSS class is never defined in any of the CSS source files (the script only recognizes CSS classnames that it has already seen in the actual CSS files when dealing with JavaScript in order to avoid potential false positives).
I had noticed that "collapsed" reference before, but decided against modifying it for some obscure reason. :-/
Anyhow, I've now added a mechanism to force specific CSS classes to be recognized in JavaScript, and "collapsed" will now be detected and prefixed as expected.
As for the first "this.$element[method]('in')" case: thanks, completely missed that one, fixed now.
Hi Francois,
ReplyDeletethanks for the update. The new version of the script fixes the bugs.
I found two more problems (replacements that are missed by your script):
1) CSS-File(s)
.tb-nav-list [class*=" icon-"] => .tb-nav-list [class*=" tb-icon-"]
2) JS-File (only in the minified version)
this.$element[b]("in") => this.$element[b]("tb-in")
Best regards,
Jan
Thanks again. I have fixed the script and pushed an update.
DeleteHi,
ReplyDeleteThis is a great script, I just can't get it to work, I am sure its me because I have nothing to do with Python what so ever but I would like to learn so I can use your script.
I have downloaded and install python on windows and have tried to run it through command prompt but it errors at line 34 saying cssfilename is invalid syntax. From the command prompt I have entered
C:\>py c:\prefixer.py c:\bootstrap\
Can you please let me know what I am doing wrong, and how I could do it better.
Thanks
Lee
Sounds like you are using Python 3 - this script was written for Python 2.7. I'll update the script syntax to conform to Python 3, but in the meantime you can either install Python 2.7, or use the "2to3" tool to update the script yourself; see http://stackoverflow.com/questions/10104805/python-2to3-windows-cmd for more info.
DeleteHi, I've updated the script - it now works fine in Python 3, and I've also made some modifications to ensure it works properly in Windows.
DeleteHi Francois, first of all: Thank you very much for this script. It saved me a lot of time :)
ReplyDeleteI use your script on windows, where I discovered, that .table-striped is not processed.
Thanks! I've updated the script to address this - the bug was introduced when fixes for the IE-specific filter-styles were added.
DeleteHi Francois,
ReplyDeletethank you for this script. it saved me a lot of time!
is there a way of "somehow" prefixing css which goes directly to html elements, like button, select, article ...
best Simon
If you're using less, you could use nesting. I.e.:
Delete.mybootstrap {
@import "reset.less";
@import "variables.less";
@import "...
}
br, m~
Hi Francois,
ReplyDeletei found a small bug, the script does not recognise following line
Line 928 unprefixed
animate = this.$element.hasClass('fade') ? 'fade' : ''
Line 928 prefixed
animate = this.$element.hasClass('tb-fade') ? 'fade' : ''
Thanks Simon, I've fixed this in the github repo.
DeleteHi,
ReplyDeleteI'm not familiar with Python but possibility to use this script is very interesting so I'm trying to give it a go... Unfortunately I'm getting this error:
Python 3.3.2 (v3.3.2:d047928ae3f6, May 16 2013, 00:06:53) [MSC v.1600 64 bit (AM
D64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> $python bootstrap_namespace_prefixer.py c:\bootstrap
File "", line 1
$python bootstrap_namespace_prefixer.py c:\bootstrap
^
SyntaxError: invalid syntax
>>>
Thannks for any help, need it so bad.
You seem to be starting the Python interpreter and then typing in "$python bootstrap_namespace_prefixer.py c:\bootstrap" into its interactive prompt - this is not going to work. The "$" is there just to indicate a command line prompt (lots of Linux shells use this as a prompt).
DeleteYou need to launch the script from the standard command line; in Windows you can do this by running "cmd.exe" to get to the command line, then cd'ing to the directory containing the script, and typing "python bootstrap_namespace_prefixer.py c:\bootstrap". Note: this assumes "python.exe" is on your system's path - please see the Python Windows docs for more info: http://docs.python.org/2/faq/windows
Thank you Francois! It works now. Perfect script saved my time.
DeleteHey Francois - great job and thanks for sharing this! I have a slightly different need, wondering if you could modify your script for such use case? Basically, unlike you, I really need to just namespace everything via wrapper class, so that I can specifically mark which portions of the page to use the bootstrap.css on, and which to leave out (internal corporate site, can't touch the legacy stuff, but ok to use on new projects, the problem is - they are intertwined). I've done as much with LESS without problem - wrapped everything in .bootstrapped and it separated the areas of implementation fine. The problem with JS is still valid though - this totally breaks things like modals for example. Would that be a lot of trouble to accommodate that scenario?
ReplyDeleteIn any case - thanks for what's already done!
Vlad
Actually resolved this myself, and it had nothing to do with bootstrap.js file. I am using this in conjunction with AngularJS and also UI-bootstrap, which is a collection of directives for AngularJS. So, in fact, I had to modify the ui-bootstrap.js and make sure that it attaches the created modal to my namespaced element, and not the 'body' element as it does by default (because then it's not really a modal since the namespaced bootstrap.css doesn't apply there)
ReplyDeleteSo, nevermind my request, I clearly wasn't looking at it right :)
I am very happy to be able to find this excellent article! After reading your article, I feel learned a lot of things
ReplyDeletesmall business outsourcing
Hi Francois,
ReplyDeleteI think I found a minor bug in your script: In the prefixed bootstrap.min.prefixed.js file
return this.$element.removeClass("tb-collapse")[b](a||"auto")[0].offsetWidth,this.$element[a!==null?"addClass":"removeClass"]("collapse"),this}
needs to be
return this.$element.removeClass("tb-collapse")[b](a||"auto")[0].offsetWidth,this.$element[a!==null?"addClass":"removeClass"]("tb-collapse"),this}
(column 19809 in my bootstrap.min.prefixed.js file)
Thanks again for the great tool :)
Jan
Does this work for 3.1.1?
ReplyDeleteProcessing CSS file: css/bootstrap-responsive.css
Failed to open file; skipping: css/bootstrap-responsive.css
Processing CSS file: css/bootstrap-responsive.min.css
Failed to open file; skipping: css/bootstrap-responsive.min.css
These were removed in Bootstrap v3.
Hello I m new in this field so i need your help for using this file i want to change my bootstrap css but i dont understand where i place this code in css can you kindly decsribe me steps how to use this script for css ids or class names to change
ReplyDeleteHi guys I am not a coder so don't know how to use this. I come from a design stand point knowing some css and html, visual. Is there a finished files somewhere that can be downloaded? thanks
ReplyDeleteHi, is this script compatible with bootstrap v3?
ReplyDeleteJoin many telephone gadgets with one of these adaptors to some individual socket. Modular attaches might be linked to one particular modular socket utilizing these kind of modular increase adaptors. Normal cabling construction is usually 6P6C straight-thru. For details : http://www.dueltek.com.au/collections/adsl-telephone-accessories
ReplyDeleteIn my view, if all web owners and bloggers made just right content as you probably did, the internet will probably be a lot more useful than ever before.
ReplyDeleteWhat is bootstrap and why should you use bootstrap?
ReplyDeleteThanks for the script. Can you please update this according to the materializecss. Same script works but there need some changes to make it working properly.
ReplyDelete