How to indent every paragraph, excluding headings?

I’m trying to indent every paragraph, but the par function includes text inside headings.

Using par(first-line-indent: ) and par(hanging-line-indent: ) yields strange results. For example, the first line after a table or a grid is never indented.

Looking through the forum to make sure this question hasn’t been asked, I found that typst’s paragraph handling seems to be very inconsistent. Will I regret using it if I care a lot about things like paragraph styling?

This doesn’t answer your question of will you regret using the native styling, but if you want “fully” indented paragraphs see if something like this works for you:

#show par: it => [
  #set align(right)
  #let indent-amt = 1em
  #block(width: 100% - indent-amt)[
    #set align(left)
    #it
  ]
]

Some styling rules might not work as they did before because you are now inside a block instead of a par, but it does e.g. indent after tables

This also affects text inside tables and grids, making them look like this

image

There is extensive discussion about this particular request here: Behavior of first line indentation in paragraphs seems limiting · Issue #311 · typst/typst · GitHub

Note that indenting only consecutive paragraphs - the default style - is a common style in multiple parts of the world. However, Typst doesn’t currently natively offer the alternative style of indenting all paragraphs, which is also often used, precisely due to the problem you’re describing: text inside headings is also inside a paragraph.

A fix for this is coming soon, in a future update. In the meanwhile, the issue I linked has some suggested workarounds.

Here’s how you could apply the workaround suggested at Behavior of first line indentation in paragraphs seems limiting · Issue #311 · typst/typst · GitHub :

#set par(first-line-indent: 1.5em)

#show heading: it => {
    it
    ""
    context v(-par.spacing - measure("").height)
}

= Hello world

#lorem(20)

#lorem(20)

To also apply this workaround to grids, tables, figures, and whichever other elements you need, you can simply replace #show heading with #show selector.or(heading, table, /* and more */):

#set par(first-line-indent: 1.5em)
#show selector.or(heading, table, grid, figure): it => {
    it
    ""
    context v(-par.spacing - measure("").height)
}

#table(columns: 2, [a], [b], [c], [d])

#lorem(10)

#figure(table(columns: 2, [a], [b], [c], [d]), caption: [A table])

#lorem(10)

We hope this won’t be necessary anymore in a future update. :slight_smile:

3 Likes