How to make a table formatting condition for just one table?

I have a table where I would like the header row to be bold, so before the table I have included the following command.

#show table.cell.where(y: 0): strong

However, later in my document I would not like this to be the case.

How can I either remove that show rule for later tables, or set it so the scope of the rule is just for a given table?

I have tried a few possibilities involving a subsequent show command, but nothing has worked:

#show table.cell.where(y: 0): ??? // forget about the earlier rule please...

(Note: in the documentation, they seem to have header rows where each item is individually put in bold like so: table.header([], [*Area*], [*Parameters*]), but to me this seems like too brittle a solution, with excessive typing in the case of tables with many columns.)

I think for now you only have 1 option: use an additional scope:

#{
  show table.cell.where(y: 0): strong
  table(table.header[header], [cell], [cell])
}
#table(table.header[header], [cell], [cell])

image

The second option isn’t implemented yet: Resetting `show` and `set` to its default / Revoke rules · Issue #420 · typst/typst · GitHub.

There is another workaround (that has its advantages) that uses a user-defined function as a wrapper for the table.header:

#let table-header(..headers) = {
  table.header(..headers.pos().map(strong))
}

Related issue: Show-set rules don't seem to work for `table.cell` · Issue #4159 · typst/typst · GitHub .

Related issue: Unable to style `table.header` and `table.footer` · Issue #3640 · typst/typst · GitHub.

1 Like

Thanks! I ended up simulating this effect as my table was contained in a #box element, so I have

#box(width: 80%)[
#show table.cell.where(y: 0): strong
#table(columns: (1fr, 1fr, 1fr, 1fr, 1fr, 1fr),
...
)]

But I’m guessing #{ gives a way to introduce scope if there is not something like a #box?

I’ll accept the solution above, but is there also a guide somewhere to the concept of scope of show rules?

Of note, that proposal is related to the opposite situation: when you have a global show rule but you want to disable it for a specific scope. You’d have something like (note: hypothetical syntax)

// NOTE: Hypothetical syntax, this doesn't exist
#let my-rule = show table: strong

// NOTE: Hypothetical syntax, this doesn't exist
#apply my-rule

#table[This is strong]

#[
  // NOTE: Hypothetical syntax, this doesn't exist
  #revoke my-rule  // disable rule temporarily
  #table[This is not strong]
]

#table[This is strong again]

because, currently, the only way to do that is to turn that setup inside out: scope half of the document with the show rule in it, then have something outside the scope, then scope again, which is cumbersome.

Here, using scopes is the intended way to temporarily apply the show rule:

#table[A regular table]

#{
  show table: strong
  table[Only this is strong.]
}

#table[But this is not!]

That issue is unrelated and specifically about #show table.cell: set table.cell(...), which doesn’t work because table cell properties are applied before show/set rules are checked (they currently are only checked when the cells are laid out).

Perhaps you meant to link to this one instead, since OP may have intended to write something like #show table.header: strong, which indeed currently doesn’t work:

2 Likes

There is more information here: Styling – Typst Documentation

1 Like

I think it is the exact same meaning, so I think we are all on the same page. If you revoke the rule in the root scope, it will indeed remove it for later tables.

Yeah, but I think I saw an issue specifically showing the #show table.cell.where(y: 0): strong example. Or maybe it was just from Table guide – Typst Documentation.

1 Like

Yes, what I mean is that this isn’t the purpose of the feature. What they want is to apply a show rule only for a single table. What revoke is for is to have a show rule which applies to all tables, except for a specific one. Right now, doing that is very cumbersome.

1 Like

Something I would quite like, and possibly can be done within Typst, is something like in HTML how you could have different classes and then have CSS rules which match the different cases.

So in CSS, you could have something like

table { /* formatting rules here for how you want tables to appear */ }
table.unusual_situation { /* formatting rules here for your unusual situation table */ }

Obviously this doesn’t match the show syntax of Typst, but this is the way that CSS would solve the problem.

If I’m understanding correctly, this is possible in Typst. This will set one default style of table which can be overridden at any time for one specific table.

#set table(gutter: 3em, columns: 2)

= Table 1
#table([a], [b], [c], [d])
= Table 2
#table(gutter: 0em, [a], [b], [c], [d])
Rendered

image

Or this which results in the same output as above but allows saving and reusing several styles of table.

#let table_wide = table.with(gutter: 3em, columns: 2)
#let table_narrow = table.with(gutter: 1em, columns: 2)

= Table 1
#table_wide([a], [b], [c], [d])
= Table 2
#table_narrow(gutter: 0em, [a], [b], [c], [d])
1 Like

I think this would be the initial/primary use case, but in reality you can use it however you want as long as this makes sense (or just works). You can have a single delimiter in a document, after which the rule is revoked. You can also revoke and apply the same rule multiple times. The possibilities are endless*!

* — maybe

In addition to what is possible today, when we get custom types, I think you would be able to create a custom table-wrapper type and then apply rules to it, but this is probably too soon to think of.

I expanded my post to include a workaround, shown here. It has its own pros and cons.