When Bootstrap Attacks!
@pamelafox
press space bar for the next slide
a bit of background...
⟱
coursera
![](http://frontend-architectures.appspot.com/images/coursera.png)
a modern web app?
Modern...
![Backbone logo](http://frontend-architectures.appspot.com/images/backbonelogo.png)
+
![Python logo](http://frontend-architectures.appspot.com/images/pythonlogo.png)
+
![Django logo](http://frontend-architectures.appspot.com/images/djangologo.png)
Not so modern...
![](http://frontend-architectures.appspot.com/images/phplogo.jpeg)
+
![](http://frontend-architectures.appspot.com/images/mysqllogo.jpeg)
too many bootstraps
Modern App: Bootstrap 2.1
Legacy Codebase: Bootstrap 1, Bootstrap 2.0
A SIMPLE GOAL:
PORT TO BOOTSTRAP 2
⟱
i'll JUST Follow
THE upgrade guide...!
![](http://dl.dropbox.com/u/10998095/Screenshots/59fp-n~vp25d.png)
2 days later
![](http://dl.dropbox.com/u/10998095/Screenshots/19g6zbs_y3aq.png)
1 month later
![](http://dl.dropbox.com/u/10998095/Screenshots/zz47xu_fr7sv.png)
bring in the recruits!
![](http://dl.dropbox.com/u/10998095/Screenshots/0y-1n-cav_p_.png)
bootstrapv2athon!
a week of q/a!
![](http://dl.dropbox.com/u/10998095/Screenshots/byd4bdatiaxy.png)
FInally, 1 month later...
![](http://dl.dropbox.com/u/10998095/Screenshots/3whxe7is41tt.png)
![](http://dl.dropbox.com/u/10998095/Screenshots/8-92oq-g8fig.png)
upgrading css
frameworks shouldn't
be that hard.
...so why was it?
⟱
my, grandma, what a big codebase you have...
207 *.template.php files
351 *controller.php files
143 *.js files
25 *.css files
class names, class names, everywhere!
HTML, CSS, PHP, PHPed JS
![](http://dl.dropboxusercontent.com/u/10998095/Screenshots/srout6wwf7v9.png)
least greppable
class names ever
grep "alert" * -R
80
grep "label" * -R
329
grep "success" * -R
364
grep "info" * -R
1153
BOOTstrap: its js, too!
![](http://dl.dropbox.com/u/10998095/Screenshots/6y_~hmrp0xyx.png)
if i could turn back time....
aka what I'll do differently next time.
⟱
use less spaghetti,
more architecture
![Backbone logo](http://frontend-architectures.appspot.com/images/backbonelogo.png)
⬇
![Jade logo](http://frontend-architectures.appspot.com/images/jadelogo.png)
⬇
![Stylus logo](http://learnboost.github.io/stylus/assets/stylus.png)
...but just one architecture!
![](http://frontend-architectures.appspot.com/images/chart_architectures_optimal.png)
use namespaced
bootstrap class names
grep 'tbs-alert' * -R
:%s/tbs-alert/tbs-alert2 * -R
Issue 1287: Prefix Bootstrap classes
Adding Prefixes to Bootstrap CSS classes
DON't use bootstrap
class names directly
<button class="coursera-submit-button">Sign Up</button>
.coursera-submit-button
@extends .btn
@extends .btn-info
&:hover
@extends .btn:hover
@extends .btn-info:hover
don't use class names in your js libraries
wysihtml5/editor.js: var defaults = {'prefix.css': ''}
var $toolbar = $(toolbarTemplate({prefix:options['prefix.css']}))
toolbar.js.jade:div(class=prefix+"-toolbar", role="toolbar", title="HTML editing toolbar")
coursera.editor.js:new WysiEditor({'prefix.css': 'coursera-wysihtml5'});
coursera.editor.styl: .coursera-wysihtml5
padding 0
Dynamic Selectors
don't use class names
in your js
<button class="coursera-submit-button">Sign Up</button>
<script>
$('.coursera-submit-button').on('click', signUp);
</script>
vs.
<button class="coursera-submit-button coursera-submit-js">Sign Up</button>
view.$('.coursera-submit-js').on('click', signUp);
vs.
<button class="coursera-submit-button" data-js="signup">Sign Up</button>
view.$('form [data-js=signup]').on('click', signUp);
test your frontend
mocha/chai/jsdom:
view.$('.course-forum-thread-showmore').click();
chai.expect(view.$('.course-forum-your-threads-listing tr:visible').size())
.to.be.equal(25);
chai.expect(view.$('.course-forum-thread-showmore').is(':visible'))
.to.be.equal(false);
selenium:
def expand_all_lectures(self):
sections = self.get_els('.course-item-list-header')
for section in sections:
if 'contracted' in section.get_attribute('class'):
section.click()
self.wait_for(lambda: 'contracted' not in section.get_attribute('class'))
diff your frontend
![](http://dl.dropbox.com/u/10998095/Screenshots/iv7w4-ql93e8.png)
![](http://dl.dropbox.com/u/10998095/Screenshots/183tl4~vub4f.png)
![](https://coursera.atlassian.net/secure/attachment/10936/course-description_v1.jpg)
Automatic: Needle: Selenium+Nose
from needle.cases import NeedleTestCase class BBCNewsTest(NeedleTestCase): def test_masthead(self): self.driver.get('http://www.bbc.co.uk/news/') self.assertScreenshot('#blq-mast', 'bbc-masthead')
Also: Perceptual Diffs, PhantomCSS, CasperJS, SlimerJS
Manual Flow: Firefox screenshot + Kaleidoscope
CSS can break you.
use protection.
When Bootstrap Attacks!
By pamelafox
When Bootstrap Attacks!
- 15,630