This will show how to create a tag cloud for a jekyll blog using ruby to render the HTML and CSS to style it.
Start with an empty jekyll project or an existing project:
jekyll new jekyll-tagcloud-demo && cd jekyll-tagcloud-demo
Make sure that the archives plugin is configured to generate archive and tag index pages:
The jekyll-archives
plugin must be listed in the Gemfile
:
gem 'jekyll-archives'
And in the _config.yaml
:
plugins:
- jekyll-archives
jekyll-archives:
enabled:
- year
- month
- tags
- categories
layout: 'page'
layouts:
year: year
month: month
tag: tag_and_category
permalinks:
year: '/:year/'
month: '/:year/:month/'
tag: '/tag/:name/'
category: '/category/:name/'
The 3 layouts for index pages must be created. Example layouts are available from the jekyll-archive plugin documentation.
Copy the following code to _plugins/tagcloud.rb
:
module Jekyll
# render a tag cloud
class RenderTagCloud < Liquid::Tag
def initialize(tag_name, text, tokens)
super
end
def render(context)
base_url = context['site.baseurl']
tags = context['tags']
return unless tags.class == Array
tags.reject! {|i| i.nil? }
site_tags = context['site.tags']
by_length = site_tags.values.map(&:length)
max = by_length.max
min = by_length.min
cloud = tags.map do |t|
tag_size = site_tags[t].length
"<div class=\"tagcloud-tag #{size_tag(min,max,tag_size)}\">"\
"<a href=\"#{base_url}/tag/#{t.downcase}\">"\
"#{t}"\
"</a>"\
"</div>"
end.join("\n")
"<div class=\"tagcloud\">#{cloud}</div>"
end
private
def size_tag(min, max, count)
diff = (max - min)
if count < (min + (diff * 0.1))
'tagcloud-tag-s'
elsif count < (min + (diff * 0.3))
'tagcloud-tag-m'
elsif count < (min + (diff * 0.5))
'tagcloud-tag-l'
else
'tagcloud-tag-xl'
end
end
end
end
Liquid::Template.register_tag('render_tagcloud', Jekyll::RenderTagCloud)
Then create a tags.html
file with following content:
---
layout: page
title: All Tags
permalink: /tags/
---
<div class="tagcloud">
{% capture site_tags %}{% for tag in site.tags %}{{ tag | first }}{% unless forloop.last %},{% endunless %}{% endfor %}{% endcapture %}
{% assign tags = site_tags | split:',' | sort %}
{% render_tagcloud %}
</div>
It will generate a tag cloud for all site tags.
If you like to have a tag cloud under every post you may add the following to your _layout/post.html
:
{% assign tags = page.tags | sort %}
{% render_tagcloud %}
This will generate the HTML for tag clouds like:
<div class="tagcloud">
<div class="tagcloud-tag tagcloud-tag-xl"><a href="/tag/jekyll">jekyll</a></div>
<div class="tagcloud-tag tagcloud-tag-xl"><a href="/tag/tagcloud">tagcloud</a></div>
</div>
Whats missing is still some CSS to style the tags.
An example sass would be:
.tagcloud {
.tagcloud-tag {
display: inline;
white-space: nowrap;
padding: 0.6em;
}
.tagcloud-tag-s a {
// default font size
color: $cyan;
}
.tagcloud-tag-m a {
font-size: 1.1em;
color: $blue;
}
.tagcloud-tag-l a {
font-size: 1.3em;
color: $indigo;
}
.tagcloud-tag-xl a {
font-size: 1.6em;
color: $red;
}
}