How to continue balanced column layout on the last page?

I want to fill two columns with blocks (in my case tables with a heading) but I want them to use two columns also on the last page. Here’s an example:

#set page("a4")
#columns(2)[
  #for b in range(17) [
    #block(breakable: false)[
      #grid(columns: (1fr, 5em), row-gutter: 0.6em,
        grid.cell(colspan: 2, [#text(fill: rgb("#666"), ligatures: false, tracking: .12em, "Header")]),
        ..for _ in range(5 + calc.rem(b,3)) {
          ([Foo],[sdfsdf])
        }
      )
    ]
  ]
]

image

As you can see the columns are built from contents like this:


But I would rather have them built like this:

Hello @AndreKR! Since this is the Questions category, it’s best if your topic title is a question. I can suggest “How do I balance content in columns?”

Your issue here is that the column on the last page is not fully completed, hence your content is not split into two columns.

Searching for relevant topics, you can read the solution at https://forum.typst.app/t/is-there-a-way-to-automatically-determine-the-page-height-for-balanced-two-column-page/3195, which suggests to use eqcolumns.

It’s not working out of the box, but you can simply change the height of the box to compensate for errors, more or less 10%.

#set page("a4")
#let eqcolumns(n, gutter: 4%, content) = {
  layout(size => [
    #let (height,) = measure(
      block(
        width: (1/n) * size.width * (1 - float(gutter)*n), 
        content
      )
    )
    #block(
      height: height / n + 10%,
      columns(n, gutter: gutter, content)
    )
  ])
}
#eqcolumns(2)[
  #for b in range(17) [
    #block(breakable: false)[
      #grid(columns: (1fr, 5em), row-gutter: 0.6em,
        grid.cell(colspan: 2, [#text(fill: rgb("#666"), ligatures: false, tracking: .12em, "Header")]),
        ..for _ in range(5 + calc.rem(b,3)) {
          ([Foo],[sdfsdf])
        }
      )
    ]
  ]
]

image

3 Likes

Thanks for the solution.

I didn’t know that this is called “balancing columns”, if I had known that, I probably would have found the existing discussions. That’s why I also avoided the term when changing the title, I wanted to make this more discoverable for people who don’t know the term either.

1 Like