Personal Blog Post:

Hacking the 'Read more' Link in Drupal

| Tags and categories.

When displaying a list of node teasers, Drupal includes a 'Read more' item within a list of links at the bottom of each node. Other items in this list include links for adding comments, the number of page reads and other node-specific actions. For users not familiar with Drupal, this link can be easily missed, making it not particularly obvious that there is more information available.

There has been quite a bit of web discussion about the 'Read more' link in Drupal, with some people advocating the Read more link module, adding some custom PHP in the node template to re-process it and even changes to core to put it to a better location.

My need on this site was simply to make it a bit more visually obvious. I wasn't keen on the extra module approach as the site is already pretty heavy on that front. Using the node.tpl.php template wasn't an option either as a couple of modules I use format nodes outside this system (such as the FAQ module) and I really didn't want to start adding all sorts of new type-specific node template files in my theme. Obviously changes to the core are out as that makes updating/upgrading much more work and I have enough trouble with the couple of add-in modules I did need to modify.

The solution turned out to be unbelievably simple and achievable entirely in CSS.

A CSS Solution

Basically, I needed to do four things to the 'Read more' link:

  • Move it out of the middle of the links list to the far right-hand side where there was some space,
  • Make it orange, bold and italic,
  • Append an ellipsis, preferably within the link itself, and
  • Not do any of this when printing.

The CSS required to do all this is as follows:


@media screen 
{ /* Only when rendering to the screen. */

  #content ul.links li.node_read_more 
  { /* Move it off to the right. */ 
    text-align: right;
    float: right;
  }
  
  #content ul.links li.node_read_more a 
  { /* Make the link orange, bold and italic. */ 
    color: #F60 !important;
    font-style: italic;
    font-weight: bold;
  }
  
  #content ul.links li.node_read_more a:after 
  { /* Append an ellipsis to the link. */
    content: "...";
  }
  
}

As it happens, Drupal always gives the 'Read more' list item a class of node_read_more. I wasn't sure if you could relatively/absolutely position an individual li element independent of the parent ul, but some trial and error proved that you could. Thus setting the float and text-align properties to "right" was all it took. The #content before each element/class refers to a div.id I use in my custom theme to wrap just the page content, to differentiate it from headers, footers and other stuff.

The next tricky bit was adding the ellipsis (yes, I know it's completely unnecessary and a folly). However I am deeply appreciative of the guy who thought to add the :before and :after pseudo-elements to the CSS spec. Boy, are they useful...

NOTE: Of course, it turns out that the before and after pseudo-elements are implemented in every browser except IE6 and IE7 (though IE8 works fine). I found a work-around for this called ie7-js, which uses Javascript to fix many of the HTML and CSS standards-compliance issues in older IE browsers. It was dead simple to include (referenced directly from Google) and seemed to work a treat, though there is a slight delay after rendering before the ellipsis are actually added.

I didn't use it in the end as, again, I'm trying to be pretty conservative with the size and complexity of each page and it seemed overkill just for a few extra dots. However, if you are interested, the code required to add it to your page header is shown below. For an explanation of the surrounding comments, see my Browser Detection post.


<!--[if lt IE 8]>
<script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script>
<![endif]-->

Finally, the @media rule allows you to include media-specific styles within the same stylesheet. I hate having to maintain separate stylesheets for printing and browsing as you always forget to change both. The reason for wanting to modify the 'Read more' link only on the screen is that it isn't actually displayed when printing so there is no point wasting cycles formatting it. In a later part of the stylesheet I use the following to turn off stuff I don't want to see in a printed version.


@media print 
{ /* Only when rendering to a printer. */

  /* Turn things off */
  form.fivestar-widget,
  #content div.node-links,
  #content ul.tabs 
  {
    display:none;
  }
  
}

You should be able to peruse the results in the front page of the site and in all other teaser lists.

Your rating: None Average: 3.1 (7 votes)