Truncate long links

Links / email addresses can be often quite long. Longer than available container width in our layout or even the width of the screen of a phone.

Sometimes we have no choice but to present those long links in the front-end. For example in search results or contact details.

One simple solution is to truncate a long line replacing it’s part with e. g. ellipsis.

Example:

verylongaddress.quitelongsubdomain.annoyinglylongdomainname.co.uk

becomes:

verylon…name.co.uk

or similar.

Truncated email address (left).

It is probably not an ideal solution but it is better than having an email wrap or overflow.

The code

I’ve created a simple JavaScript to truncate strings that are longer than their container.

# # ***
# #
# # Truncate long urls to fit in the container element without wrapping
# # 
# #


# SUBROUTINES

# ***
# String truncate
#
# truncates a string to the chars num specified, 
# replaces the middle part (roughly 30% from the begenning) with ellispys 
#  
#
String::trunc= String::trunc or (n) ->
   cut_pos= .5 # 0..1 - adjust to cut the string in different place
   if @length > n then @substr(0, n*cut_pos - 3)+'…'+@substr(@length-n*(1-cut_pos), Math.ceil n*(1-cut_pos)) else @


# ***
# Truncate url of an element to specified length
# (default 10 characters)
#
$.fn.html_truncate= (char_count=10) ->
   @.html @.attr('title').trunc(char_count)
   return


# ***
# convert pixels to em
# @params
#  target element, size in pixels
#
#  WARNING: this is a simplified version - font size of the target element must be specified in px in the css!
#
px2em= ($el, px_size) ->
   font_size= parseInt($el.css 'font-size') # this is 1em
   Math.floor px_size/font_size*1.9


# ### RUNTIME

setTimeout ->
   ##
   #  Run the function on all matched elements
   #  If the element is not a link itself then search for one inside this element.
   #
   #  The timeout here is to allow browser to load fonts and render the page
   #
   $('.str-truncate').each ->
      _$parent= $(@).parent()
      if undefined == $(@).attr('href')
         _$el= $(@).find $('a')
      else
         _$el= $(@)
      _$el.attr('title', _$el.html())
      _$el.html_truncate(px2em(_$el.parent(), _$el.parent().width()))
      return
, 150


resize_timeout = undefined
$(window).resize ->
   if resize_timeout
      window.clearTimeout resize_timeout
   resize_timeout = window.setTimeout((->
      # actual callback
      ##
      #  Same as above but without creating the 'title' attribute
      #
      $('.str-truncate').each ->
         _$parent= $(@).parent()
         if undefined == $(@).attr('href')
            _$el= $(@).find $('a')
         else
            _$el= $(@)
         _$el.html_truncate(px2em(_$el.parent(), _$el.parent().width()))
         return
      return
   ), 200)
   return
   
# # *** *** *** ***

How it works?

First we make a copy of the original string and put it in the title attribute of our link.

Then we convert the width of the parent container to the em width of the link’s font size. This part is a bit tricky and might not work with all kinds of fonts, so manual adjustment might be required. In my script I assumed a constant that works well for a standard, non-serif font similar to Helvetica.

Once we have the amount of characters that will fit inside the container we trim the original string to that length.

On window resize event we run the function again using the string from the title attribute as the reference.

Add a comment