How to setup the interlinespacing parameters as function of x-height

I tried :

#let x-height = context{measure(box(inset: 0pt, outset: 0pt, text(top-edge: “bounds”, )))}.height

#set text(
top-edge: 2.8 * x-height * 0.72,
bottom-edge: 2.8 * x-height * 0.28,
)
#set par(leading: 2.8 * x-height * 0.28)

Obviously, I get
[typst] cannot multiply float with content

let x-height = any;

But I am not yet familiar enough with Typst to quickly understand how to cope with this issue.

Thanks a lot for your help

Welcome to the forum @Garulfo ,

This is a classic case of Why is the value I receive from context always content? .

Solution will require you to move the context expression outside of the x-height definition. Hint: turn it into a function and provide context to it.

// Requires `context`
#let x-height(body) = {
  {
    measure(
      box(
        inset: 0pt,
        outset: 0pt,
        text(top-edge: "bounds", body),
      ),
    )
  }.height
}

#let body = [= Test
  #lorem(20)]
#body

#context {
  let height = x-height(body)

  set text(
    top-edge: 2.8 * height * 0.72,
    bottom-edge: 2.8 * height * 0.28,
  )
  set par(leading: 2.8 * height * 0.28)

  body
}

If you could please edit your first code snippet and enclose it in back ticks ``` snippet ```, that would help us copy/paste/read your code more easily. Thanks.

I recommend this:

#show: rest => context {
  let x-height = measure({
    set text(bottom-edge: "baseline", top-edge: "x-height")
    [x]
  }).height
  let ex = x-height / 1em.to-absolute() * 1em

  set text(
    top-edge: 2.8 * ex * 0.72,
    bottom-edge: 2.8 * ex * 0.28,
  )
  set par(leading: 2.8 * ex * 0.28)

  rest
}


#lorem(10)

Explanation:

  1. The x-height will depend on the font, so it’s context-sensitive. Therefore, we have to put everything that depends on x-height in a context {…}.

    To simplify later writing, I use a show: rest => … rule to transform the whole document afterwards.

  2. let x-height = measure(…).height is your original idea. I use "x-height" instead of "bounds" for the top-edge parameter, because it is the metric defined by the font designer, and does not depend on the specific character.

  3. x-height is an absolute length (in points), and let ex = x-height / 1em.to-absolute() * 1em will make it to relative to the font size. Doing so will make your leading settings look better for headings, where have larger font size.

    For Libertinus Serif, ex is about 0.43em.

Besides, you can go to ```ex``` as a unit · Issue #2405 · typst/typst · GitHub and click :+1: to express the wish for this to be natively supported by typst.