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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41676054/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 12:21:31  来源:igfitidea点击:

How to add fonts to create-react-app based projects?

cssreactjsfontswebpackcreate-react-app

提问by Maxim Veksler

I'm using create-react-appand prefer not to eject.

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

It's not clear where fonts imported via @font-face and loaded locally should go.

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

Namely, I'm loading

也就是说,我正在加载

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

Any suggestions?

有什么建议?

-- EDIT

- 编辑

Including the gist to which Dan referring in his answer

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

?  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');
}

回答by Dan Abramov

There are two options:

有两种选择:

Using Imports

使用导入

This is the suggested option. It ensures your fonts go through the build pipeline, get hashes during compilation so that browser caching works correctly, and that you get compilation errors if the files are missing.

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

As described in “Adding Images, Fonts, and Files”, you need to have a CSS file imported from JS. For example, by default src/index.jsimports src/index.css:

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

import './index.css';

A CSS file like this goes through the build pipeline, and can reference fonts and images. For example, if you put a font in src/fonts/MyFont.woff, your index.cssmight include this:

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

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

Notice how we're using a relative path starting with ./. This is a special notation that helps the build pipeline (powered by Webpack) discover this file.

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

Normally this should be enough.

通常这应该足够了。

Using publicFolder

使用public文件夹

If for some reason you prefer notto use the build pipeline, and instead do it the “classic way”, you can use the publicfolderand put your fonts there.

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

The downside of this approach is that the files don't get hashes when you compile for production so you'll have to update their names every time you change them, or browsers will cache the old versions.

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

If you want to do it this way, put the fonts somewhere into the publicfolder, for example, into public/fonts/MyFont.woff. If you follow this approach, you should put CSS files into publicfolder as well and notimport them from JS because mixing these approaches is going to be very confusing. So, if you still want to do it, you'd have a file like public/index.css. You would have to manually add <link>to this stylesheet from public/index.html:

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

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

And inside of it, you would use the regular CSS notation:

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

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

Notice how I'm using fonts/MyFont.woffas the path. This is because index.cssis in the publicfolder so it will be served from the public path (usually it's the server root, but if you deploy to GitHub Pages and set your homepagefield to http://myuser.github.io/myproject, it will be served from /myproject). However fontsare also in the publicfolder, so they will be served from fontsrelatively (either http://mywebsite.com/fontsor http://myuser.github.io/myproject/fonts). Therefore we use the relative path.

注意我是如何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)提供。因此我们使用相对路径。

Note that since we're avoiding the build pipeline in this example, it doesn't verify that the file actually exists. This is why I don't recommend this approach. Another problem is that our index.cssfile doesn't get minified and doesn't get a hash. So it's going to be slower for the end users, and you risk the browsers caching old versions of the file.

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

?Which Way to Use?

?使用哪种方式?

Go with the first method (“Using Imports”). I only described the second one since that's what you attempted to do (judging by your comment), but it has many problems and should only be the last resort when you're working around some issue.

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

回答by sudo bangbang

Here are some ways of doing this:

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

1. Importing font

1. 导入字体

For example, for using Roboto, install the package using

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

yarn add typeface-roboto

or

或者

npm install typeface-roboto --save

In index.js:

在 index.js 中:

import "typeface-roboto";

There are npm packages for a lot of open source fonts and most of Google fonts. You can see all fonts here. All the packages are from that project.

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

2. For fonts hosted by Third party

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

For example Google fonts, you can go to fonts.google.comwhere you can find links that you can put in your public/index.html

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

screenshot of fonts.google.com

fonts.google.com 的屏幕截图

It'll be like

它会像

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

or

或者

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

3. Downloading the font and adding it in your source code.

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

Download the font. For example, for google fonts, you can go to fonts.google.com. Click on the download button to download the font.

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

Move the font to fontsdirectory in your srcdirectory

将字体移动到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

Now, in App.css, add this

现在,在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');
}

For ttfformat, you have to mention format('truetype'). For woff, format('woff')

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

Now you can use the font in classes.

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

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

4. Using web-font-loader package

4. 使用 web-font-loader 包

Install package using

使用安装包

yarn add webfontloader

or

或者

npm install webfontloader --save

In src/index.js, you can import this and specify the fonts needed

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

import WebFont from 'webfontloader';

WebFont.load({
   google: {
     families: ['Titillium Web:300,400,700', 'sans-serif']
   }
});

回答by Hitesh Sahu

  1. Go to Google Fonts https://fonts.google.com/
  2. Select your font as depicted in image below:
  1. 转到 Google 字体https://fonts.google.com/
  2. 选择您的字体,如下图所示:

enter image description here

在此处输入图片说明

  1. Copy and then paste that url in new tab you will get the css code to add that font. In this case if you go to
  1. 复制然后将该 url 粘贴到新选项卡中,您将获得添加该字体的 css 代码。在这种情况下,如果你去

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

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

It will open like this:

它会像这样打开:

enter image description here

在此处输入图片说明

4, Copy and paste that code in your style.css and simply start using that font like this:

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

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

Result:

结果:

enter image description here

在此处输入图片说明

回答by Delfino

You can use the WebFontmodule, which greatly simplifies the process.

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

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

回答by Yasin UYSAL

I was making mistakes like this.

我犯了这样的错误。

@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";

It works properly this way

它以这种方式正常工作

@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);

回答by puiu

I spent the entire morning solving a similar problem after having landed on this stack question. I used Dan's first solution in the answer above as the jump off point.

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

Problem

问题

I have a dev (this is on my local machine), staging, and production environment. My staging and production environments live on the same server.

我有一个开发(在我的本地机器上)、暂存和生产环境。我的临时环境和生产环境位于同一台服务器上。

The app is deployed to staging via acmeserver/~staging/note-taking-appand the production version lives at acmeserver/note-taking-app(blame IT).

该应用程序部署到暂存通过acmeserver/~staging/note-taking-app,生产版本位于acmeserver/note-taking-app(归咎于 IT)。

All the media files such as fonts were loading perfectly fine on dev (i.e., react-scripts start).

所有媒体文件(如字体)都在 dev(即react-scripts start)上加载得很好。

However, when I created and uploaded staging and production builds, while the .cssand .jsfiles were loading properly, fonts were not. The compiled .cssfile looked to have a correct path but the browser http request was getting some very wrong pathing (shown below).

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

The compiled main.fc70b10f.chunk.cssfile:

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

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

The browser http request is shown below. Note how it is adding in /static/css/when the font file just lives in /static/media/as well as duplicating the destination folder. I ruled out the server config being the culprit.

浏览器http请求如下所示。请注意它是如何/static/css/在字体文件刚刚存在/static/media/以及复制目标文件夹时添加的。我排除了服务器配置是罪魁祸首。

The Refereris partly at fault too.

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

The package.jsonfile had the homepageproperty set to ./note-taking-app. This was causing the problem.

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"
  }
  //...
}

Solution

解决方案

That was long winded — but the solution is to:

这是冗长的 - 但解决方案是:

  1. change the PUBLIC_URLenv variable depending on the environment
  2. remove the homepageproperty from the package.jsonfile
  1. PUBLIC_URL根据环境更改env 变量
  2. homepagepackage.json文件中删除属性

Below is my .env-cmdrcfile. I use .env-cmdrcover regular .envbecause it keeps everything together in one file.

下面是我的.env-cmdrc文件。我.env-cmdrc经常使用,.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"
  }
}

Routing via react-router-domworks fine too — simply use the PUBLIC_URLenv variable as the basenameproperty.

通过路由也可以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 };

The server config is set to route all requests to the ./index.htmlfile.

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

Finally, here is what the compiled main.fc70b10f.chunk.cssfile looks like after the discussed changes were implemented.

最后,这是main.fc70b10f.chunk.css在实施所讨论的更改后编译文件的样子。

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

Reading material

阅读材料