Thursday, April 5th, 2012
With some CSS3 properties, like box-shadow or text-shadow, it is possible to have a comma-separated list of values for multiple shadows like this:
.element {
box-shadow: 0 1px 3px #eee, 0 5px 10px #f5f5f5;
}
This works well with regular ol’ CSS, but with CSS3 support being what it is, we sometimes want to use LESS mixins for properties like box-shadow. Given we need various vendor prefixes in our mixin, our example changes to this:
.box-shadow(@shadow) {
-webkit-box-shadow: @shadow;
-moz-box-shadow: @shadow;
box-shadow: @shadow;
}
.element {
.box-shadow(0 1px 3px #eee, 0 5px 10px #f5f5f5);
}
However, when you use LESS with this approach, the compiler will choke on the unexpected comma between those two shadows. With recent versions of LESS, one might think @arguments is the solution, but that only gets you past the compiling problem. You’ll still end up with a final output that strips that ever important comma between the two shadows. While the most straightforward approach doesn’t work, there are at least two ways of making comma-separated values work in LESS.
The first is to use a local throw-away variable:
.box-shadow(@shadow) {
-webkit-box-shadow: @shadow;
-moz-box-shadow: @shadow;
box-shadow: @shadow;
}
.element {
@shadow: 0 1px 3px #eee, 0 5px 10px #f5f5f5;
.box-shadow(@shadow);
}
This works because we’re declaring a value that’s a literal string because it’s a variable and the mixin respects the entire contents of that variable, including the comma. We currently use this method across Bootstrap for it’s simplicity and because we didn’t know of any other options at the time until we discovered this second method.
Your other option is to escape the value when you call the mixin:
.box-shadow(@shadow) {
-webkit-box-shadow: @shadow;
-moz-box-shadow: @shadow;
box-shadow: @shadow;
}
.element {
.box-shadow(~"0 1px 3px #eee, 0 5px 10px #f5f5f5");
}
This effectively does the same thing as the local variable: it ensures the value passed to the mixin is a string and not a list of options compressed into a single value. The syntax is a still fairly clear, but also more succinct. One potential downside to note is that this method doesn’t enable you to place line-breaks and spaces between values to stack them in your code for improved readability, meaning this wouldn’t compile:
.element {
.box-shadow(~"0 1px 3px #eee,
0 5px 10px #f5f5f5");
}
If that’s your style, you can accomplish this with the local variable method:
.element {
@shadow: 0 1px 3px #eee,
0 5px 10px #f5f5f5;
.box-shadow(@shadow);
}
All in all, it depends on your own style and conventions. Whatever method you opt for, I do recommend being consistent with it throughout entire projects.
It’s worth noting that in the next version of Bootstrap, we’ll be using the second method (escaping when we call the mixin). It’s less code to write and those familiar with LESS shouldn’t be caught off guard by the escaping.
Monday, April 2nd, 2012
Bootstrap wasn’t my first open-source project, but it’s definitely the largest and most successful, largely thanks to Jacob and the community of course. Since open-sourcing Bootstrap seven months ago, I’ve realized a few things about open-source that I’d like share with you all.
Communication is paramount
No matter the success of an open-source project, folks using your hard work begin to depend on you and what you’re doing. Communication becomes more important as the age and use of the project increases. When’s the next release, and what will it include? Does the license allow for X, Y, or Z? What about support for third party plugins like A or B? Questions like this are bound to arise, so you have to be proactive to fight the brunt of it and keep your sanity.
To do that in Bootstrap, we use our GitHub wiki to share a roadmap, license info, a changelog, and even contribution standards. We also use our Twitter account and new blog to post about changes and releases.
People can be jerks
Let’s get this one out of the way, because it doesn’t happen often, but when it does, it sucks in a big way. Just like in real life, some folks can be jerks online. This can be from lack of context on either person’s end, assuming someone’s an idiot, or simply being too aggressive. It sucks, but it can happen. When it does, keep a level head and get past it so you can help all the other awesome folks out there.
People can be fucking awesome
Speaking of awesome, sometimes people can just be fucking awesome. My own personal credo is to “Help awesome people do awesome shit” and I stand by that through and through. To date, Bootstrap is the best way I can help talented folks do their work, and so far it’s been a blast. There are plenty of smart, diligent, and hardworking people out there who just want to help you out or learn from you. Embrace it, learn from it, and pass it on.
Getting complete context on issues is hard
Just like bug reports in a typical web project, getting the complete picture around an issue submitted on GitHub can be difficult. Inability to reproduce a particular bug, difficulty in communicating across languages, dealing with opposite levels of experience, working with different versions of the same codebase, and more are all cases that you might come across on an open-source project.
Figure out a system that works well for you (in many cases, we require a live demo or jsfiddle) and communicate that to your followers. Stick to it and know that sometimes it just takes a bit more time and patience.
It’s all worth it
I hope you come away knowing the positive outweighs the negative in this post because when it comes right down to it, open-sourcing Bootstrap was one of the best things to happen to me personally and professionally. I’ve been able to help thousands of people do their work better and faster—all while helping them learn a bit more as they go. I’ve gotten to work with a lot of awesome people, had a blast doing it, and learned a great deal. Bootstrap has been worth every second I’ve put into it and I hope to keep it up for a long time to come.
TL;DR: Open-source is awesome, sometimes work is hard, be excellent to each other, do what you love, fuck yeah.
Monday, March 12th, 2012
A new version of Bootstrap is out today with a ton of bug fixes (over 100 closed issues), documentation improvements, and a few new features. Here’s a curated list with some details where appropriate. Download the latest from the Bootstrap docs.
Before we begin, I want to note that you’ll have to upgrade to the LESS 1.3 to compile 2.0.2. For those using LESS.js, download the latest. For those using LESS via npm, run this in your Terminal to update:
sudo npm install less -g
And you should be good to go. Not downloading the latest or running the update means you’ll see LESS spit out some nasty errors and it won’t compile.
Now, let’s check out what’s new.
Documentation updates
- All docs pages now have distinct titles, such as Scaffolding · Twitter Bootstrap.
- Updated the Apple touch icons (now black on black instead of the blue grid) and fixed the links to them in the docs.
- Added new global styles docs section to the Scaffolding page.
- Required use of HTML5 doctype
- Overview of global typographic and links details
- Mention of our embedded CSS reset via Normalize.css
- Added version number to the download button on the docs homepage.
- Updated progress bars section to simplify how the classes stack and more clearly indicate the available optional classes and styles.
- Added a new example, SoundReady.fm, to the homepage
- Added various sizes to the docs for button groups
Resolved bugs
- Removed all IE7 hacks and floats from
.input-prepend and .input-append, however, this requires you to ensure there is no whitespace in your code between .add-on and the input.
- In
.input-prepend and .input-append, added ability to use add-ons on both sides when you chain the selectors.
- Updated lingering
.btn-dark reference to .btn-inverse.
- Fixed issue with content being cut off in
.tab-content for tabbable sections.
- Updated
.navbar .container to use width: auto; to start and then reset the fixed widths via the #gridSystem mixin (it’s a little dirty, but required to avoid adding another class).
- Modal footer buttons are now aligned by their parent via
text-align: right; instead of float: right on the button level. This was changed to allow the use of .pull-left and .pull-right to align buttons easily. Double check your button order with this change!
- Fixed problem where default striped progress bar was green instead of blue.
- Fixed CSS selector used for
input and textarea grid sizes to properly apply the CSS (was input > .span* and now is input.span*).
New features
- Horizontal dividers support added to nav lists
- Added basic version of badges
- Added visible/hidden classes for devices
- Added support for buttons in input-prepend/append component
- Added .navbar-fixed-bottom support
- Added .dropup support for dropdown menus to pop them upward instead of downward (this is automatically done for the newly added fixed bottom navbar).
- Added mixin for new image replacement technique
- Added pause on hover for the carousel
- Added tons of new variables for typography, buttons, forms, dropdowns, navbar, and more for the LESS pros out there. These variables have also been reflected on the Customize page.
- Added new horizontal description list variation
- Added
.disabled class support to the pager component (also added a mention of this to the docs)
- Added
.well-large and .well-small classes for extending the well component
Responsive changes
While not a bug fix or a docs update, I wanted to specially call out this responsive CSS change. We have moved the padding from .container within the <767px layout to body. This ensures a bit more control over containers, rows, and more when setting background colors and such.
New grid mixins
Last, but not least, Jacob has rewritten the grid system mixins to utilize some new features in LESS 1.3. Nothing changes for the compiled CSS, but the LESS we use to generate that code is more succinct and can now fully utilize any number of grid columns when you customize.
For a full issue-by-issue rundown of the release, check out the now closed 2.0.2 milestone on GitHub.
Friday, March 2nd, 2012
Cascading styles is at the core of CSS—hell, it’s in the name—but experience has shown that building systems with too many cascading styles can be detrimental. Some times it’s completely necessary to just stop the cascade.
Let’s take the modal of Bootstrap as an example.
<div class="modal">
<div class="modal-header">
<h3>Modal title</h3>
</div>
<div class="modal-body">
<h3>Modal subheader</h3>
<p>Content for the modal, like additional text and forms, goes here.</p>
</div>
<div class="modal-footer">
<button class="btn">Done</button>
</div>
</div>
Notice how we namespace classes at key levels—each class name begins with modal-as a prefix. Class name prefixing makes our code more durable and easier to maintain, but it also better enables us to scope styles to only the relevant elements.
Consider this snippet of CSS used to style the modal heading:
.modal h3 {
text-align: center;
}
By using this generic selector, we inadvertently change the styles of the h3 in the .modal-body. We’ve introduced an instance of cascading styles—any h3 throughout the .modal will be center aligned. Therefore, if we wanted the other instances of h3 to be left-aligned, we’d have to override our brand new styles with something like this:
.modal .modal-body h3 {
text-align: left;
}
It’s worth noting that this example isn’t without its flaws, but that’s the point. With a little more time and thought, one can easily avoid this problem, avoiding extra lines of code and more complications in the overall system. Had we done things differently and altered our selector, our CSS might look like this:
.modal-header h3 {
text-align: center;
}
By limiting the scope of a selector, we reduce the likelihood that we need additional code down the line by strengthening each component and limiting the effects of their styles. If done right, we can create an entire system of independent and durable, yet still flexible, components. It’s a promising approach I think, but one not to employ with an iron first.
Some CSS should be allowed to cascade. Base typography, links, and the such are prime examples of something not to redeclare over and over again. This would only serve to weigh down a project and make it even more unmanageable. Instead, the goal as always is to strike a balance.
Find ways to isolate components and make them more durable by limiting the scope of their CSS. You’ll discover that components can be more easily rearranged without causing adverse effects and the amount of code necessary will likely decrease.
Monday, February 27th, 2012
A recent question on Stack Overflow regarding Bootstrap’s dropdown menus got me thinking I should do a few posts on some of our design decisions. Folks seem curious about certain aesthetics and behavior, and I’d love to shed some light if I can. Beyond explaining existing decisions, I hope these posts can help guide future updates to the docs as well.
To start, let’s talk dropdowns.
Appearance
Before Bootstrap 2 launched, our dropdowns were confined to the topbar (now the navbar) and were thus styled to be white text on black background. This fit with what we do on Twitter.com and helped the topbar feel more complete with the dropdowns as a natural extension of that style. However, we knew we wanted dropdowns to work in a number of components, so we flipped the color scheme back to black on white.

This resulted in improved contrast for the text (especially for typeahead) and made dropdowns work much better for buttons and the like. This gave us a standardized design and cleared up a lot of CSS had we chosen to keep the previous inverted colors. Simpler appearance, simpler codebase.
Behavior
There has always been contention between hover and click events in interaction design. In general I am against using hover as a trigger because things can get messy quickly. The best (worst?) example of this may have been hovercards on Twitter.com from a couple years back. They were great in terms of their content and utility, but not so great in the fact that they seemed to fire without the user intending them to. Inevitably we dropped them and now have a mini profile modal with the latest redesign.
In Bootstrap, we use a mix of both hover and click though–hover for tooltips and popovers, clicks for dropdowns and more. What it really boils down to is user intent. The purpose of a hover state is to indicate something is clickable (underlined text) or to provide some quick information (full URL in a tooltip). The purpose of a click is to actually do something, to take an explicit action. Opening a dropdown is an explicit action and should only happen on click.
Additional notes
It behooves me to mention a few other quick thoughts on our dropdowns:
- The aesthetic was derived from menus OS X. They’re super simple, elegant, and scalable.
- Prior to open sourcing Bootstrap, the dropdowns were actually fired on hover. We changed this because as soon as your cursor leaves a dropdown, it disappears.
- The caret in a dropdown link is the equivalent of underlining a link: it provides some affordance for what will happen when you click this element. Don’t mistake that for providing enough information to pop the dropdown on hover though.
- Because we use a click to trigger the dropdown in most implementations, there is no option for a parent link (one of the primary complaints in that Stack Overflow article). Pointing back to OS X and other toolbars, I don’t see this as a huge issue as it promotes our advocacy of using clicks to carry out an action instead of hovers.
And that’s it—dropdowns in Bootstrap explained. Stay tuned for more posts like this in the future. If you’d like me to elaborate on another particular feature of Bootstrap, please hit me up on Twitter or send me an email.