Improving link display for print - Jekyll edition
When I’m making websites I often like to (and sometimes have to) think about print styles. That is, how the page looks when you click ‘print’. What’s the best way to display links when printed on a piece of paper?
By default the browser puts the link next to where it appears on the page. It looks like this:
What I like instead is to put a footnote at the bottom of the page (print only) for each link. So it looks like this:
For a long time I used code from Adrian Rosselli2 who in turn improved on the 2005 article from Aaron Gustafson at A List Apart3.
The above uses javascript, and it’s always niggled me that I could probably generate it all when I build the website, avoiding the use any javascript at all. Here’s how I did it for Jekyll.
First, put the following code in the _plugins
directory and call it link-numbering.rb
require 'nokogiri'
require 'uri'
module Jekyll
class LinkNumbering < Liquid::Block
def initialize(tag_name, markup, tokens)
super
end
def render(context)
output = super
doc = Nokogiri::HTML.fragment(output)
site = context.registers[:site]
# Get the page object from the context
page = context.registers[:page]
page_links = context.registers[:page_links] ||= {}
page_link_counter = page_links[page['id']] ||= 0
doc.css('a:not(.noprint)').each do |link|
page_link_counter += 1
sup = Nokogiri::XML::Node.new('sup', doc)
sup['class'] = 'footnote'
sup.content = page_link_counter.to_s
link.after(sup)
# Add the link to the page links hash
page_links[page['id']] = page_link_counter
end
# Generate the list of links
link_list = doc.css('a:not(.noprint)').map { |link| link['href'] }
if link_list.any?
link_container = Nokogiri::XML::Node.new('aside', doc)
link_container['id'] = 'LinkContainer'
link_list_element = Nokogiri::XML::Node.new('ol', doc)
link_list_element['id'] = 'LinkList'
link_list.each do |link|
link_item_element = Nokogiri::XML::Node.new('li', doc)
# Check if the link is absolute or relative using URI module
site_url = site.config['url']
uri = URI.parse(link)
if uri.relative?
# Prepend the site URL if the link is relative
link = "#{site_url}#{link}"
end
link_item_element.content = link
link_list_element.add_child(link_item_element)
end
link_container.add_child(link_list_element)
doc.add_child(link_container)
end
doc.to_html
end
end
end
Liquid::Template.register_tag('link_numbering', Jekyll::LinkNumbering)
In short:
- It counts up the links that don’t have the class
noprint
and are inside alink_numbering
block - It puts a number after every applicable link in the page
- It generates a list of links into an
<aside id="LinkContainer">
element.
Then in your template you need to wrap your content e.g.:
{% link_numbering %}
{{ content }}
{% endlink_numbering %}
You then need to hide the stuff in your CSS:
sup.footnote, #LinkContainer {
@apply hidden;
}
Then make it show up when you click print, also in your CSS:
@media print {
#LinkContainer{
@apply block;
}
}
I’ve excluded all the extra styling because you probably want to customise it, but you can see mine for yourself in the CSS of this page, and in Rosselli’s original post (he breaks the list into two columns which is a nice idea).
Remember, if there are any links in your post that you don’t want to appear in the list of links, just use the noprint class e.g. <a href="www.example.com" class="noprint">Example link</a>