Post Formatting

Or, how to distinguish headers and subheaders


When I started looking into some of the finer points of how my Hugo site looked, I had a few post formatting questions:

  • Why does the sub-header look different in the post listing and page view?
  • Why do the date posted and tags not appear in the page view but do in the post listing?

First, to the Docs!

As has been helpful on a number of occasions, I went to the Hugo docs to see if I could find what I needed there. I started with singe page templates which led me to themes/beautifulhugo/layouts/_default/single.html.

Looking in that file, I didn’t quite see what I was looking for.

1
2
3
<article role="main" class="blog-post">
  {{ .Content }}
</article>

Instead of something as simple as {{ .Content }} I was looking to find something that resembled more of what I was seeing in themes/beautifulhugo/layouts/_default/list.html.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
<article class="post-preview">
  <a href="{{ .Permalink }}">
    <h2 class="post-title">{{ .Title }}</h2>

    {{ if .Params.subtitle }}
      <h3 class="post-subtitle">
        {{ .Params.subtitle }}
      </h3>
    {{ end }}
  </a>

  <p class="post-meta">
    {{ default (i18n "dateFormat") .Site.Params.dateformat | .Date.Format | i18n "postedOnDate" }}
  </p>
  <div class="post-entry">
    {{ if .Truncated }}
      {{ .Summary }}
      <a href="{{ .Permalink }}" class="post-read-more">[{{ i18n "readMore" }}]</a>
    {{ else }}
      {{ .Content }}
    {{ end }}
  </div>

  {{ if .Params.tags }}
    <span class="post-meta">
      {{ range .Params.tags }}
        #<a href="{{ $.Site.LanguagePrefix | absURL }}tags/{{ . | urlize }}/">{{ . }}</a>&nbsp;
      {{ end }}
    </span>
  {{ end }}

</article>
...

In particular, I was looking for something that called out the following elements:

  • {{ .Title }}
  • {{ .Params.subtitle }}
  • {{ i18n "postedOnDate" }}
  • {{ .Params.tags }}

Custom layouts/posts/single.html

NOTE: In the header, I use “posts” instead of “post” - I thought I remembered seeing something about using singular in some places and plural in others but in the end, in order for this to take effect I needed the directory in layout/ to match the name of the directory in content/.

My first attempt to inject what I was looking for into the single.html was to insert something between <div class="container" role="main"> and <div class="row"> (the first and last rows in the code below). I used what I had seen in the list.html as a reference.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<div class="container" role="main">
  <div class="row">
    <article class="post-preview">
      <h2 class="post-title">{{ .Title }}</h2>
      {{ if .Params.subtitle }}
        <h3 class="post-subtitle">{{ .Params.subtitle }}</h3>
      {{ end }}
      <p class="post-meta">
        {{ default (i18n "dateFormat") .Site.Params.dateformat | .Date.Format | i    18n "postedOnDate" }}
      </p>
      {{ if .Params.tags }}
        <span class="post-meta">
          {{ range .Params.tags }}
            #<a href="{{ $.Site.LanguagePrefix | absURL }}tags/{{ . | urlize }}/"    >{{ . }}</a>&nbsp;
          {{ end }}
        </span>
      {{ end }}
    </article>
  </div>
  <div class="row">

I should have realized this wouldn’t work because even the single.html that I was starting from did not include the {{ .Title }} and other elements. What I did get was something like the following:

But I did learn that what I was looking for was something that apparently wraps the single.html partial.

A Break, Then A Breakthrough

I took a break from digging into this topic. It felt like a time-sink that I wasn’t likely to break out of any time soon.

When I came back at it, it was after I had been digging into the Pygments to Chroma Migration and was thinking more about CSS as a result.

As it turns out adding the following two lines to the main.css from the theme addressed the sub-header font weight issues I was seeing.

1
2
3
4
5
6
h2.posts-subheading {
  font-weight: 300;
}
h2.pages-subheading {
  font-weight: 300;
}

This seems to be because of a typo in either the theme or in Hugo. The following block shows what I think was supposed to address this issue of changing the font-weight: 800 to font-weight: 300 for sub-headings but they use the singular instead of plural for both post and page.

1
2
3
4
5
6
7
8
9
.intro-header .page-heading .page-subheading,
.intro-header .post-heading .post-subheading {
  font-size: 27px;
  line-height: 1.1;
  display: block;
  font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 300;
  margin: 10px 0 0;
}

My guess is that it is a problem in the BeautifulHugo theme since I couldn’t find subheading in the Hugo repo but I was able to find it in the theme’s repo. I created a new issue to see if what I found could be confirmed or refuted. (Keep reading, turns out I was wrong… mostly.)

Just One More Thing To Check

I should have gone to bed. But instead, I took one more pass down a line of thinking I had been going on before I took that long break. I needed to look at how Content Types are defined in Hugo.

Spoiler: back in the “Custom layouts/posts/single.html” section I made a note about singular vs plural issues.

When you look closely at the Content Types documentation it says that types are always singular when creating a Type layout directory. By contrast in the Assign a Content Type section it gives examples using the plural.

This apparent guidance - to use posts instead of post - conflicts with what the Beautiful Hugo theme expects. Renaming my content/posts/ directory to content/post/ allowed me to remove the custom main.css I had made to compensate for this percieved bug in the theme. Feeling a bit sheepish, I updated and closed the issue I had created ~2h earlier.

Update: Later I also “fixed” the formatting on the “About” page by moving content/pages/ to `content/page/‘.

When I resolved this conflicting type issue, I also found that the date posted was now showing at the top of the posts! That led me to noticing that there is a post_meta.html partial that is referenced in both layouts/partials/header.html and layouts/index.html in the theme.

At first, I tried adding the tags to the post_meta.html but ultimately ran into issues where tags would show up twice on the main post listing. Instead I found that if I replace two blocks that looked like the following in header.html:

1
2
3
{{ if eq .Type "post" }}
  {{ partial "post_meta.html" . }}
{{ end }}

With something like the following which adds in the tags conditionally:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{{ if eq .Type "post" }}
  {{ partial "post_meta.html" . }}
  {{ if .Params.tags }}
    <br/>
    <span class="post-meta">
      {{ range .Params.tags }}
        #<a href="{{ $.Site.LanguagePrefix | absURL }}tags/{{ . | urlize }}/">{{ . }}</a>&nbsp;
      {{ end }}
    </span>
  {{ end }}
{{ end }}

That got me what I was looking for.

But then I noticed that the Posts page wasn’t using the same formatting I would be expecting from post_meta.html. I looked at layouts/_default/list.html in the theme and found that it had the following:

1
2
3
4
<p class="post-meta">
  {{ default (i18n "dateFormat") .Site.Params.dateformat | .Date.Format | i18n "postedOnDate" }}
</p>
<div class="post-entry">

Instead of what I would be expecting:

1
2
3
4
<p class="post-meta">
  {{ partial "post_meta.html" . }}
</p>
<div class="post-entry">

Making that change in a copy of layouts/_default/list.html did the trick.

I’m wondering if sending a PR to fix that will be my first contribution to the theme. Right now - 2:30 AM - I need to get some sleep because I have “kid duty” in about 4 hours.

Update: Because I can’t seem to leave well enough alone tonight, I did create the PR. :)