You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

字体连字异常问题:负letter-spacing下部分连字失效

解决负letter-spacing下字体连字失效的问题

问题场景

给标题设置了负letter-spacing,但希望字体连字(如"ffi"、"ffl"、"ffj"、"fi"、"fl"、"fj"、"ff")正常生效。尝试用JavaScript选中这些连字字符,包裹进<span>标签并设置letter-spacing: 0,但出现异常:同一元素内混合多种连字时,部分长连字(如第一个<h1>里的"ffi")失效,浏览器会优先渲染短连字(如"fi")而非完整的长连字。

问题原因

  1. 连字处理顺序错误:短连字的替换逻辑会破坏已匹配的长连字结构。即使数组里长连字在前,直接操作innerHTML会导致后续短连字的正则匹配到长连字内部的片段,把<span class="glyph">ffi</span>拆成<span class="glyph">f<span class="glyph">fi</span></span>,彻底破坏长连字的完整性。
  2. DOM结构污染:直接替换innerHTML会重复包裹已处理的内容,导致标签嵌套混乱,浏览器无法识别完整的连字字符序列。

解决方案

  1. 按连字长度从长到短排序:优先处理3字符的长连字,再处理2字符的短连字,避免短连字破坏长连字结构。
  2. 操作纯文本节点:通过遍历文本节点精准拆分并包裹目标连字,避免破坏已生成的DOM结构。

修改后的完整代码示例

JavaScript代码

// 按字符长度从长到短排序连字,优先处理长连字
let ligatures = ["ffi", "ffl", "ffj", "fi", "fl", "fj", "ff"].sort((a, b) => b.length - a.length);
highlightLigatures(document.querySelectorAll("h1"), ligatures);

function highlightLigatures(elements, substrings) {
  elements.forEach((el) => {
    highlightText(el, substrings, "glyph");
  });
}

function highlightText(el, substrings, classNames = "glyph") {
  // 使用TreeWalker遍历所有纯文本节点
  const treeWalker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, null, false);
  let node;
  while (node = treeWalker.nextNode()) {
    let text = node.nodeValue;
    // 遍历所有连字,逐个处理当前文本节点
    substrings.forEach(substring => {
      let index;
      // 循环查找当前文本中的连字,直到全部处理完
      while ((index = text.indexOf(substring)) !== -1) {
        // 拆分文本节点:前半部分、连字部分、后半部分
        const before = node.splitText(index);
        const ligatureNode = before.splitText(substring.length);
        // 创建span包裹连字
        const span = document.createElement('span');
        span.className = classNames;
        span.appendChild(before);
        // 替换原来的文本节点为span
        ligatureNode.parentNode.insertBefore(span, ligatureNode);
        // 更新text变量为剩余的文本内容
        text = ligatureNode.nodeValue;
        // 将当前节点切换为剩余的文本节点,继续处理
        node = ligatureNode;
      }
    });
  }
}

CSS代码

h1 {
  font-size: 4rem;
  font-family: 'Cormorant Garamond', serif;
  font-weight: 400;
  margin: 0;
  letter-spacing: -0.08em;
}

.glyph {
  letter-spacing: 0;
  color: red;
}

HTML代码

<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond&display=swap" rel="stylesheet">

<h1>Office (the ffi ligature is not working) Often Oficial Offset</h1>
<h1>Office (the ffi ligature is working)</h1>

效果说明

修改后,长连字会被优先完整包裹,短连字仅匹配未被处理的纯文本片段,不会破坏已生成的连字结构。浏览器能识别完整的连字字符序列,同时letter-spacing:0的span能让连字正常渲染,解决了混合连字场景下的失效问题。

内容的提问来源于stack exchange,提问作者user2991837

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 00:03:15