使用 CSS 和 JavaScript 修改特定字母

Avatar of Bret Cameron
Bret Cameron

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

在 CSS 中更改特定字符可能是一个挑战。通常,我们被迫在 HTML 中逐个实现所需的更改,可能使用 span 元素。但是,在一些特定情况下,仍然可能使用以 CSS 为中心的解决方案。在本文中,我们将首先介绍一些更改字符的 CSS 优先方法,然后再考虑需要转向 JavaScript 的场景。

CSS

目前,CSS 并不擅长在不修改 HTML 的情况下定位特定字符。但是,在某些情况下,CSS 可能是最佳选择。

@font-face

@font-face 规则通常用于创建自定义字体,但其 unicode-range 属性也可以让我们定位特定字符。

例如,假设我们的网站标题中经常包含 & 符号。我们希望使用比标题字体更华丽的字体,而不是标题字体。我们可以查找 & 符号的 Unicode 值 (U+0026),并使用 unicode-range 定位此特定字符。

@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@300');

h1, h2, h3, h4, h5, h6 {
  font-family:  'Ampersand', Montserrat, sans-serif;
}

@font-face {
  font-family: 'Ampersand';
  src: local('Times New Roman');
  unicode-range: U+0026;
}

尝试使用以下 HTML 代码来查看其效果

<h1>Jane Austen Novels</h1>
<h2>Pride & Prejudice</h2>
<h2>Sense & Sensibility</h2>

::first-letter

::first-letter 伪元素主要用于首字母大写,并且所有主流浏览器都支持它。

p::first-letter {
  font-size: 125%;
  font-weight: bold;
}

当然,这仅在相对有限的场景中才有用。人们曾多次呼吁使用 ::nth-letter 伪元素(包括 CSS-Tricks 上的这篇文章),但目前这只是一个梦想!

::after

使用 ::after 伪元素和 content 属性,我们可以为最后一个字符实现类似的效果——只要该字符始终相同。例如,以下是如何在每个 h2 元素后面添加一个花哨的斜体感叹号

h2::after {
  content: '\0021';
  color: red;
  font-style: italic;
}

font-variant-alternates

最后,还有 font-variant-alternates 属性。这 仅受 Firefox 支持,因此不建议用于生产环境,但对于非常具体的场景可能值得了解:如果字体碰巧包含备用字形,我们可以使用此属性和 character-variant() 函数为我们选择的字符选择首选字形。

JavaScript

转向 JavaScript 不需要以性能为代价,尤其是在构建时运行 HTML 修改函数时。最常见的用例可能是使用 span 元素查找并替换 HTML 中的特定字符。为简单起见,我将从客户端示例开始,之后我们将研究使用 webpack 在构建时运行此操作。

运行时查找和替换

假设,每当我们在网站的标题中包含“LOGO”文本时,我们都希望仅对第一个“O”字符添加特殊样式,方法是将其包装在一个带有 .special-o 类的 span 元素中。

const headings = document.querySelectorAll("h1, h2, h3, h4, h5, h6");

for (const heading of headings) {
  heading.innerHTML = heading.innerHTML
    .replace(/\bLOGO\b/g, 'L<span class="special-o">O</span>GO');
}

在上面的 JavaScript 代码中,我们对每个标题标签执行查找和替换操作。

我们的正则表达式使用元字符 \b 来确保 LOGO 始终是一个单词——而不是更大单词的一部分。例如,我们不想匹配复数“LOGOS”。目前,使用 CSS 无法做到这一点,尤其是因为我们只想定位序列中的第一个“O”。

如果我们想用图像替换“O”——甚至整个单词“LOGO”,则适用相同的原则。

构建时查找和替换

有很多构建工具可用,但由于 webpack 非常流行,因此我们将使用它作为示例——幸运的是,有一个名为 string-replace-loader 的插件可以满足我们的需求。对于 webpack 新手来说,加载器用于预处理文件。在这里,我们可以作为构建的一部分对特定文件执行查找和替换操作。

首先,我们需要安装插件

npm install --save-dev string-replace-loader

然后,在 webpack.config.js 中添加

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.html$/i,
        loader: 'string-replace-loader',
        options: {
          search: '/\bLOGO\b/g',
          replace: 'L<span class="special-o">O</span>GO',
        }
      }
    ]
  }
}

通过更改 test 属性的值,我们可以定位 JSX、TSX、PUG、Handlebars 或任何其他模板文件格式

/\.html$/i # HTML
/\.[jt]sx$/i # JSX or TSX
/\.pug$/i # PUG
/\.handlebars$/i # Handlebars

这种方法的优点是,客户端浏览器中不会运行任何不必要的 JavaScript 代码。

最后说明

最后,如果您熟悉创建和编辑字体,并且希望避免使用 CSS 或 JavaScript,则自定义字体可以解决上面列出的许多场景。对于那些想要尝试这种更注重设计的方法的人来说,有很多免费的字体编辑工具可用,例如 Font ForgeBirdfont