如何向基于 create-react-app 的项目添加字体?

IT技术 css reactjs fonts webpack create-react-app
2021-04-01 03:46:24

我正在使用create-react-app而不想使用eject.

目前尚不清楚通过@font-face 导入并在本地加载的字体应该放在哪里。

也就是说,我正在加载

@font-face {
  font-family: 'Myriad Pro Regular';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Regular'), url('MYRIADPRO-REGULAR.woff') format('woff');
}

有什么建议?

- 编辑

包括丹在他的回答中提到的要点

➜  Client git:(feature/trivia-game-ui-2) ✗ ls -l public/static/fonts
total 1168
-rwxr-xr-x@ 1 maximveksler  staff  62676 Mar 17  2014 MYRIADPRO-BOLD.woff
-rwxr-xr-x@ 1 maximveksler  staff  61500 Mar 17  2014 MYRIADPRO-BOLDCOND.woff
-rwxr-xr-x@ 1 maximveksler  staff  66024 Mar 17  2014 MYRIADPRO-BOLDCONDIT.woff
-rwxr-xr-x@ 1 maximveksler  staff  66108 Mar 17  2014 MYRIADPRO-BOLDIT.woff
-rwxr-xr-x@ 1 maximveksler  staff  60044 Mar 17  2014 MYRIADPRO-COND.woff
-rwxr-xr-x@ 1 maximveksler  staff  64656 Mar 17  2014 MYRIADPRO-CONDIT.woff
-rwxr-xr-x@ 1 maximveksler  staff  61848 Mar 17  2014 MYRIADPRO-REGULAR.woff
-rwxr-xr-x@ 1 maximveksler  staff  62448 Mar 17  2014 MYRIADPRO-SEMIBOLD.woff
-rwxr-xr-x@ 1 maximveksler  staff  66232 Mar 17  2014 MYRIADPRO-SEMIBOLDIT.woff
➜  Client git:(feature/trivia-game-ui-2) ✗ cat src/containers/GameModule.css
.GameModule {
  padding: 15px;
}

@font-face {
  font-family: 'Myriad Pro Regular';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Regular'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-REGULAR.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Condensed';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Condensed'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-COND.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Semibold Italic';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Semibold Italic'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-SEMIBOLDIT.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Semibold';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Semibold'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-SEMIBOLD.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Condensed Italic';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Condensed Italic'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-CONDIT.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Bold Italic';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Bold Italic'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-BOLDIT.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Bold Condensed Italic';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Bold Condensed Italic'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-BOLDCONDIT.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Bold Condensed';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Bold Condensed'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-BOLDCOND.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Bold';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Bold'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-BOLD.woff') format('woff');
}
6个回答

有两种选择:

使用导入

这是建议的选项。它确保您的字体通过构建管道,在编译期间获得哈希值,以便浏览器缓存正常工作,并且如果文件丢失,您将收到编译错误。

“添加图像、字体和文件”中所述,您需要有一个从 JS 导入的 CSS 文件。例如,默认情况下src/index.js导入src/index.css

import './index.css';

像这样的 CSS 文件通过构建管道,并且可以引用字体和图像。例如,如果您将字体放入 中src/fonts/MyFont.woff,则index.css可能包含以下内容:

@font-face {
  font-family: 'MyFont';
  src: local('MyFont'), url(./fonts/MyFont.woff) format('woff');
  /* other formats include: 'woff2', 'truetype, 'opentype',
                            'embedded-opentype', and 'svg' */
}

请注意我们如何使用以 开头的相对路径./这是一个特殊的符号,可以帮助构建管道(由 Webpack 提供支持)发现这个文件。

通常这应该足够了。

使用public文件夹

如果由于某种原因您不想使用构建管道,而是使用“经典方式”,您可以使用该public文件夹并将字体放在那里。

这种方法的缺点是文件在编译生产时不会得到哈希值,因此每次更改它们时都必须更新它们的名称,否则浏览器将缓存旧版本。

如果要这样做,请将字体放入public文件夹中的某个位置,例如放入public/fonts/MyFont.woff. 如果你遵循这种方法,你也应该将 CSS 文件放入public文件夹中,而不是从 JS 中导入它们,因为混合这些方法会非常混乱。所以,如果你仍然想这样做,你会有一个像public/index.css. 您必须从以下位置手动添加<link>到此样式表public/index.html

<link rel="stylesheet" href="%PUBLIC_URL%/index.css">

在其中,您将使用常规的 CSS 符号:

@font-face {
  font-family: 'MyFont';
  src: local('MyFont'), url(fonts/MyFont.woff) format('woff');
}

注意我是如何fonts/MyFont.woff用作路径的。这是因为index.css位于public文件夹中,所以它将从公共路径提供(通常它是服务器根目录,但如果您部署到 GitHub Pages 并将您的homepage字段设置http://myuser.github.io/myproject,它将从 提供/myproject)。但是fonts也在public文件夹中,因此它们将从fonts相对(http://mywebsite.com/fontshttp://myuser.github.io/myproject/fonts)提供。因此我们使用相对路径。

请注意,由于我们在此示例中避免了构建管道,因此它不会验证文件是否确实存在。这就是我不推荐这种方法的原因。另一个问题是我们的index.css文件没有被缩小,也没有得到散列。因此,对于最终用户而言,它会变慢,并且您冒着浏览器缓存旧版本文件的风险。

 使用哪种方式?

使用第一种方法(“使用导入”)。我只描述了第二个,因为那是你试图做的(根据你的评论判断),但它有很多问题,当你解决一些问题时,它应该只是最后的手段。

如果有人正在添加ttf字体,您应该将truetype而不是ttf作为参数提供给format*
2021-06-05 03:46:24
我发现我实际上必须使用 url ./fonts/Myfont.woff 而不是 ./Myfont.woff
2021-06-09 03:46:24
文档中的一个例子会很有用,我也有点困惑
2021-06-15 03:46:24
如果您正在使用,otf关注@milkersarac,您需要将opentype.
2021-06-15 03:46:24
字体正在加载,但文件具有 '<hash>.ttf' 并且它们没有加载,因为 index.css 文件仍然具有常规路由。有任何想法吗?
2021-06-21 03:46:24

这里有一些方法可以做到这一点:

1.导入字体

例如,要使用 Roboto,请使用以下命令安装软件包

yarn add typeface-roboto

或者

npm install typeface-roboto --save

在 index.js 中:

import "typeface-roboto";

有很多开源字体和大部分谷歌字体的 npm 包。您可以在此处查看所有字体所有的包都来自那个项目

2.对于第三方托管的字体

例如 Google 字体,您可以访问fonts.google.com,在那里您可以找到可以放入您的public/index.html

fonts.google.com 的屏幕截图

它会像

<link href="https://fonts.googleapis.com/css?family=Montserrat" rel="stylesheet">

或者

<style>
    @import url('https://fonts.googleapis.com/css?family=Montserrat');
</style>

3. 下载字体并将其添加到您的源代码中。

下载字体。例如,对于 google 字体,您可以访问fonts.google.com点击下载按钮下载字体。

将字体移动到fonts目录中的src目录

src
|
`----fonts
|      |
|      `-Lato/Lato-Black.ttf
|       -Lato/Lato-BlackItalic.ttf
|       -Lato/Lato-Bold.ttf
|       -Lato/Lato-BoldItalic.ttf
|       -Lato/Lato-Italic.ttf
|       -Lato/Lato-Light.ttf
|       -Lato/Lato-LightItalic.ttf
|       -Lato/Lato-Regular.ttf
|       -Lato/Lato-Thin.ttf
|       -Lato/Lato-ThinItalic.ttf
|
`----App.css

现在,在App.css,添加这个

@font-face {
  font-family: 'Lato';
  src: local('Lato'), url(./fonts/Lato-Regular.otf) format('opentype');
}

@font-face {
    font-family: 'Lato';
    font-weight: 900;
    src: local('Lato'), url(./fonts/Lato-Bold.otf) format('opentype');
}

@font-face {
    font-family: 'Lato';
    font-weight: 900;
    src: local('Lato'), url(./fonts/Lato-Black.otf) format('opentype');
}

对于ttf格式,您必须提及format('truetype'). 对于woff,format('woff')

现在您可以在类中使用该字体。

.modal-title {
    font-family: Lato, Arial, serif;
    font-weight: black;
}

4. 使用 web-font-loader 包

使用安装包

yarn add webfontloader

或者

npm install webfontloader --save

在 中src/index.js,您可以导入它并指定所需的字体

import WebFont from 'webfontloader';

WebFont.load({
   google: {
     families: ['Titillium Web:300,400,700', 'sans-serif']
   }
});
@YossiVainshtein,我不这么认为。当您使用 App.css 中的字体时,它也应该与它一起编译。
2021-05-23 03:46:24
字体已弃用,使用字体源:github.com/fontsource/fontsource
2021-05-30 03:46:24
For ttf format, you have to mention format('truetype'). For woff, format('woff')为我做的!谢谢!
2021-06-06 03:46:24
@sudobangbang 谢谢,解决方案 #3 对我有用。但是 - 有没有办法不把fonts文件夹放在src,而是放在下面public我试过了,但似乎不允许...
2021-06-13 03:46:24
从源代码加载的 Web 字体是要走的路。如果您尝试从 Google 加载它们,您会被 Lighthouse 发现并降低页面速度(更不用说中国的用户了)。要提高您的网络字体的性能,请安装woff2cli 工具并woff2_compress在 Google 字体 TTF 下载文件上使用其二进制文件将它们压缩为网络。在你的@font-face规则中,使用font-display规则来加快速度。最后,您需要为 Web 发送 WOFF2 文件。
2021-06-18 03:46:24
  1. 转到 Google 字体https://fonts.google.com/
  2. 选择您的字体,如下图所示:

在此处输入图片说明

  1. 复制然后将该 url 粘贴到新选项卡中,您将获得添加该字体的 css 代码。在这种情况下,如果你去

https://fonts.googleapis.com/css?family=Spicy+Rice

它会像这样打开:

在此处输入图片说明

4,将该代码复制并粘贴到 style.css 中,然后像这样开始使用该字体:

      <Typography
          variant="h1"
          gutterBottom
          style={{ fontFamily: "Spicy Rice", color: "pink" }}
        >
          React Rock
        </Typography>

结果:

在此处输入图片说明

在许多情况下(例如:公司网络),对外部 CDN 的访问被防火墙阻止,这种方法虽然正确,但可能不起作用。我们的组织中有多个 VLAN,除了 IT 和其他少数人之外,所有 VLAN 都阻止外部 CDN 访问,这也意味着 Google 的内容 CDN 也被阻止。去过也做过。
2021-05-30 03:46:24

您可以在不需要 CSS 的情况下使用Web API FontFace构造函数(也称为 Typescript):

export async function loadFont(fontFamily: string, url: string): Promise<void> {
    const font = new FontFace(fontFamily, `local(${fontFamily}), url(${url})`);
    // wait for font to be loaded
    await font.load();
    // add font to document
    document.fonts.add(font);
    // enable font with CSS class
    document.body.classList.add("fonts-loaded");
}
import ComicSans from "./assets/fonts/ComicSans.ttf";

loadFont("Comic Sans ", ComicSans).catch((e) => {
    console.log(e);
});

font.ts用你的module声明一个文件(仅限 TS):

declare module "*.ttf";
declare module "*.woff";
declare module "*.woff2";

如果 TS 无法找到 FontFace 类型作为其仍在官方 WIP 中,请将此声明添加到您的项目中。它将在您的浏览器中工作,IE 除外。

您可以使用WebFontmodule,这大大简化了流程。

render(){
  webfont.load({
     custom: {
       families: ['MyFont'],
       urls: ['/fonts/MyFont.woff']
     }
  });
  return (
    <div style={your style} >
      your text!
    </div>
  );
}