Adding a class to a block in Drupal 7: Block Class module vs. preprocessing
All right, short version first. If you want to add a class to a block in Drupal 7, here are two methods:
- Using the Block Class module. This provides the option to add a class to any block (standard block, menu block, views block, block from a module, etc.) from the block edit screen.
- Using preprocessing to add classes to different blocks based on the module name they came from and their delta - e.g. block-3 or menu_block-7. There's a code example from this year's CapitalCamp on the Modular Stylesheets - Design 4 Drupal Gist. I tweaked it for Omega. Here's what I dropped in preprocess/preprocess-block.inc. Remember to replace MYTHEME with your theme name.
function MYTHEME_alpha_preprocess_block(&$vars) {
/* Set shortcut variables */
$block_id = $vars['block']->module . '-' . $vars['block']->delta;
$classes = &$vars['attributes_array']['class'];
/* Add classes based on the block delta */
switch ($block_id) {
/* Add .badge class to block #14 */
case 'block-14':
$classes[] = 'badge';
break;
/* Add .form class to block #20 */
case 'block-20':
$classes[] = 'form';
break;
}
}
Why You Want to Add Classes to Your Blocks
Drupal blocks provide several selectors for themers to latch onto when trying to style blocks. One of the more widely used selectors is .block-block-[id] (e.g. .block-block-8). This selector lets you apply your CSS directly to one unique block. Unfortunately, it carries some notable drawbacks:
- Lack of reusability. If you want to reuse that theming for another block, you have to go back and edit your CSS to add other block IDs to the selectors. A chunk that used to apply to only .block-block-8 might now be getting used by .block-block-11 and .block-block-16. If a content admin creates a block and wants to apply the look and feel of an existing block, he or she may not be comfortable editing the CSS, and you'll probably get sick of adding more and more CSS selectors to your chunk as new blocks get added.
- Block ID inconsistencies.* If you create a new HTML block (as opposed to a views or module block) in a dev/staging environment first, style it, and then re-create it on prod, you run the risk of a different block ID on prod. For example, if there were only 9 blocks on dev and you created the 10th, it would be .block-block-10. If, during the time when you were theming, a new block got created on prod, that other block would become the 10th block and your block (yet to be created) would be the 11th block or higher. Your .block-block-10 CSS would have to be rewritten accordingly.
Using the block ID method causes more problems than it's worth because (among other reasons) good web design creates reusable templates -- consistent design elements shared by items that all meet the same criteria.** Theming each little piece individually isn't efficient. But if you create groups for each type of block, you can reduce work and save yourself a headache later. That's where adding classes to blocks comes in.
Picking the Method That's Right for You
As with all things in Drupal, there's more than one way to do this. Using the Block Class module and doing preprocessing have different implications for your site. The next two sections are intended to provide you with an idea of each method's use case.
The Case for Block Class
- Content admins can learn to use it. Block classes can be added or deleted through the Drupal interface -- which means a savvy content administrator can feasibly be trained to use this. If you have a frequently used block style that you anticipate your admins reusing in the future, you can give them a little freedom by enabling them to apply it themselves instead of relying on you.
- The block ID can change with no consequences. You don't have to know the block ID to theme the block, and if you create a new block, you can just drop the new class in the field on the edit screen -- no code update needed. Preprocessing, as you can see from the code above, does rely on block IDs to tell it when to add a class, so you have to go back and add a case to that function every time you add a new block that should use your style.
The Case for Preprocessing
- You can move your theming between environments without database updates. Preprocessing lives in code; the Block Class fields live in the database. This means that if the block IDs don't change, you can push it up with your theming and everything will get applied without you having to open the blocks and make edits. If you have many blocks to theme and aren't expecting their IDs to change, it's much faster to use this method. And if block IDs do change, you can edit your code, push it to dev, push it to staging, push it to prod -- with git, that's a fast process, still faster than editing a bunch of blocks by hand. In fairness to both approaches, I should note that you can sidestep all of this hassle by creating your blocks/adding your classes on prod, so you only have to do it once.
- It's a step toward relying less on modules and more on code (when appropriate). Helper modules are great, and they have a time and place. But there's something to be said for solving a theming problem within the theme layer. I know, a theoretical "pro" is kind of a cop-out, but taking a second thought, or even a third, before downloading helper modules gives me a cleaner site and makes me think more creatively about how to solve similar problems. For example, once you've had an introduction to preprocessing, you might want to try using it in other ways -- say, adding taxonomy-based classes to the body of a page.
In my opinion, either method is fine. It's all about what suits your constraints and your workflow. I will say that if I see any possibility of a client or non-themer needing to apply pre-developed styles, I'll use Block Class.
Notes
*Purists, or people who are really good at following processes, may point out that you can neatly avoid block ID inconsistency problems by always creating your blocks on prod, and pulling the database down to dev and staging. This relies on having your site builders, themers, and back-end devs all on the same page and gets more challenging with a bigger team, but if you can make it work, you'll save a lot of sanity. ↩
**Speaking of templates, if you want to create template files for different groups of blocks, consider Block Theme. This module is overkill if you just need to add a class, but great if you need to change the markup. ↩