cssfontstypography

Keep font ligatures and have tighter letter-spacing


The font I am using has lovely ligatures:

enter image description here

But when I tighten the letter-spacing, for example:

letter-spacing: -0.01em;

The ligatures no longer work and the individual characters (f f i) are used:

enter image description here

I have the following:

font-variant-ligatures: common-ligatures;

In Desktop Publishing the ligatures will still display even with negative letter spacing / kerning. Is there a way to keep the ligatures on a web page?


Solution

  • Sure, browsers could add a certain threshold for rather subtle changes in letter spacing/tracking to disable ligatures - just like design applications (e.g. Illustrator, Indesign).

    On the other hand - I don't blame them:
    As you probably know, ligatures are additional (and manually designed) glyphs that replace certain combinations of characters.
    So the safe way to prevent strange text rendering is to disable ligatures whenever the tracking deviates from the standard.

    In your case, you could wrap all ligature-related character combinations in a span element to preserve ligatures.

    Here's an JS helper example:

    // add font-family classes
    let ligatures = ["ffi", "ft", "fi", "ff"];
    let ligatureEls = document.querySelectorAll(".findLigatures");
    ligatureEls.forEach((el) => {
      highlightText(el, ligatures, "highlight ligature");
    });
    
    function highlightText(el, substrings, classNames = "highlight") {
      substrings.forEach((substring) => {
        let regex = new RegExp(`(${substring})`, "gi");
        el.childNodes.forEach((childNode) => {
          if (childNode.nodeValue && regex.test(childNode.nodeValue)) {
            childNode.parentNode.innerHTML = childNode.parentNode.innerHTML.replace(
              regex,
              `<span class="${classNames}">${substring}</span>`
            );
          }
        });
      });
    }
    body {
      font-size: 5em;
      font-family: georgia;
      font-family: 'Cormorant Garamond', serif;
    }
    
    p {
      margin: 0;
    }
    
    .narrow {
      letter-spacing: -0.08em;
    }
    
    .wide {
      letter-spacing: 0.08em;
    }
    
    .ligature {
      letter-spacing: 0;
    }
    
    .highlight {
      text-decoration: underline;
      text-decoration-color: red;
      text-decoration-thickness: 0.05em;
      text-underline-offset: 0.1em;
    }
    <link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond&display=swap" rel="stylesheet">
    
    <p class="narrow findLigatures">Office Often Oficial Offset</p>
    <p class="wide findLigatures">Office Often Oficial Offset</p>

    We're basically using a highlighting helper function to find certain character combinations (specified in an array) and wrap these textnodes in a <span> element with an extra class name. This way we can "disable" the custom letter-spacing property (by resetting it to 0) and thus retain the ligature rendering.