Creating a column-based layout

Changing the Page Layout in Quarto

blog
quarto
how-to

Do you want to place two figures side by side or write text in parallel in different columns? The post describes four methods to turn part of your blog post into a column-based layout.

Author

Peter Baumgartner

Published

May 7, 2023

Modified

May 7, 2023

From PxHere (CC0, Public Domain)

In my first two articles, I encountered the problem of changing the page layout several times: So I wanted – for instance – in my article How to delete Git branches two small screenshots to appear side by side.

Help page about article layout

When I looked at the Quarto help pages, I found a chapter about article layouts. But it treated the layout of pages in a more general way by answering the following questions:

  • How to use the whole main content region?

  • How can content overflow this standard content region?

  • How can one span the width of the entire page?

  • How can authors place content on the document margin?

I think that these questions address pretty special requirements. I just wanted a solution for content items side by side. This support page about the article layout was not helpful to me.

Using a table failed

My first approach was to use a table to position images side by side. I created a one-row / two-column table with the visual editor of RStudio and uploaded in each column a picture. But the screenshots didn’t appear. Whenever I rendered the page, Quarto told me, “404: Not Found”.

Two red error messages

Looking after rendering into the tab “Background Jobs” revealed these error messages

As I inspected the source code, I saw the reason: The long image URLs didn’t fit in the table column, and therefore forced line breaks that destroyed the URLs.

The source code shows that the URLs are wrapped in wrong places and therefore broken

Source code generated by RStudio after loading two images into a one-row / two-columns desing

Using pandoc extensions

After long research, I found three answers to my question via StackOverflow. They all used the fenced_divs extension of pandoc.

It is easier to explain the method after I have presented these three examples. I will use the same toy text sample for the following illustration.

Text in the left column:

I would like to have text here

Sentence becomes longer, it should automatically stay in their column

Text in the right column:

and here

More text

Example 1: Two columns separated by a small third column

---
title: "Two columns separated by a small third column"
format: html
engine: knitr
---

:::: {.columns}

::: {.column width="70%"}
I would like to have text here

Sentence becomes longer, it should automatically stay in their column
:::

::: {.column width="10%"}
<!-- empty column to create gap -->
:::

::: {.column width="20%"}
and here

More text
:::

::::

The example is — slightly redacted — taken from shafee via StackOverflow

Example 2: Two columns using the bootstrap CSS grid system

---
title: "Two columns using the bootstrap CSS grid system"
format: html
engine: knitr
---
  
  
::: {.grid}

::: {.g-col-6}

## First column 
I would like to have text here

Sentence becomes longer, it should automatically stay in their column
:::
  
::: {.g-col-6}

## Second column 

and here

More text

:::
  
:::

The example is — slightly redacted — taken from Julian via StackOverflow.

Example 3: Two columns with text center-aligned

---
title: "Two columns with text center-aligned"
format: html
engine: knitr
---
    



::: {.cell}
<style type="text/css">
.column {
text-align: center;
}
</style>
:::

:::: {.columns}

::: {.column width="50%"}

I would like to have text here

Sentence becomes longer, it should automatically stay in their column
:::

::: {.column width="50%"}

and here

More text
:::

::::

The example is — slightly redacted — taken again from shafee via StackOverflow.

Fenced divs in Pandoc: How do they work?

What is Pandoc?

Pandoc is an open-source universal document converter. Pandoc is licensed with the very permissive GNU1 General Public License (GPL). Currently, Pandoc supports the conversion of more than 60 formats. John MacFarlane, a philosophy professor at the University of Berkeley, is developing and maintaining Pandoc.

RStudio IDE ships with a pandoc binary. The path is stored in the RSTUDIO_PANDOC environment variable. You can get the path and the current pandoc version used by RStudio with rmarkdown::find_pandoc().

rmarkdown::find_pandoc()
$version
[1] '3.1.2'

$dir
[1] "/usr/local/bin"

To get the version number on your machine type in the terminal:

pandoc --version
(base) path@my_machine quarto-blog % pandoc --version
pandoc 3.1.2
Features: +server +lua
Scripting engine: Lua 5.4
User data directory: /Users/petzi/.pandoc
Copyright (C) 2006-2023 John MacFarlane. Web:  https://pandoc.org
This is free software; see the source for copying conditions. There is no
warranty, not even for merchantability or fitness for a particular purpose.
(base) path@my_machine quarto-blog % 

This result shows I have two different pandoc versions installed — a potential danger for a version conflict: One version installed RStudio, and the other I downloaded with the macOS package manager Homebrew.

Div Blocks in Pandoc

The pandoc div extension allows a special fenced syntax to generate HTML div-tags:

A div starts with a fence containing at least three consecutive colons plus some attributes. The attributes may optionally be followed by another string of consecutive colons. … [O]ne can use either attributes in curly braces or a single unbraced word, which will be treated as a class name. The Div ends with another line containing a string of at least three consecutive colons. The fenced Div should be separated by blank lines from preceding and following blocks. From Extension: fenced_divs

Two more remarks:

  1. If you are going to nest pandoc div directives, you must provide more colons for the outer divs than the inner divs.

  2. To prevent that Quarto uses the jupyter engine, you must provide engine: knitr in the YAML front matter.

A genuine Quarto solution

After I looked around at how to create a two-text column layout for a while, I found a simple Quarto answer. Hidden in the help page about figures, I found the remark:

You can treat any markdown content you want as a figure by enclosing it in Pandoc div block with an identifier prefaced with #fig-. See the first sentence under the header Figure Divs.

The first part of the sentence, “You can treat any markdown content you want as a figure…” could be reversed to the concept that a layout for figures works similarly to a design for text.

I came up with the following solution that I also published to answer the StackOverflow post.

Version 1 with equally wide columns


---
title: "Two columns layout Quarto with equally wide columns"
format: html
engine: knitr
---

::: {layout-ncol=2}


First column

Second column

I would like to have text here

and here

Sentence becomes longer, it should automatically stay in their column

More text

:::

The above solution uses the Quarto layout-ncol attribute. There is also a layout-nrowattribute. In both directives, you can specify the number of columns respectively rows.

Version 2 with different wide columns

---
title: "Two columns layout Quarto with different wide columns"
format: html
engine: knitr
---

::: {layout="[[10,5], [40,20], [26,13], [2,1]]"}


**First column**

**Second column**

I would like to have text here

and here

Sentence becomes longer, it should automatically stay in their column

More text

:::

The version 2 solution uses the general form of the layout attribute. It is followed by a 2-dimensional array where the first dimension defines rows and the second columns. Note that the used row / column numbers in the second version are arbitrary. They just provide the desired proportion of 2:1. The code translates to “create four rows, where the first column has always the double size of the second column.”

Some final remarks on both of the last examples:

  1. There needs to be an empty line between every paragraph (here sentence). This structure is necessary so Pandoc can see the break and addresses the next column.

  2. You need to use the engine: knitr command to prevent rendering with the jupyter engine.

Conclusion

There are many possibilities for a creative layout design in Quarto. This article shows the use of Pandocs div block directives with five different methods. These layout directives can be generalized from a two-column to a many column layout

  1. Several columns with varying percentages of widths.

  2. Several columns using the very flexible bootstrap CSS grid system.

  3. Several columns with formatted explicitly with a CSS style.

  4. Several columns with the same width using the Quarto layout-ncol or layout-nrow attribute.

  5. Several columns with different widths using the Quarto general layout attribute.

Back to top