Mark Otto

Deep thoughts by one Mark Otto.
Web Platform Designer at Twitter. Creator of Bootstrap. Broheim.

Powered by Fusion

Comma-separated values in LESS mixins

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.

Learnings from open-sourcing Bootstrap

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.

Bootstrap 2.0.2 released

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

Resolved bugs

New features

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.

Stop the cascade

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.

Designing dropdowns in Bootstrap

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.

Dropdowns in Bootstrap

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:

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.