How to add padding between table cells under a rowspan cell?

I’m trying to produce publication-quality tables looking like this:

So far I was able to merge some cells and fiddle with conditional rule widths, to some extent, but when I set a non-zero stroke at the bottom of my merged cells (under “Bar” and “Baz”) I can’t find a way to leave some empty padding to visually separate the merged cells. Any pointers would be helpful, thanks.

Could you provide a working example please?

Here it is:

#let tabledata = (
	([123], [234], [345], [456], [567], [678]),
	([123], [234], [345], [456], [567], [678]),
	([123], [234], [345], [456], [567], [678]),
	([123], [234], [345], [456], [567], [678]),
)

#let framing(stroke) = (x, y) => {
	(
		left: 0pt,
		right: 0pt,
		top: {
			if y in (0, 2, -1) { stroke }
			else if (y == 1) { stroke * 0 }
			else { stroke * 0.5 }
		},
		bottom: stroke,
	)
}

#align(center)[
	#table(
		columns: 6,
		stroke: framing(1pt),
		[Foo],
		table.cell(colspan: 2, stroke: (bottom: red + 1pt))[Bar],
		table.cell(colspan: 2, stroke: (bottom: blue + 1pt))[Baz],
		[Qux],
		..tabledata.flatten()
	)
]

This yields:

I’m looking for a way to introduce a small gap between the red and blue lines.

1 Like

You can use a column-gutter to introduce the small gap between the lines below “Bar” and “Baz”. For the regular lines you would then have to use table.hline which ignores the gutter. This does not feel like a particularly elegant solution but it works for your specific use case. If you want to make the stroke of the horizontal lines adjustable, just turn table-lines into a function.

#let tabledata = (
	([123], [234], [345], [456], [567], [678]),
	([123], [234], [345], [456], [567], [678]),
	([123], [234], [345], [456], [567], [678]),
	([123], [234], [345], [456], [567], [678]),
)

#let table-lines = (
  table.hline(y: 0),
  table.hline(y: 2),
  ..range(1, tabledata.len()).map(i => table.hline(y: 2 + i, stroke: 0.5pt)),
  table.hline(y: 2 + tabledata.len()),
)

#let framing(stroke) = (x, y) => (
  bottom: if (y == 0) { stroke }
)

#align(center)[
  #table(
    columns: 6,
    column-gutter: 0.5em,
    stroke: framing(0.5pt),
    table.header(
      table.cell(rowspan: 2, [Foo]),
      table.cell(colspan: 2, [Bar]),
      table.cell(colspan: 2, [Foo]),
      table.cell(rowspan: 2, [Qux]),
      [abc], [xyz], [abc], [xyz]
    ),
    ..tabledata.flatten(),
    ..table-lines
  )
]
1 Like

Oh wow, I would have not found that by myself! Thanks.

Hey @Mathieu, welcome to the forum! I’ve changed your question post’s title to better fit our guidelines: How to post in the Questions category

For future posts, make sure your title is a question you’d ask to a friend about Typst. :wink: