Add "first" and "last" classes on blocks
Last modified: August 23, 2009 - 15:25
Sometimes, the first or last block in a region needs to be styled different than the rest. To get 'first' and 'last' classes on the first and last block in a region, you need to override two theme functions: theme_block() and theme_blocks().
1) Override theme_blocks()
<?php
function phptemplate_blocks($region) {
$output = '';
if ($list = block_list($region)) {
$blockcounter = 1; // there is at least one block in this region
foreach ($list as $key => $block) {
// $key == <i>module</i>_<i>delta</i>
$block->extraclass = ''; // add the 'extracclass' key to the $block object
if ($blockcounter == 1){ // is this the first block in this region?
$block->extraclass .= ' first';
}
if ($blockcounter == count($list)){ // is this the last block in this region?
$block->extraclass .= ' last';
}
$output .= theme('block', $block);
$blockcounter++;
}
}
// Add any content assigned to this region through drupal_set_content() calls.
$output .= drupal_get_content($region);
return $output;
}
?>2) Override theme_block()
<?php
function phptemplate_block($block) {
$output = "<div class=\"block block-$block->module $block->extraclass\" id=\"block-$block->module-$block->delta\">\n"; // in this line, the extraclass value is added as class
$output .= " <h2 class=\"title\">$block->subject</h2>\n";
$output .= " <div class=\"content\">$block->content</div>\n";
$output .= "</div>\n";
return $output;
}
?>That's it!

already overriding _block function phptemplate.engine
Thank you very much for the function... I was able to apply it to my theme.
I'm not entirely sure why this was, but my phptemplate was already overriding the theme_block function with a phptemplate_block() function in the phptemplate.engine file.
Once I thought about it it made sense, however, as I am using a block.tpl.php file...so I got this function to work by adding the phptemplate_blocks() function to my template.php file, then changing
class="block <?php print $block_classes; ?>to
class="block <?php print $block_classes.$block->extraclass; ?>in my block.tpl.php file. I'm kind of curious how I would override other theme functions that have already been overridden in the phptemplate.engine file as this was the approach I first attempted to no avail, but I'm just happy I got this to work.
----
http://www.johnpezzetti.com
Drupal 6 + Zen Theme
I had to do something different to add "first" and "last" classes to my blocks. The site I was working on is using Drupal 6 and its custom theme is based on Zen.
To add "first" and "last" classes to blocks in this situation, I had to add the following in my theme's template.php:
<?phpfunction themename_preprocess_block(&$vars, $hook)
{
static $counts;
if(!isset($counts)) $counts = array();
$region = $vars['block']->region;
if(!isset($counts[$region])) $counts[$region] = count(block_list($region));
$count = $counts[$region];
$extremity = '';
if($vars['id'] == 1) $extremity = 'first';
if($vars['id'] == $count) $extremity = 'last';
$vars['classes'] .= $extremity != '' ? ' ' . $extremity : '';
}
?>
Rémi
remiplourde.com
My preferred D6 method
For Drupal 6, I prefer this method (basically a rewrite of the D5 method above, the code goes in template.php):
<?php
function themename_blocks($region) {
$output = '';
if ($list = block_list($region)) {
$blockcounter = 1;
foreach ($list as $key => $block) {
$block->extraclass = '';
$block->extraclass .= ( $blockcounter == 1 ? ' block-first' : '' );
$block->extraclass .= ( $blockcounter == count($list) ? ' block-last' : '' );
$output .= theme('block', $block);
$i++;
}
}
// Add any content assigned to this region through drupal_set_content() calls.
$output .= drupal_get_content($region);
return $output;
}
function themename_preprocess_block(&$vars){
$vars['classes'] .= $vars['block']->extraclass;
}
?>
This method is (at least in theory) better for performance: block_list() is already called in themename_blocks(), so I don't want to call it again in themename_preprocess_block().
I noticed a typo in the above
I noticed a typo in the above code when I tried to implement it. It should be as follows:
<?php
function themename_blocks($region) {
$output = '';
if ($list = block_list($region)) {
$blockcounter = 1;
foreach ($list as $key => $block) {
$block->extraclass = '';
$block->extraclass .= ( $blockcounter == 1 ? ' block-first' : '' );
$block->extraclass .= ( $blockcounter == count($list) ? ' block-last' : '' );
$output .= theme('block', $block);
$blockcounter++;
}
}
// Add any content assigned to this region through drupal_set_content() calls.
$output .= drupal_get_content($region);
return $output;
}
function themename_preprocess_block(&$vars){
$vars['classes'] .= $vars['block']->extraclass;
}
?>
For my own uses I only needed to mark the last block in a class, so I addapted this as follows:
<?php
function csc_zen_blocks($region) {
$output = '';
if ($list = block_list($region)) {
$blockcounter = 1;
foreach ($list as $key => $block) {
$block->is_last = ( $blockcounter == count($list) ? true : false );
$blockcounter++;
$output .= theme('block', $block);
}
}
// Add any content assigned to this region through drupal_set_content() calls.
$output .= drupal_get_content($region);
return $output;
}
function csc_zen_preprocess_block(&$vars, $hook) {
if ($vars['block']->is_last) :
$vars['classes'] .= ' region-last';
endif;
}
?>
––
Jeremy Stoller
Senior Graphic Artist
California Science Center
Hey Jeremy, Thank you, and
Hey Jeremy,
Thank you, and the rest of the folks on this post for this snippet. I just added it to my customized Basic theme. I did notice a small issue, however. B/c of the way that you have the counter setup, if there's only one block in the region, it adds both the first and last classes. I'm not sure if that's intentional - you could argue it either way. Just something for folks to keep in mind.
Cheers,
Sean
ThinkShout.com
Sean Larkin
Think!Shout