Is there any difference between `set align(center)` and `align(center, …)`?

Is there any difference between set align(center) and align(center, …)?

#[
  #set align(center)
  …
]
// vs
#align(center)[…]

I know that the former changes the default alignment, while the latter calls the align function.
But I also notice that many align parameters use the outer alignment by default. For instance, table.align:

…If set to auto, the outer alignment is used.
Default: auto

So will there be any visible difference?

My attempt

I failed to construct any counter example.

Full code
#let example = [
  #lorem(15)

  - a
  - #context align.alignment

  #align[
    - a
    - #context align.alignment
  ]
  #align(start)[
    - a
    - #context align.alignment
  ]

  #table(
    columns: (2em,) * 2,
    align: horizon,
    [A], [B \ C],
  )

  #colbreak(weak: true)
]

#set page(width: 50em, height: auto, margin: 2em, columns: 3)
#set raw(lang: "typc")

#[
  = Default
  #example
]
#[
  = `set align(center)`
  #set align(center)
  #example
]
#[
  = `align(center, …)`
  #align(center, example)
]

I also asked typst/typst | DeepWiki and found the following rust implementations.
It looks like the align function does nothing but set align(…)?

const ALIGN_RULE: ShowFn<AlignElem> =
    |elem, _, styles| Ok(elem.body.clone().aligned(elem.alignment.get(styles)));

impl Content {
    /// Set alignments for this content.
    pub fn aligned(self, align: Alignment) -> Self {
        self.styled(AlignElem::set_alignment(align))
    }
}
Links to details

Additional notes

Our original question was set align(center) vs. show: align.with(center).
I changed it to the current version to avoid being disturbed by show rule priority.

typst/crates/typst-library/src/layout/align.rs at bcc71ddb9b5146b97cb3078ecdb5406f31781ea2 · typst/typst · GitHub actually has many alignments. Not sure where, but I’m pretty sure the constructor adds block wrapper unlike the set rule. But that’s probably about it. The alignment inheritance should work the same with both approaches.

1 Like

Thanks, but the set rule somehow also creates a new block…

a#set align(center);b c
// vs
a#align(center)[b c]
// vs
a#show: align.with(center);b c

Code
#set page(width: 24em, height: auto, margin: 2em)
#set raw(lang: "typc")

#[
  = Default
  a#set enum(indent: 2em);b c
]
#[
  = `set align(center)`
  a#set align(center);b c
]
#[
  = `align(center, …)`
  a#align(center)[b c]
]
#[
  = `show: align.with(center)`
  a#show: align.with(center);b c
]
#let f(x) = { set align(end); x }
// vs
#let f = align.with(end)

+ a
+ b
#f[+ c]
+ d

Full code
#set page(width: 24em, height: auto, margin: 2em)
#set raw(lang: "typc")

#[
  = Default
  #let f(body) = body

  + a
  + b
  #f[+ c]
  + d
]
#[
  = `set align(center)`
  #let f(body) = {
    set align(center)
    body
  }

  + a
  + b
  #f[+ c]
  + d
]
#[
  = `align(center, …)`
  #let f = align.with(center)

  + a
  + b
  #f[+ c]
  + d
]

There is no block wrapper added in either case but in both cases grouping of inline-level elements is interrupted.

Both variants are intended to be equivalent and unless you are manually parsing the content or something like that, there shouldn’t be any difference.

2 Likes

So a parbreak is inserted or something?

Essentially, yes. It’s the other way around though: Parbreaks also interrupt grouping of inline-level elements.

1 Like