When using auto-sizing in grid, can i have finer control over the height of cells? So that the height of specific cells is used?

Hi,

I’m trying to create a grid where i want to use rows:(auto,auto,1fr), to determine the height of the top 2 rows.

More specificly i want the left column to determine the height.
In the right column i want an image to cover the entire rowspanned cells, similar to the fit parameter on image..

I made an example below:

#let imagecontents = "<svg class=\"svg-icon\" style=\"width: 1.01171875em; height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;\" viewBox=\"0 0 1036 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">
<rect width=\"100%\" height=\"100%\" fill=\"gray\" />
<path d=\"M231.633593 295.165243c0-153.595317 124.940454-278.535771 278.537807-278.535771 153.595317 0 278.535771 124.940454 278.535771 278.535771 0 153.60448-124.940454 278.53068-278.535771 278.53068C356.574047 573.695923 231.633593 448.769723 231.633593 295.165243L231.633593 295.165243zM0 1014.090329c5.996914-67.351756 38.330358-306.001432 286.846943-433.813074 61.63687 48.382571 139.069346 77.514946 223.325474 77.514946 84.715315 0 162.56727-29.428658 224.36908-78.30605 249.591753 127.274058 279.721917 364.250911 285.801301 434.597051C1018.86037 1015.51676 1.473266 1014.201308 0 1014.090329L0 1014.090329zM0 1014.090329\"  /></svg>"

#grid(
    columns:( 3fr, 1.5fr),
	rows:(auto,auto,1fr),
    stroke:red,
    [
      #set text(size:3em)
      = big title],
    grid.cell(inset:0pt,
      
			fill:aqua,
			stroke:none,
			rowspan:2,
			align:right,image.decode(imagecontents)),
   grid.cell(inset:(top:2em))[
     = subtitle
    #lorem(60)
    #lorem(20)
    ],
   [more content here],
   [sidebar that should be aligned with the image]
  )

This results in the following:
gridquestion

At the moment you can still see the background of the topright cell, and i want the image to cover the entire cell, so that you no longer see the aqua-blue in the example.

Setting a height on the image of 100% or 1fr, results in the image determining the height of the 2 top rows. I want the left cells to determine the height of the top rows and the right to just adjust to the height of the left cells.

(How) can i do this in typst?

PS. Im looking for a solution in Typst not SVG because i want to use bitmap images. The svg is just an example.

I managed to find a solution by measuring/calculating the height of the left column and then setting the height of the image in the right column explicitly.

The code containing the solution:

#let imagecontents = "<svg class=\"svg-icon\" style=\"width: 1.01171875em; height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;\" viewBox=\"0 0 1036 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">
<rect width=\"100%\" height=\"100%\" fill=\"gray\" />
<path d=\"M231.633593 295.165243c0-153.595317 124.940454-278.535771 278.537807-278.535771 153.595317 0 278.535771 124.940454 278.535771 278.535771 0 153.60448-124.940454 278.53068-278.535771 278.53068C356.574047 573.695923 231.633593 448.769723 231.633593 295.165243L231.633593 295.165243zM0 1014.090329c5.996914-67.351756 38.330358-306.001432 286.846943-433.813074 61.63687 48.382571 139.069346 77.514946 223.325474 77.514946 84.715315 0 162.56727-29.428658 224.36908-78.30605 249.591753 127.274058 279.721917 364.250911 285.801301 434.597051C1018.86037 1015.51676 1.473266 1014.201308 0 1014.090329L0 1014.090329zM0 1014.090329\"  /></svg>"

// define the content here so it's easy to measure later on
#let title = [
      #set text(size:3em)
      #box()[= big title]]
      
#let subblock = [
     #box(inset:(top:2em),[= subtitle
    #lorem(60)
    #lorem(20)
    #lorem(10)])]



#grid(
    columns:( 3fr, 1.5fr),
	rows:(auto,auto,1fr),
    stroke:red,
    title ,
      
    grid.cell(inset:0pt,
       align: center+horizon,
			 fill:aqua,
			stroke:none,
			rowspan:2,
      {
      layout(size => {
        // we know the left column is twice as big as the right column
        let curwidth-leftcolumn = size.width*2
        // we know the content of the left column, so we can measure it's height
        let title-height = measure(width:curwidth-leftcolumn,title).height
        let subblock-height = measure(width:curwidth-leftcolumn,subblock).height
        let heightofleft = title-height+subblock-height
        // knowing the height we can create an image of the specific height and 100% width with the default fit of cover
        image.decode(width:100%,height:heightofleft,imagecontents) 
      })
   }),
   grid.cell(subblock),
   [more content here],
   [sidebar that should be aligned with the image]
  )

results in:

1 Like

You’re looking for this feature: Add `table.cell(fit: Axes<bool>)` parameter · Issue #4000 · typst/typst · GitHub

For the moment, this is only present in tablex package (which inspired Typst 0.11’s new table API) through the fit-spans: (y: true) setting. It is, however, generally discouraged to use tablex as most of its features have been ported to built-in tables and grids (but specifically not this feature at the moment), and tablex compiles much slower than those. Still, here’s how it would look like:

#import "@preview/tablex:0.0.9": gridx, cellx

#let imagecontents = "<svg class=\"svg-icon\" style=\"width: 1.01171875em; height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;\" viewBox=\"0 0 1036 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">
<rect width=\"100%\" height=\"100%\" fill=\"gray\" />
<path d=\"M231.633593 295.165243c0-153.595317 124.940454-278.535771 278.537807-278.535771 153.595317 0 278.535771 124.940454 278.535771 278.535771 0 153.60448-124.940454 278.53068-278.535771 278.53068C356.574047 573.695923 231.633593 448.769723 231.633593 295.165243L231.633593 295.165243zM0 1014.090329c5.996914-67.351756 38.330358-306.001432 286.846943-433.813074 61.63687 48.382571 139.069346 77.514946 223.325474 77.514946 84.715315 0 162.56727-29.428658 224.36908-78.30605 249.591753 127.274058 279.721917 364.250911 285.801301 434.597051C1018.86037 1015.51676 1.473266 1014.201308 0 1014.090329L0 1014.090329zM0 1014.090329\"  /></svg>"

#gridx(
    columns:( 3fr, 1.5fr),
	rows:(auto,auto,auto),
    stroke: red,
    [
      #set text(size:3em)
      = big title],
    cellx(inset:0pt,
     fit-spans: (y: true),
			fill:aqua,
			rowspan:2,
			align:right,image.decode(imagecontents, height: 100%)),
   cellx(inset:(top:2em))[
     = subtitle
    #lorem(60)
    #lorem(20) ddd dd d d d dd dddddddddddddd ddddddddddd ddddd dddddddddddddddd
    ],
   [more content here],
   [sidebar that should be aligned with the image]
  )

output: image adjusts to height

Note that tablex internally uses measure for this, so your approach is generally correct (albeit a bit manual).

1 Like

Hi @PgBiel,

tablex looks interesting. I’ll look into it. :typstguy_peeking: