Adding first and last classes to your field items

By default, Drupal's core field.module with add 'odd' and 'even' classes to your field items, but it won't add 'first' and 'last' classes! This can quickly be remedied by overriding the core field.tpl.php file with your own custom one.

I'd recommend first copying /modules/field/theme/field.tpl.php into your site's theme folder. For me, the destination was /sites/all/themes/grasmash/templates/field.tpl.php. Then clear your caches. This will force Drupal to check for new template files in your theme's directory, and select the new field.tpl.php as the prioritized template for generating fields.

Here's the business part of my customized field.tpl.php file:

<?php $max_delta = count($items) - 1; ?>
<div class="<?php print $classes; ?> clearfix"<?php print $attributes; ?>>
  <?php if (!$label_hidden): ?>
    <div class="field-label"<?php print $title_attributes; ?>><?php print $label ?>:&nbsp;</div>
  <?php endif; ?>
  <div class="field-items"<?php print $content_attributes; ?>>
    <?php foreach ($items as $delta => $item): ?>
      <div class="field-item<?php print $delta % 2 ? ' odd' : ' even'; ?><?php print $delta == 0 ? ' first' : ''; ?><?php print $delta == $max_delta ? ' last' : ''; ?>"<?php print $item_attributes[$delta]; ?>><?php print render($item); ?></div>
    <?php endforeach; ?>
  </div>
</div>

There are two important changes here:

  • <?php $max_delta = count($items) - 1; ?> counts the total number of field items in each field, allowing us to determine which field item should be given the 'last' class
  • <?php print $delta == 0 ? ' first' : ''; ?><?php print $delta == $max_delta ? ' last' : ''; ?> will print out our new sparkly classes.

You should note that this may add a small performance tax to your site by requiring PHP to count the $items array for every field, but I think that it is fairly negligible. Some people would prefer not to include this kind of logic in a template file at all. Let me know if you've got a better way!

Drupal Version Compatibility: 

Comments

div.field-item:first-child
div.field-item:last-child

Use http://selectivizr.com/ for pre IE9 support

CSS pseudo selector :last-child is not a good way to solve this problem because a lot of browsers don't support it ... Anyway its a CSS hack.

The way described here, using templates is much better.

Btw. I'm a frontend developer and wanted always use only CSS an Drupal backend to generate markup. Working with templates and make your own structure let's you feel much better ;)

Thanks for this article.

Thanks Alan. I generally stay away from CSS3 (unfortunately) given that it is not backwards compatible with other browsers, but I hadn't heard of selectivizr!

Seems like someone started a sandbox module to include the selectivzr library in Drupal:
http://drupal.org/sandbox/revagomes/1361416

On the other hand, there is at least one advantage of using the field.tpl.php file— it will remain backwards compatible even with javascript disabled.

Some people would prefer not to include this kind of logic in a template file at all. Let me know if you've got a better way!

You could also put those kind of alterations into the appropriate preprocess function.

If it were me, to simply add first and last class, It seems like it would be a lot less overhead to add a few lines of JQuery to do this. I also think it would be less of a performance hit.

That's not true ....
jQuery works on client side and php on the server. So it's obviously better for performance to use php. I don't think you will use a crappy server for your D7 Site/App.

Maybe file a patch? Seems to me this is an omission in core, as other kinds of lists in core have those classes.

Those sorts of classes are being removed from Drupal 8 already, as they're redundant. CSS can handle that just fine. first/last classes are only necessary for legacy browsers that are rapidly dying, and there are dozens of shiv libraries that will make them work in those older browsers.

I wouldn't put that into a template file, or anywhere else in PHP. It belongs in CSS, and people with older browsers that don't support the 10-year-old CSS 2 spec yet can eat the JS cost of the BC shivs as penance for using crappy browsers. :-)

Amend to Larry's approach

Add new comment

Plain text

  • No HTML tags allowed.
  • Lines and paragraphs break automatically.