.Render vs partial

A long time ago @Leo_Merkel ask me a question in private. I feel making my answer public would benefit a lot of users here who struggle when choosing between the two.

.Render vs partial

.Render is a method of the page object. Its greatest advantage is template lookup order. It will use Hugo’s template lookup order to define which template file to use. So if you have two different title.html template files, one for your entries of type post and one for your entries of type page each living in a directory named after those two types:

  • layouts/_default/title.html
  • layouts/post/title.html
  • layouts/page/title.html

Hugo would grab the type of the page .Render is used on and find the right file for you. And if the file does not exist, gracefully fallback to your default file.

.Render does not take any argument. The context passed to the template file is always the context of the page the method is used on.

partial on the other hand is a global function. It can be used anywhere. It takes two arguments, the file path and the context to be passed to the template file.
It does not have any template lookout logic. So back to our title.html example. You would have to place your two files in the layouts/partials directory

  • layouts/partials/post/title.html
  • layouts/partials/page/title.html

And you would have to grab the page type and use it to build the partial’s path yourself prior to passing it to the partial function and make sure the file exist or fall back to a default one. (Luckily there is templates.Exists now).

So which one to use?

Now by those two definitions, it appears both have their pros and cons, but the limited context passed to the template file by .Render will often be a problem for me. Unlike partial there is no way to conveniently complement or replace this default context.

For exemple, from within your partial you often need to know beyond the page context, like is this template file being used on a single page or a list page?

Let’s say you have a template file called article.html to display your title, featured image and text.
The only difference in the file is calling .Summary when in a list template vs .Content when in a single template. A simple ternary condition could do!

Using .Render though you would have no way to know if you’re supposed to call for .Summary or .Content , you’ve got nothing to test your condition on.
So in order to benefit form its amazing template lookup feature, you would have to create two quasi-identifcal html files, article_list.html and article_single.html (in each of your type directories) and replace the part dealing with .Summary or .Content .
This doesn’t seem much for many but it’s a no go for me. Having several identical template files and maintaining multiple files when changing the HTML of this section is a no go for me. (principles… :disappointed:).

For these reasons, on my website which matches this use case, I had to fall back to using partial . This way I’m able pass this information (list or single) to the context, and test my condition on it)

More

There is an ongoing issue to add the possibility to pass more to .Render than the page context: Make the argument to .Render (optionally) be a map with type and layout keys · Issue #8182 · gohugoio/hugo · GitHub

16 Likes