Login

Avoid widows using a template filter

Author:
jcroft
Posted:
February 25, 2007
Language:
Python
Version:
Pre .96
Score:
28 (after 34 ratings)

Support good typography! Avoid widows!

"Widows" are single words that end up on their own line, thanks to automatic line-breaks. This is an no-no in graphic design, and is especially unsightly in headers and other short bursts of text. This filter automatically replaces the space before the last word of the passed value with a non-breaking space, ensuring there is always at least two words on any given line. Usage is like so:

{{ blog.entry.headline|widont }}

It's a simple tag, but good typography is one of the hallmarks of a well-designed site that separates it from amateurish counterparts.

Note: The idea and name "widont" is copped directly from Shaun Inman, who wrote a similar feature for WordPress.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from django.template import Library, Node

register = Library()

def widont(value):
    bits = value.rsplit(' ', 1)
    try:
        widowless = bits[0] + " " + bits[1]
        return widowless
    except:
        return value

register.filter(widont)

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 2 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 2 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 9 months, 2 weeks ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 10 months, 1 week ago
  5. Help text hyperlinks by sa2812 11 months ago

Comments

obeattie (on February 27, 2007):

Thanks for this - looks like this could prove very useful!

#

paching (on March 1, 2007):

Nice little trick I didn't know about! Just a couple notes;

If there happens to be an HTML tag such as a link on the last word, this would break it. However for simple headers, I suppose this isn't a problem. In my own code I'm putting this inside a text conversion function where I'm already keeping track of tags, anyway :)

Also, it could be implemented as a simple one-liner:

return ' '.join(value.rsplit(' ', 1))

#

obeattie (on March 11, 2007):

Just one little gotcha...

The template should ensure that it is using a string... so Line 6 should read:

bits = str(value).rsplit(' ', 1)

Therefore, if an object which is not a string is passed to it, it's string method will be called to ensure that the filter will work as intended.

Otherwise, this is brilliant!

#

amr-mostafa (on April 22, 2007):

Nice one! Thanks

#

Please login first before commenting.