gridtypst

Typst: automatically adapt the column width with the grid function


I have three figures in 3:2 format, two of which are in landscape mode and one in portrait mode. I would like to arrange them on the same page, the two horizontal figures on the left, the vertical figure on the right. Here is what I obtained very simply using the grid function.

#set align(center + horizon)

#set page(
  width: 12.625in,
  height: 10.875in,
  margin: (x: 1in, y: 1in)
)

#grid(
  rows: (auto),
  columns: (auto, auto),
  gutter: 0.2in,

  grid(
    rows: (auto, auto),
    columns: auto,
    gutter: 0.2in,
  image("recth.jpg"),
  image("recth.jpg"),
  ),
  image("rectv.jpg"),
)

grid1

The result is not entirely satisfactory, as I would like the top and bottom edges of the figures to be aligned. I was able to do this by manually adjusting the relative width of the two columns in the grid function.

#grid(
  rows: (auto),
  columns: (1fr, 0.913fr),
  gutter: 0.2in,

  grid(
    rows: (auto, auto),
    columns: (auto),
    gutter: 0.2in,
  image("recth.jpg"),
  image("recth.jpg"),
  ),
  image("rectv.jpg"),
)

grid2

My question is: is there a way to achieve this result automatically (by having typst automatically find the suitable relative width)?

Thank you very much to the community for this wonderful project.

[EDIT]

Thank you for the answer! The first answer is exactly what I was look for. I have another question to slightly improve this answer. I tried to slightly modify your proposal, in order to allow the result to automatically take the maximum height of the page. The problem is that depending on the format of the page and the result, the images can be cut off on the left and right (hard to see in the image below, but the gray rectangles are not whole).


#set align(center + horizon)

#set page(
  width: 12.625in,
  height: 10.875in,
  margin: (x: 1in, y: 1in)
)

#pagebreak()

#layout(size => {
  let gh = size.height
  let image-grid(grid-height, gutter) = {
    let landscape-height = (grid-height - gutter) / 2
    grid(columns: 2, rows: grid-height, gutter: gutter)[
      #align(top, image("landscape.jpg", height: landscape-height))
      #align(bottom, image("landscape.jpg", height: landscape-height))
    ][
      #image("portrait.jpg", height: 100%)
    ]
  }

  image-grid(gh, 0.2in)
})

grid3

Is their a way to give the whole result the maximum height that preserves the integrity of the images?


Solution

  • You can make each portrait figure the same size, ensure they leave room for a gutter, then align them to the top and bottom of a grid cell.

    Putting this into typst, we get:

    #let image-grid(grid-height, gutter) = {
      let landscape-height = (grid-height - gutter) / 2
      grid(columns: 2, rows: grid-height, gutter: gutter)[
        #align(top, image("landscape.png", height: landscape-height))
        #align(bottom, image("landscape.png", height: landscape-height))
      ][
        #image("portrait.png", height: 100%)
      ]
    }
    
    #image-grid(3in, 0.1in)
    

    enter image description here