Ask Ben: Truncating The Event Titles In A Calendar Display
Say you need to display items on the calendar by text description. You need to show the "title" of the event(s) in an abbreviated form. For example:
Long Event Title Goes Here Ben NadelMight need to be abbreviated as
Long Event Title. . .
How would you repeatedly determine where to truncate an event title for a calendar?
For something like this, you could go the route of actually truncating the text and appending a "..." if necessary. But to me, this feels like a very pre-CSS solution to the problem. Now that we live in an age of CSS with super awesome layout and formatting control, I say, let's not truncate the data, let's try to truncate the display.
In order to do this, we are going to assume that our even titles are wrapped in anchor tags. After all, you probably need to be able to click on them to get the event details right? Well, we are gonna give those anchors an explicit height and width. Once we have the dimensions set, we can tell the anchors to "hide" everything that "overflows" the given content dimensions. If we want to get snazzy (and possibly irritate the end user???) we can actually have the height of the event change on mouse over to reveal the full title.
Take a look at this code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Long Event Title Display Truncation</title>
<style type="text/css">
table.calendar {}
table.calendar td {
border: 1px solid ##999999 ;
font: 11px verdana ;
padding: 3px 3px 3px 3px ;
vertical-align: top ;
}
table.calendar tr.header td {
background-color: ##F0F0F0 ;
font-weight: bold ;
text-align: center ;
}
table.calendar tr.day a.number {
background-color: ##666666 ;
border: 1px solid ##333333 ;
color: ##FFFFFF ;
display: block ;
font-size: 9px ;
margin: 0px 0px 3px auto ;
text-align: center ;
text-decoration: none ;
width: 15px ;
}
table.calendar tr.day a.event {
border: 1px solid ##CC0000 ;
color: ##333333 ;
display: block ;
height: 30px ;
margin-bottom: 2px ;
overflow: hidden ;
text-decoration: none ;
width: 99% ;
}
table.calendar tr.day a.event:hover {
height: auto ;
}
table.calendar tr.day a.event span {
background-color: ##CC9999 ;
border-bottom: 1px solid ##CC0000 ;
color: ##FFFFFF ;
display: block ;
font-size: 9px ;
line-height: 13px ;
text-align: center ;
white-space: nowrap ;
}
</style>
</head>
<body>
<table width="100%" class="calendar">
<colgroup>
<col width="13%" />
<col width="15%" />
<col width="15%" />
<col width="15%" />
<col width="15%" />
<col width="15%" />
<col width="12%" />
</colgroup>
<tr class="header">
<td>
Sun
</td>
<td>
Mon
</td>
<td>
Tue
</td>
<td>
Wed
</td>
<td>
Thr
</td>
<td>
Fri
</td>
<td>
Sat
</td>
</tr>
<tr class="day">
<td>
<a href="##" class="number">2</a>
</td>
<td>
<a href="##" class="number">3</a>
<a href="##" class="event">
<span>8:00 AM</span>
This is a really long even title that
will cause the link to become much too
long for a nice display.
</a>
<a href="##" class="event">
<span>10:00 AM</span>
This is a really long even title that
will cause the link to become much too
long for a nice display.
</a>
</td>
<td>
<a href="##" class="number">4</a>
</td>
<td>
<a href="##" class="number">5</a>
</td>
<td>
<a href="##" class="number">6</a>
</td>
<td>
<a href="##" class="number">7</a>
</td>
<td>
<a href="##" class="number">8</a>
</td>
</tr>
</table>
</body>
</html>
If you run this in your browser, it will look something like this:
Notice that even though we have a lot of text in the event title, only a small amount of it shows through. But, since our a:hover CSS rule gives us:
table.calendar tr.day a.event:hover {
height: auto ;
}
... that means that when we hover our mouse over the event, the height of the event link will no longer be an explicit height and the display will transform into this:
Now, I am not saying this is the best thing to do - the mouse over shifting of the physical space might drive the user a bit batty. What I like about this, though, is that it is a dynamic display with very little effort; no Javascript, not crazy markup - just some clean XHTML and CSS. Plus, if this were a public-facing site, then this would be much better for search engine optimization over its text-truncation counter-part (since more relevant data is present on the page).
The real magic here is in the "overflow: hidden ;" CSS rule.
Want to use code from this post? Check out the license.
Reader Comments
Be You TEEEE Full!
I'd have to say it's got to be the best, most efficient use of the right technology for the solution. I agree that literally truncating the data would be sort of the caveman solution--not that there is ANYTHING wrong with cavemen.
@Dave,
Glad you like. And who doesn't like the Caveman - He has his time and place :)
. . .Being a more recent descendant of cavemen, I probably would have used some sort of CF string manipulation on the Query field along with some cockamaymee, hard-coded, string-length limiter that would end up cutting some strings off much earlier than truly necessary and others much later.
I hear you... who hasn't built some sort of ColdFusion user defined function like:
Truncate( strText, intLength, strSuffix )
It's just, the more I learn about CSS, the more I see places I want to apply it.
I'm not sure I like this approach. First, as Ben mentioned, the hover pseudo-class would bounce the display all over the place - even when the user is just trying to move the cursor from point A to point B. Batty, indeed. Second, using this approach without the pseudo-class would arbitrarily truncate the text. Not in fact, but certainly perceptually. The text might even appear to be truncated in the middle of a letter. That's just not cool.
Instead, I prefer a variation of the so-called caveman approach. :-)
1. First, truncate the text to some character limit
2. Strip off any word characters at the end of the remaining string so you're not breaking in the middle of a word (much less a letter :-)
3. Add an ellipsis to the end of the text, if necessary.
4. Apply a title attribute to the element that includes the text which contains the entire content of the text string.
Now I have a logical break in the text while still having access to the entire content.
To me that just makes more sense.
@Ben - I understand your point about wanting to use CSS, but the right tool for the right job, you know? I don't know of a cross-browser CSS method to implement this kind of thing (which doesn't mean one doesn't exist).
Unfortunately text truncation is a real and necessary evil sometimes. What would happen if i put http://areallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallylongurl.com in your comment thread?
Also you don't always have control over the css/html markup that your data may be being plugged into. An example would be my cfTimeline (http://cfsilence.com/blog/client/cfTimeline/mxnaTimeline.cfm) - lets say there wasn't a way to specify the width of an event label...
@Rob,
I am certainly on board with NOT using the :hover to change the event. I knew it would go bad even as I was writing it.
I do think use of the Title attribute is an excellent idea. Ultimately, I think the best result would be the combination of CSS and Javascript to do some very nice stuff.
I think if you are going to go with the character limit, then you are going to need a different character limit depending on the time available. For instance, using an explicit height, you might decide that events are 20px -to- 15 minutes scale (therefore a longer event would have more visible text). I did not demo this, but I think this would be the right way to do. If you go this way, you might want to say that an hour event can have 20 characters, but a two hour even might allow 40 characters.
Just some thoughts... I am not saying either way is the right way. I know that I use gMail for my eMail and in their Subject "teaser" they do something similar to this where the text is being hidden depending on the size of the window. This does not bother me at all, even when parts of letter get cut off. I think part of it is just what you are used to.
All be it to say, as you say, right tool for the right job... gonna depend on what your users want.
@Todd,
Hopefully on your browser (fingers crossed), you will notice that your really really long link actually just gets truncated by the overflow of the "content column". I agree that some form of truncation is required in order to make your display look decent. I choose CSS truncation in my case because it is much easier than parsing the text and trying to figure out where to truncate what.
Also, as far as not being able to control the CSS of the thing you are plugging the data into.... this is not the decision of the user (truncation), it is the decision of the developer. The user should be able to enter what ever they want... text vs. CSS truncation is up to the application / developer to make happen.
Also, let's realize that the context is going to dictate some usage stuff. For instance, my content area above is rather narrow for a calendar display. For something like this, I probably wouldn't try to cram all that text in there using just CSS/XHTML as it is very tight.
If, however, my calendar could fill up a whole screen, this would be very different and my layout and markup would be different. So again, kind of as an add on to the "right tool, right job", its really "right solution, right situation".
Just to throw my glove into the ring, I've used a similar solution to what Ben has outlined here for more web UIs than I can count. The major benefit that I see is that it is semantically correct. That is, things like web spiders and other automated tools aren't being given bogus half-complete information. You're not going to get that benefit from a hard-truncated solution.
As for reflow problems, in this specific case I'd probably expand a dynamically-generated copy of the calendar item with absolute positioning so as not to disturb the flow. Sure, you could probably hack your way to a CSS-only solution, but I doubt it would be any more elegant than one using extremely simple JS behaviors.
Either way, the bonus here would be that you could show a bunch of other information that might clutter up the default calendar view (who set up the meeting, start and end times, locations, etc.).
If you wanted to get fully-buzzword-compliant, I bet you could mash in calendar microformat information, thus making the page even more semantically juicy.
@Rick,
Thanks for contributing some real world experience insights.
Thanks for your nice contrubution.