Over the last few weeks, we have been building a web application in one of our clients and ended up duplicating some template code. These new pages had something in common between them, but not with the rest of the application. We needed an inner layout to reuse the template code between these pages, however, Phoenix doesn’t come with this feature. In this post, you’ll learn how you can build nested layouts in Phoenix and when you should use them.

Why are they useful?

Inner (or nested) layouts are useful to reuse template code when you have subsections on your website. Usually, in Phoenix applications, we have /templates/layout/app.html.eex that shares template code between all pages. For example:

In the example above, we want to reuse the application logo, title, and navigation menu across all pages. We can solve that by using the Phoenix default layout and it works great. However, sometimes you need to create a new website section inside the parent layout. For example, imagine we want to add a help section to our Phoenix website. Look at the image below:

We still want to reuse the layout header across all pages, but we also want to reuse the left navigation and main content layout in all pages inside the help section. Let’s see how we can do that using Phoenix.

The Inner Layout Solution

I tried some solutions by looking at some examples online. After discussing with the Plataformatec team, we came up with an approach that’s very simple and extensible, thanks to Phoenix explicit layout rendering. The solution works like this:

You create the nested layout template.

In the nested layout, you set the parent template by calling a function.

The parent layout is aware that is possible to have an inner layout and will render it.

You can invoke your nested layout by using the Phoenix `put_layout/2` function.

The main goal here is to make the nested layout work like any Phoenix layout. This will make it familiar to any Phoenix developer.

Preparing The Parent Template

First, let’s add a function that allows a template to render the parent layout:

The render_layout/3 will render the given layout by assigning the contents of the inner layout given in the do argument. Now, in the parent layout, we need to render the inner layout contents or the controller view contents. Look at how you can do it:

We render the parent and put the inner content in the do/end blocks in our nested layout template. Any content outside of the do/end blocks will not be rendered. Don’t forget to call render @view_module, @view_template, assigns, or the contents of your controller’s action template will not be rendered.

Now you can use our nested layout by invoking the plug put_layout/2 in your controller or router. For example:

You can organize your nested layout files in a different way. For example, imagine you have a help section in your website and you want to keep the nested layout file in the help folder. In your HelpView you’ll need to import the render_layout/3 function, like this:

Wrapping Up

Inner layouts come in handy to reuse template code of subsections of your web application. You learned how simple it is to build that in Phoenix. Just be aware of not creating inner layouts of inner layouts. If you do that, your codebase will start to be very hard to maintain. You can see and try by yourself a sample Phoenix app running the inner layout example.

Have you implemented inner layout in a different way? Do you have any feature that you would like to see how we can build it in Phoenix? Let us know in your comments.