【问题标题】:Highlighting Combining Characters突出显示组合字符
【发布时间】:2014-10-16 15:12:51
【问题描述】:

我正在尝试构建一个小系统来突出显示与常规字符不同颜色的字符组合。举个例子:

* { font-size: 72px }
b { font-weight: normal; color: red }
Te&#x301;st A&#x334; B&#x353; <br/>
Te<b>&#x301;</b>st A<b>&#x334;</b> B<b>&#x353;</b>

我希望三个组合字符(重音符号、波浪号覆盖和下面的 x)以红色突出显示,但如果在原始文本中,则保持它们所在的位置。问题是,当我在 HTML 元素中包装组合字符时,它不再“附加”到基本字符,而是与文本的其余部分内联。

有没有办法用 HTML / CSS 来完成这个?

注意:我已经查看了herehere 的答案,但它们似乎都只从“几何”上解决问题——即它们突出了某个字符中的某个部分地区。这个问题专门关于突出组合字符的“印刷”方面。

【问题讨论】:

标签: html css combining-marks


【解决方案1】:

我不确定我是否完全理解了您的问题,但这里是。如果您现在只需要重音返回正确的位置,现在它是单独设置的,您可以应用类似于:

* { font-size: 72px }
b { font-weight: normal; color: red; position: absolute; top: 52%;}
Te&#x0301;st <br/>
Te<b>&#x0301;</b>st

【讨论】:

  • 使用position: absolute意味着锐角的实际位置取决于容器。单击 sn-p 中的“整页”链接以了解我的意思。你可以使用position: relative,但你必须为每个角色调整它。
【解决方案2】:

好的,我想我找到了部分解决方案,但这有点棘手。基本上,我必须通过组合字符来渲染整个字符,然后在它上面隐藏另一个字符而不使用任何组合字符:

* { font-size: 72px }
b { font-weight: normal; color: red; width: 0px; overflow: visible; display: inline-block; }
i { font-style: normal; color: black; }
Te&#x0301;st <br/>
T<b>e&#x0301;</b><i>e</i>st

不幸的是,这会在消除锯齿时为基本字符提供非常轻微的红色轮廓。

而且它不适用于某些覆盖字符。在本例中,红色条应为黑色d

* { font-size: 72px }
b { font-weight: normal; color: red; width: 0px; overflow: visible; display: inline-block; }
i { font-style: normal; color: black; }
d&#x336; <br/>
<b>d&#x336;</b><i>d</i>

【讨论】:

  • 您遇到过比这更好的解决方案吗?对我来说很失望,似乎什么都没有。
  • @jcuenod 我刚刚发布了一个您可能感兴趣的基于 SVG 的新答案。
【解决方案3】:

将近一年后,我重新审视了这个问题,并且我已经找到了一个使用 SVG 的更令人满意(虽然更冗长)的解决方案。基本上,这与我之前基于 HTML/CSS 的版本类似,但 SVG 使您能够对底层基本字符的抗锯齿边缘进行剪辑/屏蔽。

剩下的唯一真正问题是如何处理覆盖字符(组合字符直接呈现在底层字符之上)。在这种情况下,您要么需要在覆盖层顶部呈现基本字符(在我的用例中不推荐),要么将覆盖层呈现在不一定完全匹配基本字符宽度的占位符空白字符上。这是一个演示:

svg text {
  x: 50px;
  y: 50px;
  alignment-baseline: middle;
  text-anchor: middle;
  font-size: 55px;
}
svg .backdrop {
  x: 1px;
  y: 1px;
  rx: 15px;
  ry: 15px;
  width: 98px;
  height: 98px;
  fill: url(#grad);
}
svg .cc-above { fill: #F00; }
svg .cc-below { fill: #00F; }
svg .cc-overlay { fill: #0FF; }
svg .cc-base { fill: #000; }
svg .cc-mask { stroke: #000; stroke-width: 3px; }
.sample { float: left; }
.caption { display: block; text-align: center; }
<div class="sample">
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100px" height="100px" viewBox="0 0 100 100">
    <defs>
      <text id="base" x="50" y="50">e</text>
      <linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
        <stop offset="0%" style="stop-color:#DDD;stop-opacity:1" />
        <stop offset="100%" style="stop-color:#888;stop-opacity:1" />
      </linearGradient>
    </defs>
    <rect class="backdrop" />
    <mask id="mask1">
      <rect x="0" y="0" width="100%" height="100%" fill="#fff" />
      <use xlink:href="#base" class="cc-mask" />
    </mask>
    <text class="cc-above" x="50%" y="50%" mask="url(#mask1)">e&#x0300;</text>
    <use xlink:href="#base" class="cc-base" />
  </svg>
  <div class="caption">Above</div>
</div>

<div class="sample">
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100px" height="100px" viewBox="0 0 100 100">
    <defs>
      <text id="base" x="50" y="50">e</text>
      <linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
        <stop offset="0%" style="stop-color:#DDD;stop-opacity:1" />
        <stop offset="100%" style="stop-color:#888;stop-opacity:1" />
      </linearGradient>
    </defs>
    <rect class="backdrop" />
    <mask id="mask1">
      <rect x="0" y="0" width="100%" height="100%" fill="#fff" />
      <use xlink:href="#base" class="cc-mask" />
    </mask>
    <text class="cc-below" x="50%" y="50%" mask="url(#mask1)">e&#x031F;</text>
    <use xlink:href="#base" class="cc-base" />
  </svg>
  <div class="caption">Below</div>
</div>

<div class="sample">
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100px" height="100px" viewBox="0 0 100 100">
    <defs>
      <text id="base" x="50" y="50">e</text>
      <linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
        <stop offset="0%" style="stop-color:#DDD;stop-opacity:1" />
        <stop offset="100%" style="stop-color:#888;stop-opacity:1" />
      </linearGradient>
    </defs>
    <rect class="backdrop" />
    <mask id="mask1">
      <rect x="0" y="0" width="100%" height="100%" fill="#fff" />
      <use xlink:href="#base" class="cc-mask" />
    </mask>
    <use xlink:href="#base" class="cc-base" />
    <text class="cc-overlay" x="50%" y="50%">&#x2002;&#x0334;</text>
  </svg>
  <div class="caption">Overlay</div>
</div>

<div class="sample">
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100px" height="100px" viewBox="0 0 100 100">
    <defs>
      <text id="base" x="50" y="50">e</text>
      <linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
        <stop offset="0%" style="stop-color:#DDD;stop-opacity:1" />
        <stop offset="100%" style="stop-color:#888;stop-opacity:1" />
      </linearGradient>
    </defs>
    <rect class="backdrop" />
    <mask id="mask1">
      <rect x="0" y="0" width="100%" height="100%" fill="#fff" />
      <use xlink:href="#base" class="cc-mask" />
    </mask>
    <text class="cc-above" x="50%" y="50%" mask="url(#mask1)">e&#x0300;</text>
    <text class="cc-below" x="50%" y="50%" mask="url(#mask1)">e&#x031F;</text>
    <use xlink:href="#base" class="cc-base" />
    <text class="cc-overlay" x="50%" y="50%">&#x2002;&#x0334;</text>
  </svg>
  <div class="caption">All</div>
</div>

我对 SVG 没有太多经验,有经验的人可能会找到进一步改进此解决方案的方法。

【讨论】:

    【解决方案4】:

    这是一个 hack,但是如何使用 text-indent:-1ex 将重音向后移动 1 个字符宽度。 http://jsfiddle.net/1tm1Lrrp/4/

    在任何情况下,这些建议都不适用于 i,因为点仍然存在。

    【讨论】:

    • 那更糟。重音应该在第一个例子中的位置,只有红色。
    猜你喜欢
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-26
    • 2014-06-15
    • 2020-10-18
    相关资源
    最近更新 更多