字体连字异常问题:负letter-spacing下部分连字失效
解决负letter-spacing下字体连字失效的问题
问题场景
给标题设置了负letter-spacing,但希望字体连字(如"ffi"、"ffl"、"ffj"、"fi"、"fl"、"fj"、"ff")正常生效。尝试用JavaScript选中这些连字字符,包裹进<span>标签并设置letter-spacing: 0,但出现异常:同一元素内混合多种连字时,部分长连字(如第一个<h1>里的"ffi")失效,浏览器会优先渲染短连字(如"fi")而非完整的长连字。
问题原因
- 连字处理顺序错误:短连字的替换逻辑会破坏已匹配的长连字结构。即使数组里长连字在前,直接操作
innerHTML会导致后续短连字的正则匹配到长连字内部的片段,把<span class="glyph">ffi</span>拆成<span class="glyph">f<span class="glyph">fi</span></span>,彻底破坏长连字的完整性。 - DOM结构污染:直接替换
innerHTML会重复包裹已处理的内容,导致标签嵌套混乱,浏览器无法识别完整的连字字符序列。
解决方案
- 按连字长度从长到短排序:优先处理3字符的长连字,再处理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
相关产品推荐
相关产品推荐

