How to typeset tables with rows of equal but minimal width?

How do I typeset a table with rows of equal but not greedy width?

My current approach is

    #table(
      columns: (1fr, 1fr, 1fr),
      align: center,
      [], [$K_Y$], [$E_(Y, i)$],
      [$C_(Y, i, 1)$], [$-1$], [$-1$],
      [$C_(Y, i, 2)$], [$0$], [$-2$],
    )

This does guarantee that each column has the same width, but this results in the table being too wide.

1 Like

Would something like this not do what you want?

    #table(
      columns: (60pt, 60pt, 60pt),
      align: center,
      [], [$K_Y$], [$E_(Y, i)$],
      [$C_(Y, i, 1)$], [$-1$], [$-1$],
      [$C_(Y, i, 2)$], [$0$], [$-2$],
    )

[/quote]

1 Like

Idk if there’s an easy automated way of doing this but you can write @Mark_Hilton 's answer more compactly like this:

#table(
  columns: (40pt,)*3,
  align: center,
  [], $K_Y$, $E_(Y, i)$,
  $C_(Y, i, 1)$, $-1$, $-1$,
  $C_(Y, i, 2)$, $0$, $-2$,
)
2 Likes

I want it to be automatic.

1 Like

That is definitely beyond my pay grade! :smiley:

Mark

Best way would probably be to measure the width of each cell and find the maximum:

#let equal-width-table(columns: 1, ..args) = context {
  let cells = args.pos()
  let max-width = 0pt
  for cell in cells {
    let c = if cell.func() == table.cell and "colspan" in cell.fields() {
      cell.colspan
    } else {
      1
    }
    let t = table(columns: c, ..args.named(), cell)
    let w = measure(t).width
    max-width = calc.max(max-width, w)
  }
  table(
    columns: (max-width,) * columns,
    ..args
  )
}

The measuring is slightly hacky because simply measuing the cell’s body discards the table inset and I wanted to ensure that cells with colspan >= 2 also worked. If you don’t need to worry about the latter it can be simplified to

#let equal-width-table(columns: 1, ..args) = context {
  let cells = args.pos()
  let max-width = calc.max(
    ..args.pos().map(it => measure(it).width)
  )
  if "inset" in args.named() {
    max-width += args.named().inset * 2
  }
  else {
    // default inset is 5pt on both sides
    max-width += 10pt
  }
  table(
    columns: (max-width,) * columns,
    ..args
  )
}

You can call the function like you would call std.table, with the exception that columns should be of type int

3 Likes