17.2 Rendering Content: .Content and .Summary
Right, let’s talk about getting your words onto the page. You’ve got your content files written in beautiful, pristine Markdown. Hugo has dutifully parsed them. Now what? You need to actually render that content. This is where .Content and .Summary come in, and while they seem simple on the surface, they’re the very heart of your site’s engine. I’ve seen more than a few people trip over the nuances here, so pay attention.
The Workhorse: .Content
Think of .Content as the main event. When you call .Content on a page object within a template, Hugo says, “Alright, you asked for it,” and serves up the entire rendered content of that page. It’s not the raw Markdown; it’s the final HTML, after all your shortcodes have been processed and your Markdown has been transformed. This is what you’ll slap into your single.html template to show the full blog post or product description.
Here’s the typical, no-frills usage:
<article class="prose prose-lg">
{{ .Content }}
</article>
Dead simple, right? But here’s the first “gotcha” everyone encounters: Hugo, in its infinite wisdom, has already wrapped your content in a <p> tag if it’s a paragraph, or the appropriate HTML element. This means if you write a Markdown file that’s just Hello, world!, calling .Content gives you <p>Hello, world!</p>. This is mostly fine until you try to do something clever like wrap it in another element and your HTML structure gets weird. The solution is to understand that .Content is a pre-rendered HTML block, not a string you can easily manipulate with Go template functions. You work around it, not with it.
The Art of the Tease: .Summary
Now, .Summary is a different beast entirely. Its job is to give you a preview, a snippet to use on listing pages without giving away the whole farm. By default, Hugo calculates the summary as the first 70 words of your content, *but only up to the first occurrence of the `
` summary divider*.
This is the most important thing to remember: <!--more--> trumps everything. If you put <!--more--> in your content, .Summary is everything before it. If you don’t, it’s the first 70 words. Always.
---
title: "My Deep Thoughts on Sandwiches"
---
This is the intro, which is deeply compelling. I talk about the history of bread and the societal implications of condiment choices. This will be in the summary.
<!--more-->
This is the part where I get into the really weird, specific details about the precise mustard-to-meat ratio. This will NOT be in the summary, reserved for the single page view.
In your list.html or homepage.html template:
<div class="post-preview">
<h3>{{ .Title }}</h3>
<p>{{ .Summary }}</p>
<a href="{{ .Permalink }}">Read more...</a>
</div>
Common Pitfalls and How to Avoid Them
The
.SummaryHTML Tag Soup: Here’s the real kicker. The content before the<!--more-->divider is also rendered to HTML. So if you have an image, a shortcode, or a complex HTML table right at the beginning, that all gets dumped into.Summary. This can seriously mess up your layout on a listing page if your CSS isn’t built to handle random full-width images sitting in your preview card. The best practice? Keep your intro text clean. Use the summary divider before you get into the heavy, layout-breaking stuff.The “Read More…” Link Dilemma: Notice in the code above I used a simple
<a>tag. You might be tempted to get fancy and only show the “Read more…” link if the summary exists or if the content is truncated. You can do this, but it’s a bit clunky:<p>{{ .Summary }}</p> {{ if .Truncated }} <a href="{{ .Permalink }}">Read more...</a> {{ end }}The
.Truncatedvariable returnstrueif the summary is not the full content (i.e., either because of the<!--more-->divider or the 70-word limit was hit). It’s useful, but honestly, most people just include the link all the time. It’s simpler and never broken for me.You Want a Custom Summary: Sometimes, 70 words (or the text before
<!--more-->) isn’t what you want for a preview. You might want to use a field from the front matter, likedescription. That’s perfectly valid!.Summaryis automatic; front matter is manual. You have to choose the right tool for the job. For a curated, marketing-style blurb, use{{ .Params.description }}. For an automated, content-driven excerpt, use{{ .Summary }}. Don’t confuse the two.
In the end, .Content is your faithful, straightforward workhorse. .Summary is its slightly neurotic, rules-driven cousin. Use the <!--more--> divider religiously to keep it in line, and your listing pages will thank you for it. Now let’s move on to making that content look good.