Skip to content

Disable ligatures when tracking is non-zero#8443

Open
lasernoises wants to merge 1 commit into
typst:mainfrom
lasernoises:tracking-ligatures
Open

Disable ligatures when tracking is non-zero#8443
lasernoises wants to merge 1 commit into
typst:mainfrom
lasernoises:tracking-ligatures

Conversation

@lasernoises

Copy link
Copy Markdown

I noticed that when tracking is non-zero, ligatures are still enabled. This leads to the letters involved looking too close together:

2026-06-05_18:05:05

It seems that both LaTeX and browsers handle this by just disabling ligatures when tracking is non-zero. For example here is the relevant part of the CSS spec: https://drafts.csswg.org/css-text/#example-d2a0b994.

I didn't find any issues talking about this and it seemed quite easy to implement, so I'm making a PR directly instead of creating an issue first.

@Enivex

Enivex commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

In my opinion this should be user choice. Ligatures can look fine with minor tracking adjustments.

@cady-b

cady-b commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Edit: whoops, this is not a response to Enivex but my own thoughts on the PR


Not a big fan of this overwriting a non-auto value, but generally this seems like sensible behavior to me.

I believe from a user-perspective it would be much less surprising to convert ligatures to be auto by default and not overwrite boolean settings of the value to get the best of both worlds, but with dlig and hlig as well that could get messy. Not sure if it'd actually result in an interface that's easier to use :(

As of right now with this PR, I believe people that still want ligatures could manually set the relevant text.features, which is fair I guess. I do like that with tracking ligatures are off by default anyway (though maybe we should check >0 instead of !=0, or even some larger threshold? At least the current rationale only really makes sense with increased tracking; though if both CSS and LaTeX have this convention then I guess it's fine too).


Edit: I can't confirm what the actual behavior in LaTeX is though; there seem to be varying solutions for this. The microtype package seems to have a dedicated option and explains in its user manual:

In the absence of this option, ligatures in letterspaced fonts would be constructed as usual, which may be advisable when changing the tracking by only a small amount. For larger letterspacing amounts, on the other hand, the normal letter space within ligatures would have displeasing e ff e c t s.
[...]
The default settings (in microtype.cfg) disable ligatures for the character ‘f’ only, i.e., ‘ff’, ‘fi’, ffi’, etc.

@lasernoises

lasernoises commented Jun 5, 2026

Copy link
Copy Markdown
Author

I believe from a user-perspective it would be much less surprising to convert ligatures to be auto by default and not overwrite boolean settings of the value to get the best of both worlds, but with dlig and hlig as well that could get messy. Not sure if it'd actually result in an interface that's easier to use :(

I guess by auto you mean changing ligatures to a Smart<bool> [here](https://github.com/typst/typst/blob/main/crates/typst-library/src/text/mod.rs#L680) and then only doing this behavior if it's Auto?

If you have a whole bunch of text and want to enable ligatures for all of it and then only a bit of it has tracking that might be a bit unexpected. But I'm not sure in what case you would explicitly set ligatures to true.

With dlig and hlig I wonder whether it should also check the tracking. Because that could also be enabled for a whole document for example and if only some of it has tracking it might be unexpected as well.

I wondered about setting a threshold for not doing the whole behavior if tracking is small enough. But that would also have to be a configurable setting probably.

Edit: I can't confirm weather LaTeX does this automatically though. The microtype package seems to have a dedicated option for this and explains in its user manual:

In the absence of this option, ligatures in letterspaced fonts would
be constructed as usual, which may be advisable when changing the tracking
by only a small amount. For larger letterspacing amounts, on the other hand,
the normal letter space within ligatures would have displeasing e ff e c t s.
[...]
The default settings (in microtype.cfg) disable ligatures for the character ‘f’ only, i.e., ‘ff’, ‘fi’, ffi’, etc.

Oh, I guess you're right. I tested it, but I must have compared it to text outside of \textls. And now I can see that in my example it doesn't seem to do ligatures in \textls at all. I guess I was confused because I don't understand how LaTeX works.


Edit: Didn't fully read this part:

As of right now with this PR, I believe people that still want ligatures could manually set the relevant text.features, which is fair I guess. I do like that with tracking ligatures are off by default anyway (though maybe we should check >0 instead of !=0, or even some larger threshold? At least the current rationale only really makes sense with increased tracking; though if both CSS and LaTeX have this convention then I guess it's fine too).

I'm not sure with negative tracking. If you really want to move letters sort of into each other you probably don't want ligatures either. But I suppose negative tracking is much more likely to be a very small number.

@cady-b

cady-b commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Yes, It'd become a Smart<bool> in rust. IIRC the default for ligatures is currently true; that would change to auto, and be evaluated as true unless tracking is set. If an explicit true / false is given, that'd be used unconditionally.

I agree that this would still be a weird interface; just slightly more predictable and give space for relevant documentation (explaining why the default is auto). Though as for dlig and hlig I'm also much less sure about how to fit those in sadly; we don't really have the notion of truthy or falsy values that can still be overwritten currently.

One option would be to just document that all of these are mere suggestions that can be overwritten by other values were sensible, pointing to text.features for concrete settings, but that's also unfortunate.


Generally setting ligatures: false when you adjust kerning is also an okay ask in my opinion and doesn't necessarily have to be automatic. We could hint in the documentation of tracking to consider this similarly to what microtype says.

I feel more input and discussion would be good here either way, which is why making issues first is generally a good idea 😅. Ultimately we'll have to hear from Laurenz what his vision here is though, as generally he's the person you have to convince to get things merged.


I'm not sure with negative tracking. If you really want to move letters sort of into each other you probably don't want ligatures either. But I suppose negative tracking is much more likely to be a very small number.

I guess you're right. Unlike positive tracking, negative tracking only makes sense in a very limited fashion were (imo) ligatures would still be fine visually, but beyond that to where letters are overlapping it might indeed make sense to also disable ligatures for more consistency.

@lasernoises

Copy link
Copy Markdown
Author

I feel more input and discussion would be good here either way, which is why making issues first is generally a good idea 😅. Ultimately we'll have to hear from Laurenz what his vision here is though, as generally he's the person you have to convince to get things merged.

Yeah, in hindsight I probably should have created an issue first. It just seemed like a standard typographic thing to me to disable them with tracking, but after seeing that I misunderstood the microtype thing it seems much less clear.

@laurmaedje laurmaedje added text Related to the text category, which is all about text handling, shaping, etc. waiting-on-review This PR is waiting to be reviewed. labels Jun 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

text Related to the text category, which is all about text handling, shaping, etc. waiting-on-review This PR is waiting to be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants