¿Cómo agregar fuentes para crear proyectos basados ​​en aplicaciones?

177

Estoy usando create-react-app y prefiero no hacerlo eject.

No está claro dónde deberían ir las fuentes importadas a través de @ font-face y cargadas localmente.

A saber, estoy cargando

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

¿Alguna sugerencia?

- EDITAR

Incluyendo la esencia a la que Dan se refiere en su respuesta

  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');
}
Maxim Veksler
fuente
2
¿Ha marcado la sección "Agregar fuentes" en su Guía del usuario?
Dan Abramov
2
@DanAbramov que tengo, la recomendación es importar la fuente. Pero siento que no está claro (al menos no para mí) sobre cómo debería hacerse en la práctica. Mientras tanto, he hecho esto gist.github.com/maximveksler/5b4f80c5ded20237c3deebc82a31dcd5 y parece funcionar (alertas de paquetes web si no puede encontrar un archivo de fuente) pero estoy seguro de que no es la solución óptima y un ejemplo o tenerlo documentado aquí ayudaría. Ty para llegar!
Maxim Veksler
2
Respondí. Su enfoque me parece incorrecto: %PUBLIC_URL%no puede funcionar (y es innecesario) en un archivo CSS. Además, como se describe en la guía, debe utilizar las importaciones JS en casi todos los casos, no la carpeta pública.
Dan Abramov
¿Hay alguna utilidad / paquete para escanear la carpeta especificada en busca de fuentes y generar el archivo de script con todas las variaciones de fuente? Es tedioso escribirlo todo manualmente
Helloworld

Respuestas:

290

Hay dos opciones:

Usando Importaciones

Esta es la opción sugerida. Asegura que sus fuentes pasen por la canalización de compilación, obtengan hashes durante la compilación para que el almacenamiento en caché del navegador funcione correctamente y que obtenga errores de compilación si faltan los archivos.

Como se describe en "Agregar imágenes, fuentes y archivos" , debe tener un archivo CSS importado de JS. Por ejemplo, por defecto las src/index.jsimportaciones src/index.css:

import './index.css';

Un archivo CSS como este pasa por la canalización de compilación y puede hacer referencia a fuentes e imágenes. Por ejemplo, si pones una fuente ensrc/fonts/MyFont.woff , index.csspuede incluir esto:

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

Observe cómo estamos usando una ruta relativa a partir de ./. Esta es una notación especial que ayuda a la canalización de compilación (desarrollada por Webpack) a descubrir este archivo.

Normalmente esto debería ser suficiente.

Usando publicCarpeta

Si por alguna razón prefiere no usar la canalización de compilación y, en su lugar, hacerlo de la "manera clásica", puede usar elpublic carpeta y colocar sus fuentes allí.

La desventaja de este enfoque es que los archivos no obtienen hashes cuando compila para la producción, por lo que tendrá que actualizar sus nombres cada vez que los cambie, o los navegadores guardarán en caché las versiones anteriores.

Si desea hacerlo de esta manera, coloque las fuentes en algún lugar de la publiccarpeta, por ejemplo, en public/fonts/MyFont.woff. Si sigue este enfoque, también debe colocar los archivos CSS en la publiccarpeta y no importarlos desde JS porque mezclar estos enfoques será muy confuso. Entonces, si aún quieres hacerlo, tendrás un archivo como public/index.css. Tendría que agregar manualmente <link>a esta hoja de estilo desde public/index.html:

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

Y dentro de él, usarías la notación CSS normal:

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

Observe cómo lo estoy usando fonts/MyFont.woffcomo ruta. Esto se debe a que index.cssestá en la publiccarpeta, por lo que se servirá desde la ruta pública (generalmente es la raíz del servidor, pero si implementa en GitHub Pages y configura su homepagecampo http://myuser.github.io/myproject, se servirá desde /myproject). Sin embargo fonts, también están en la publiccarpeta, por lo que serán atendidos desde fontsrelativamente (ya sea http://mywebsite.com/fontso http://myuser.github.io/myproject/fonts). Por lo tanto, usamos la ruta relativa.

Tenga en cuenta que dado que estamos evitando la canalización de compilación en este ejemplo, no verifica que el archivo realmente exista. Por eso no recomiendo este enfoque. Otro problema es que nuestro index.cssarchivo no se minimiza y no obtiene un hash. Por lo tanto, será más lento para los usuarios finales y correrá el riesgo de que los navegadores almacenen en caché las versiones antiguas del archivo.

 ¿Qué manera de usar?

Vaya con el primer método ("Uso de importaciones"). Solo describí el segundo, ya que eso es lo que intentaste hacer (a juzgar por tu comentario), pero tiene muchos problemas y solo debería ser el último recurso cuando estés trabajando en algún problema.

Dan Abramov
fuente
55
un ejemplo en los documentos sería útil, también estaba un poco confundido
Tom
2
Descubrí que en realidad tenía que usar la url ./fonts/Myfont.woff y no ./Myfont.woff
th3morg
57
Si alguien agrega una ttffuente, debe dar en truetypelugar de ttfcomo parámetro para el format* .
milkersarac
3
@milkersarac eres el mejor!
João Vilaça
19
Siguiendo a @milkersarac si estás usando otfnecesitas poner opentype.
Karl Taylor
46

Aquí hay algunas formas de hacer esto:

1. Importando fuente

Por ejemplo, para usar Roboto, instale el paquete usando

yarn add typeface-roboto

o

npm install typeface-roboto --save

En index.js:

import "typeface-roboto";

Hay paquetes npm para muchas fuentes de código abierto y la mayoría de las fuentes de Google. Puedes ver todas las fuentes aquí . Todos los paquetes son de ese proyecto. .

2. Para fuentes alojadas por terceros

Por ejemplo, las fuentes de Google, puede ir a fonts.google.com donde puede encontrar enlaces que puede poner en supublic/index.html

captura de pantalla de fonts.google.com

Será como

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

o

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

3. Descargando la fuente y agregándola en su código fuente.

Descargue la fuente. Por ejemplo, para las fuentes de google, puede ir a fonts.google.com . Haga clic en el botón de descarga para descargar la fuente.

Mueva la fuente al fontsdirectorio en su srcdirectorio

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

Ahora, en App.css, agrega esto

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

Para el ttfformato, tienes que mencionar format('truetype'). porwoff ,format('woff')

Ahora puedes usar la fuente en las clases.

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

4. Usando el paquete web-font-loader

Instalar paquete usando

yarn add webfontloader

o

npm install webfontloader --save

En src/index.js, puede importar esto y especificar las fuentes necesarias

import WebFont from 'webfontloader';

WebFont.load({
   google: {
     families: ['Titillium Web:300,400,700', 'sans-serif']
   }
});
sudo bangbang
fuente
2
--save es el valor predeterminado con npm 5 (2017)
NattyC
Gracias por el comentario @Natalie, me alegra que npm haya hecho ese cambio.
sudo bangbang
@sudobangbang Gracias, la solución # 3 funcionó para mí. Sin embargo, ¿hay alguna manera de no colocar la fontscarpeta debajo src, sino debajo public? Lo intenté, pero parece que no está permitido ...
Yossi Vainshtein
@YossiVainshtein, no lo creo. Como está utilizando las fuentes en App.css, también debe compilarse con ellas.
sudo bangbang
For ttf format, you have to mention format('truetype'). For woff, format('woff')lo hizo por mi! ¡gracias!
Joseph Briggs
7
  1. Vaya a Google Fonts https://fonts.google.com/
  2. Seleccione su fuente como se muestra en la imagen a continuación:

ingrese la descripción de la imagen aquí

  1. Copie y pegue esa URL en la nueva pestaña, obtendrá el código CSS para agregar esa fuente. En este caso si vas a

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

Se abrirá así:

ingrese la descripción de la imagen aquí

4, copie y pegue ese código en su style.css y simplemente comience a usar esa fuente de esta manera:

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

Resultado:

ingrese la descripción de la imagen aquí

Hitesh Sahu
fuente
1
En muchos casos (ej .: redes corporativas), el firewall bloquea el acceso a CDN externo y este método, aunque correcto, puede no funcionar. Tenemos varias VLAN en nuestra organización y, a excepción de TI y algunas otras, todas las VLAN bloquean el acceso externo a CDN, lo que también significa que el contenido de Google CDN también está bloqueado. He estado allí, hecho eso.
AnBisw
2

Puede usar el módulo WebFont , que simplifica enormemente el proceso.

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

Estaba cometiendo errores como este.

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

Funciona correctamente de esta manera.

@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);
Yasin UYSAL
fuente
0

Pasé toda la mañana resolviendo un problema similar después de haber aterrizado en esta pregunta de la pila. Usé la primera solución de Dan en la respuesta anterior como punto de partida.

Problema

Tengo un entorno de desarrollo, montaje y producción (esto está en mi máquina local). Mis escenarios y entornos de producción viven en el mismo servidor.

La aplicación se implementa a través de la puesta en escena acmeserver/~staging/note-taking-appy la versión de producción vive en acmeserver/note-taking-app(culpar a TI).

Todos los archivos multimedia, como las fuentes, se cargaban perfectamente bien en dev (es decir, react-scripts start).

Sin embargo, cuando creé y cargué las etapas y las compilaciones de producción, mientras que los archivos .cssy .jsse cargaban correctamente, las fuentes no. El .cssarchivo compilado parecía tener una ruta correcta, pero la solicitud http del navegador estaba recibiendo una ruta muy incorrecta (se muestra a continuación).

El main.fc70b10f.chunk.cssarchivo compilado :

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

La solicitud http del navegador se muestra a continuación. Tenga en cuenta cómo se agrega /static/css/cuando el archivo de fuente solo vive /static/media/y duplica la carpeta de destino. Descarté que la configuración del servidor sea la culpable.

El Refereres en parte culpable también.

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

El package.jsonarchivo tenía la homepagepropiedad establecida en ./note-taking-app. Esto estaba causando el problema.

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

Solución

Eso fue largo aliento, pero la solución es:

  1. cambiar el PUBLIC_URL variable env según el entorno
  2. eliminar la homepagepropiedad del package.jsonarchivo

Debajo está mi .env-cmdrcarchivo. Lo uso .env-cmdrccon regularidad .envporque mantiene todo junto en un solo archivo.

{
  "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"
  }
}

El enrutamiento a través de react-router-domfunciona bien también: simplemente use la PUBLIC_URLvariable env como basenamepropiedad.

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

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

export { createRouter };

La configuración del servidor está configurada para enrutar todas las solicitudes al ./index.htmlarchivo.

Finalmente, así es main.fc70b10f.chunk.csscomo se ve el archivo compilado después de que se implementaron los cambios discutidos.

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

Material de lectura

puiu
fuente