Tag Colors on the Blog Homepage

16 Jul 2021 9:44 PM    the blog jekyll
convert to local time zone


Right now, when you’re on a post, the tags (at least the ones that have colors) are correctly colored:

Post title with colored tag

However, when you look at that same post from the blog homepage, they’re not colored:

Post title with uncolored tag

This is rather annoying, and seems like it should be relatively simple to fix. Let’s get down to it.

First, we need to figure out where that java tag is being colorized in the first place. If we check _layouts/post.html, we find this:

{% for tag in page.tags %}
  {% assign css-class = "badge-info" %}
  {% for site_tag in site.data.tags %}
    {% if site_tag.name == tag %}
      {% assign css-class = site_tag.class %}
    {% endif %}
  {% endfor %}
  <a href="{{ "/tags/" | append: tag | relative_url }}" class="badge {{ css-class }}">{{ tag }}</a>
{% endfor %}

which seems to be using badge-info for all tags that aren’t in site.data.tags; for those, it uses site_tag.class (site_tag being the tag in site.data.tags that matches the current tag on the post). If we look in _data/tags.yml, we find this:

- name: swift
  class: badge-swift
- name: jekyll
  class: badge-danger
- name: java
  class: badge-java

which appears to be mapping these tags to CSS classes that already exist (I created the badge-swift and badge-java classes for the project langauge badges, while the badge-danger class comes with Bootstrap).


Now to figure out why these aren’t being applied on the blog homepage. If we look on blog.html, we see this:

{% for tag in post.tags %}
  <a href="{{ "/tags/" | append: tag | relative_url }}" class="badge badge-info">{{ tag }}</a>
{% endfor %}

Seems like I just forgot to adjust the code here when I added colors in the first place. Changing that excerpt to this:

{% for tag in post.tags %}
  {% assign css-class = "badge-info" %}
  {% for site_tag in site.data.tags %}
    {% if site_tag.name == tag %}
      {% assign css-class = site_tag.class %}
    {% endif %}
  {% endfor %}
  <a href="{{ "/tags/" | append: tag | relative_url }}" class="badge {{ css-class }}">{{ tag }}</a>
{% endfor %}

and voilà!

Post title with colored tag


But I think that we want the “Posts By Tag” section, even if it’s unfinished, to also use these colors. For now, let’s just convert these headings into their tag badges, which will use the colors as well. Heading back to blog.html:

<h2>Posts By Tag</h2>
{% for tag in site.tags %}
  <h4>{{ tag[0] }}</h4>
  <ul>
    {% for post in tag[1] %}
      <li><a href="{{ post.url }}">{{ post.title }}</a></li>
    {% endfor %}
  </ul>
{% endfor %}
<h2>Posts By Tag</h2>
{% for tag in site.tags %}
  <h4>{{ tag[0] }}</h4>
  <ul>
    {% for post in tag[1] %}
      <li><a href="{{ post.url }}">{{ post.title }}</a></li>
    {% endfor %}
  </ul>
{% endfor %}

(still can’t highlight more than one language at a time). Anyway, we see the <h4>{{ tag[0] }}</h4> section, which is what we want to change. Doing the same thing we’ve just done, we get:

<h2>Posts By Tag</h2>
{% for tag in site.tags %}
  {% assign css-class = "badge-info" %}
  {% for site_tag in site.data.tags %}
    {% if site_tag.name == tag %}
      {% assign css-class = site_tag.class %}
    {% endif %}
  {% endfor %}
  <h4 class="badge {{ css-class }}">{{ tag[0] }}</h4>
  <ul>
    {% for post in tag[1] %}
      <li><a href="{{ post.url }}">{{ post.title }}</a></li>
    {% endfor %}
  </ul>
{% endfor %}
<h2>Posts By Tag</h2>
{% for tag in site.tags %}
  {% assign css-class = "badge-info" %}
  {% for site_tag in site.data.tags %}
    {% if site_tag.name == tag %}
      {% assign css-class = site_tag.class %}
    {% endif %}
  {% endfor %}
  <h4 class="badge {{ css-class }}">{{ tag[0] }}</h4>
  <ul>
    {% for post in tag[1] %}
      <li><a href="{{ post.url }}">{{ post.title }}</a></li>
    {% endfor %}
  </ul>
{% endfor %}

This does NOT work. Here’s why:

<h2>Posts By Tag</h2>
{% for tag in site.tags %}
  {% assign css-class = "badge-info" %}
  {% for site_tag in site.data.tags %}
    {% if site_tag.name == tag %}
      {% assign css-class = site_tag.class %}
    {% endif %}
  {% endfor %}
  <h4 class="badge {{ css-class }}">{{ tag[0] }}</h4>
  <ul>
    {% for post in tag[1] %}
      <li><a href="{{ post.url }}">{{ post.title }}</a></li>
    {% endfor %}
  </ul>
{% endfor %}

In this case, tag is from site.tags, not site.data.tags. This means that it is provided by Jekyll, not me, and that it is an array with the first element being the tag name and the second being a list of posts with that tag. That’s why the second use of tag (the one that I didn’t just insert) is using tag[0] to show the tag name. So if we change to this:

<h2>Posts By Tag</h2>
{% for tag in site.tags %}
  {% assign css-class = "badge-info" %}
  {% for site_tag in site.data.tags %}
    {% if site_tag.name == tag[0] %}
      {% assign css-class = site_tag.class %}
    {% endif %}
  {% endfor %}
  <h4 class="badge {{ css-class }}">{{ tag[0] }}</h4>
  <ul>
    {% for post in tag[1] %}
      <li><a href="{{ post.url }}">{{ post.title }}</a></li>
    {% endfor %}
  </ul>
{% endfor %}
<h2>Posts By Tag</h2>
{% for tag in site.tags %}
  {% assign css-class = "badge-info" %}
  {% for site_tag in site.data.tags %}
    {% if site_tag.name == tag[0] %}
      {% assign css-class = site_tag.class %}
    {% endif %}
  {% endfor %}
  <h4 class="badge {{ css-class }}">{{ tag[0] }}</h4>
  <ul>
    {% for post in tag[1] %}
      <li><a href="{{ post.url }}">{{ post.title }}</a></li>
    {% endfor %}
  </ul>
{% endfor %}

we get exactly what we want. Of course, they should also probably link to the tag pages, but as those don’t exist yet, I’ll just stick in a TODO and call it a success.


Respond to this