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


177

我正在使用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');
}

2
您是否已查看其用户指南中的“添加字体”部分?
Dan Abramov

2
@DanAbramov我有,建议是导入字体。但是我觉得目前尚不清楚(至少对我来说不是这样)。同时,我已经完成了此操作gist.github.com/maximveksler/5b4f80c5ded20237c3deebc82a31dcd5,它似乎可以正常工作(如果找不到字体文件,Web Pack会发出警报),但我确定这不是最佳解决方案,并且是一个示例或在此处进行记录将有所帮助。ty伸出手!
Maxim Veksler,

2
我回答了。您的方法对我来说似乎是错误的:%PUBLIC_URL%在CSS文件中无法工作(并且是不必要的)。另外,如指南中所述,几乎在所有情况下都应使用JS导入,而不是公用文件夹。
Dan Abramov

是否有任何实用程序/软件包可扫描指定文件夹中的字体并生成具有所有字体变化的脚本文件?手动编写全部内容很麻烦
helloworld

Answers:


289

有两种选择:

使用导入

这是建议的选项。它可以确保字体通过生成管道,在编译过程中散列,以便浏览器缓存正常工作,并且在文件丢失时出现编译错误。

“添加图像,字体和文件”中所述,您需要从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');
}

请注意,我们如何使用以开头的相对路径./。这是一种特殊的表示法,可帮助构建管道(由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.csspublic文件夹位于文件夹中,因此可以从公共路径提供服务(通常是服务器根目录,但是如果部署到GitHub Pages并将homepage字段设置为http://myuser.github.io/myproject,则可以从提供/myproject)。但是,fonts它们也位于public文件夹中,因此将从fonts相对位置(http://mywebsite.com/fontshttp://myuser.github.io/myproject/fonts)进行投放。因此,我们使用相对路径。

请注意,由于在本示例中我们避免使用构建管道,因此它不会验证文件是否实际存在。这就是为什么我不推荐这种方法的原因。另一个问题是我们的index.css文件没有缩小并且没有散列。因此,对于最终用户而言,它的运行速度将会变慢,并且浏览器会缓存文件的旧版本,因此您可能会承担风险。

 使用哪种方式?

使用第一种方法(“使用导入”)。我仅描述了第二个,因为这是您尝试执行的操作(根据您的评论来判断),但是它有很多问题,并且只有在解决某些问题时才是最后的选择。


5
文档中的一个示例将非常有用,我也有些困惑
Tom

2
我发现我实际上必须使用URL ./fonts/Myfont.woff而不是./Myfont.woff
th3morg

57
如果有人要添加ttf字体,则应该给*truetype而不是ttf作为参数。format
milkersarac

3
@milkersarac你是最棒的!
若昂Vilaça

19
如果您正在使用@milkersarac,则otf需要输入opentype
卡勒·泰勒

46

以下是一些方法:

1.导入字体

例如,要使用Roboto,请使用

yarn add typeface-roboto

要么

npm install typeface-roboto --save

在index.js中:

import "typeface-roboto";

npm软件包包含许多开源字体和大多数Google字体。您可以在此处查看所有字体。所有软件包均来自该项目

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')。对于woffformat('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']
   }
});

2
--save默认为npm 5(2017)
NattyC '19

谢谢@Natalie的评论,我很高兴npm做出了更改。
sudo bangbang

@sudobangbang谢谢,解决方案3对我有用。但是-有没有一种方法可以将fonts文件夹放在下src,而public不是下?我尝试过,但是似乎不允许...
Yossi Vainshtein

@YossiVainshtein,我不这么认为。当您在App.css中使用字体时,还应该使用它进行编译。
sudo bangbang

For ttf format, you have to mention format('truetype'). For woff, format('woff')为我做到了!谢谢!
约瑟夫·布里格斯

7
  1. 转到Google字体https://fonts.google.com/
  2. 选择您的字体,如下图所示:

在此处输入图片说明

  1. 复制该网址,然后将其粘贴到新标签中,您将获得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>

结果:

在此处输入图片说明


1
在许多情况下(例如,公司网络),防火墙会阻止对外部CDN的访问,尽管这种方法正确,但可能无法使用。我们组织中有多个VLAN,除了IT和其他几个VLAN外,所有VLAN都阻止外部CDN访问,这也意味着Google的内容CDN也被阻止。去过也做过。
AnBisw

2

您可以使用WebFont模块,这大大简化了过程。

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

0

我在犯这样的错误。

@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i&amp;subset=cyrillic,cyrillic-ext,latin-ext";
@import "https://use.fontawesome.com/releases/v5.3.1/css/all.css";

这样可以正常工作

@import url(https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i&amp;subset=cyrillic,cyrillic-ext,latin-ext);
@import url(https://use.fontawesome.com/releases/v5.3.1/css/all.css);

0

在讨论了这个堆栈问题之后,我花了整个上午来解决类似的问题。在以上答案中,我使用了Dan的第一个解决方案作为起点。

问题

我有一个开发人员(在我的本地计算机上),暂存和生产环境。我的登台和生产环境位于同一台服务器上。

该应用程序通过进行部署,acmeserver/~staging/note-taking-app生产版本位于acmeserver/note-taking-app(非IT)。

所有的媒体文件(例如字体)都可以在dev上完美加载(即, react-scripts start)。

但是,当我创建并上载暂存和生产版本时,虽然.css.js文件正确加载,但字体却不正确。编译后的.css文件看起来具有正确的路径,但是浏览器的http请求得到了一些非常错误的路径(如下所示)。

编译main.fc70b10f.chunk.css文件:

@font-face {
  font-family: SairaStencilOne-Regular;
  src: url(note-taking-app/static/media/SairaStencilOne-Regular.ca2c4b9f.ttf) ("truetype");
}

浏览器http请求如下所示。请注意,/static/css/当字体文件存在时,它是如何添加的,/static/media/以及如何复制目标文件夹。我排除了导致服务器配置问题的原因。

Referer过错是部分过。

GET /~staging/note-taking-app/static/css/note-taking-app/static/media/SairaStencilOne-Regular.ca2c4b9f.ttf HTTP/1.1
Host: acmeserver
Origin: http://acmeserver
Referer: http://acmeserver/~staging/note-taking-app/static/css/main.fc70b10f.chunk.css

package.json文件的homepage属性设置为./note-taking-app。这是造成问题的原因。

{
  "name": "note-taking-app",
  "version": "0.1.0",
  "private": true,
  "homepage": "./note-taking-app",
  "scripts": {
    "start": "env-cmd -e development react-scripts start",
    "build": "react-scripts build",
    "build:staging": "env-cmd -e staging npm run build",
    "build:production": "env-cmd -e production npm run build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  }
  //...
}

那已经很久了,但是解决方案是:

  1. PUBLIC_URL根据环境更改环境变量
  2. homepagepackage.json文件中删除属性

以下是我的.env-cmdrc文件。我使用.env-cmdrc了over Regular,.env因为它将所有内容都保存在一个文件中。

{
  "development": {
    "PUBLIC_URL": "",
    "REACT_APP_API": "http://acmeserver/~staging/note-taking-app/api"
  },
  "staging": {
    "PUBLIC_URL": "/~staging/note-taking-app",
    "REACT_APP_API": "http://acmeserver/~staging/note-taking-app/api"
  },
  "production": {
    "PUBLIC_URL": "/note-taking-app",
    "REACT_APP_API": "http://acmeserver/note-taking-app/api"
  }
}

通过进行路由也可以react-router-dom正常工作-只需使用PUBLIC_URLenv变量作为basename属性。

import React from "react";
import { BrowserRouter } from "react-router-dom";

const createRouter = RootComponent => (
  <BrowserRouter basename={process.env.PUBLIC_URL}>
    <RootComponent />
  </BrowserRouter>
);

export { createRouter };

服务器配置设置为将所有请求路由到./index.html文件。

最后,这是main.fc70b10f.chunk.css讨论的更改实现后的编译文件外观。

@font-face {
  font-family: SairaStencilOne-Regular;
  src: url(/~staging/note-taking-app/static/media/SairaStencilOne-Regular.ca2c4b9f.ttf)
    format("truetype");
}

阅读材料

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.