Jak dodawać czcionki do projektów opartych na tworzeniu i reagowaniu na aplikacje?


177

Używam aplikacji create-react- i wolę tego nie robićeject .

Nie jest jasne, gdzie powinny znajdować się czcionki importowane przez @ font-face i ładowane lokalnie.

Mianowicie ładuję

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

Jakieś sugestie?

-- EDYTOWAĆ

Włączając sedno, do którego Dan nawiązał w swojej odpowiedzi

  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
Czy zaznaczyłeś sekcję „Dodawanie czcionek” w jej Podręczniku użytkownika?
Dan Abramov

2
@DanAbramov mam, zalecenie to zaimportować czcionkę. Ale czuję, że nie jest jasne (przynajmniej dla mnie), jak należy to zrobić w praktyce. W międzyczasie zrobiłem to gist.github.com/maximveksler/5b4f80c5ded20237c3deebc82a31dcd5 i wydaje się, że działa (alerty pakietu internetowego, jeśli nie może znaleźć pliku czcionki), ale jestem pewien, że nie jest to optymalne rozwiązanie i przykład lub udokumentowanie tego tutaj byłoby pomocne. za wyciągnięcie ręki!
Maxim Veksler

2
Odpowiedziałam. Twoje podejście wydaje mi się złe: %PUBLIC_URL%nie może działać (i jest niepotrzebne) w pliku CSS. Ponadto, jak opisano w przewodniku, w prawie wszystkich przypadkach należy używać importu JS, a nie folderu publicznego.
Dan Abramov,

Czy istnieje narzędzie / pakiet do skanowania określonego folderu w poszukiwaniu czcionek i generowania pliku skryptu ze wszystkimi odmianami czcionek? Trudno jest pisać to wszystko ręcznie
helloworld

Odpowiedzi:


289

Istnieją dwie możliwości:

Korzystanie z importu

To jest sugerowana opcja. Zapewnia to, że czcionki przechodzą przez potok kompilacji, uzyskują skróty podczas kompilacji, dzięki czemu buforowanie przeglądarki działa poprawnie, a w przypadku braku plików pojawiają się błędy kompilacji.

Jak opisano w „Dodawanie obrazów, czcionek i plików” , musisz mieć plik CSS zaimportowany z JS. Na przykład domyślnie src/index.jsimportuje src/index.css:

import './index.css';

Taki plik CSS przechodzi przez proces kompilacji i może odnosić się do czcionek i obrazów. Na przykład, jeśli umieścisz czcionkę src/fonts/MyFont.woff, możesz index.cssdołączyć to:

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

Zwróć uwagę, jak używamy ścieżki względnej zaczynającej się od ./. Jest to specjalna notacja, która pomaga potokowi kompilacji (opartemu na pakiecie Webpack) wykryć ten plik.

Zwykle to powinno wystarczyć.

Korzystanie z publicfolderu

Jeśli z jakiegoś powodu wolisz nie używać potoku kompilacji i zamiast tego zrobić to w „klasyczny sposób”, możesz użyć publicfolderu i umieścić tam swoje czcionki.

Wadą tego podejścia jest to, że pliki nie otrzymują skrótów podczas kompilacji do produkcji, więc będziesz musiał aktualizować ich nazwy za każdym razem, gdy je zmienisz, lub przeglądarki będą buforować stare wersje.

Jeśli chcesz to zrobić w ten sposób, umieść czcionki gdzieś w publicfolderze, na przykład w public/fonts/MyFont.woff. Jeśli zastosujesz się do tego podejścia, powinieneś również umieścić pliki CSS w publicfolderze i nie importować ich z JS, ponieważ mieszanie tych podejść będzie bardzo mylące. Jeśli więc nadal chcesz to zrobić, będziesz mieć plik, taki jak public/index.css. Musiałbyś ręcznie dodać <link>do tego arkusza stylów z public/index.html:

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

Wewnątrz tego użyłbyś zwykłej notacji CSS:

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

Zwróć uwagę, jak używam fonts/MyFont.woffścieżki. Dzieje się tak, ponieważ index.cssznajduje się w publicfolderze, więc będzie obsługiwany ze ścieżki publicznej (zwykle jest to katalog główny serwera, ale jeśli wdrożysz na GitHub Pages i ustawisz homepagepole na http://myuser.github.io/myproject, będzie obsługiwane z /myproject). Jednak fontsznajdują się one również w publicfolderze, więc będą obsługiwane ze fontswzględnie (albo http://mywebsite.com/fontsalbo http://myuser.github.io/myproject/fonts). Dlatego używamy ścieżki względnej.

Zwróć uwagę, że ponieważ w tym przykładzie unikamy potoku kompilacji, nie weryfikuje on, czy plik faktycznie istnieje. Dlatego nie polecam tego podejścia. Innym problemem jest to, że nasz index.cssplik nie zostaje zminimalizowany i nie otrzymuje skrótu. Więc to będzie wolniejsze dla użytkowników końcowych i ryzykujesz, że przeglądarki buforują stare wersje pliku.

 Który sposób użyć?

Wybierz pierwszą metodę („Korzystanie z importu”). Opisałem tylko drugą, ponieważ to właśnie próbowałaś zrobić (sądząc po komentarzu), ale ma wiele problemów i powinna być ostatecznością tylko wtedy, gdy pracujesz nad jakimś problemem.


5
przykład w dokumentach byłby przydatny, byłem też trochę zdezorientowany
Tom

2
Okazało się, że faktycznie muszę użyć adresu URL ./fonts/Myfont.woff, a nie ./Myfont.woff
th3morg

57
Jeśli ktoś dodaje ttfczcionkę, należy podać truetypezamiast ttfparametru format* .
milkersarac

3
@milkersarac, jesteś najlepszy!
João Vilaça

19
Śledzenie @milkersarac, jeśli używasz otf, musisz umieścić opentype.
Karl Taylor

46

Oto kilka sposobów na zrobienie tego:

1. Importowanie czcionki

Na przykład, aby używać Roboto, zainstaluj pakiet za pomocą

yarn add typeface-roboto

lub

npm install typeface-roboto --save

W index.js:

import "typeface-roboto";

Istnieją pakiety npm dla wielu czcionek open source i większości czcionek Google. Można zobaczyć wszystkie czcionki tutaj . Wszystkie pakiety pochodzą z tego projektu .

2. W przypadku czcionek udostępnianych przez inną firmę

Na przykład czcionki Google, możesz przejść do fonts.google.com, gdzie możesz znaleźć linki, które możesz umieścić w swoimpublic/index.html

zrzut ekranu fonts.google.com

To będzie jak

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

lub

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

3. Pobranie czcionki i dodanie jej do kodu źródłowego.

Pobierz czcionkę. Na przykład w przypadku czcionek Google możesz przejść do fonts.google.com . Kliknij przycisk pobierania, aby pobrać czcionkę.

Przenieś czcionkę do fontskatalogu w swoim srckatalogu

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

Teraz App.cssdodaj to

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

Aby uzyskać ttfformat, musisz wspomnieć format('truetype'). dla woff,format('woff')

Teraz możesz używać czcionki na zajęciach.

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

4. Korzystanie z pakietu web-font-loader

Zainstaluj pakiet za pomocą

yarn add webfontloader

lub

npm install webfontloader --save

W programie src/index.jsmożesz to zaimportować i określić potrzebne czcionki

import WebFont from 'webfontloader';

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

2
--zapisz jest domyślny w przypadku npm 5 (2017)
NattyC,

Dziękuję za komentarz @Natalie, cieszę się, że npm dokonał tej zmiany.
sudo bangbang,

@sudobangbang Dzięki, rozwiązanie nr 3 zadziałało dla mnie. Jednak - czy jest sposób, aby fontsfolder nie był umieszczany pod src, ale publiczamiast tego? Próbowałem, ale wydaje mi się, że to niedozwolone ...
Yossi Vainshtein

@YossiVainshtein, nie sądzę. Ponieważ używasz czcionek w App.css, należy go również skompilować z tym.
sudo bangbang

For ttf format, you have to mention format('truetype'). For woff, format('woff')zrobił to dla mnie! Dziękuję Ci!
Joseph Briggs

7
  1. Przejdź do Google Fonts https://fonts.google.com/
  2. Wybierz czcionkę, jak pokazano na poniższym obrazku:

wprowadź opis obrazu tutaj

  1. Skopiuj, a następnie wklej ten adres URL w nowej karcie, a otrzymasz kod css, aby dodać tę czcionkę. W tym przypadku, jeśli pójdziesz do

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

Otworzy się w ten sposób:

wprowadź opis obrazu tutaj

4, Skopiuj i wklej ten kod do swojego style.css i po prostu zacznij używać tej czcionki w ten sposób:

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

Wynik:

wprowadź opis obrazu tutaj


1
W wielu przypadkach (np. Sieci korporacyjne) dostęp do zewnętrznej sieci CDN jest blokowany przez zaporę ogniową i ta metoda, choć poprawna, może nie działać. W naszej organizacji mamy wiele sieci VLAN i oprócz działów IT i kilku innych wszystkie sieci VLAN blokują dostęp do zewnętrznej sieci CDN, co oznacza również, że sieć CDN treści Google jest również blokowana. Byłem tam, zrobiłem to.
AnBisw

2

Możesz skorzystać z modułu WebFont , który znacznie upraszcza proces.

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

0

Popełniłem takie błędy.

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

W ten sposób działa poprawnie

@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

Spędziłem cały ranek na rozwiązywaniu podobnego problemu po tym, jak trafiłem na to stosowne pytanie. Użyłem pierwszego rozwiązania Dana w powyższej odpowiedzi jako punktu wyjścia.

Problem

Mam środowisko deweloperskie (to jest na moim komputerze lokalnym), pomostowe i produkcyjne. Moje środowiska pomostowe i produkcyjne znajdują się na tym samym serwerze.

Aplikacja jest wdrażana do przemieszczania za pośrednictwem, acmeserver/~staging/note-taking-appa wersja produkcyjna znajduje się pod adresem acmeserver/note-taking-app(winić IT).

Wszystkie pliki multimedialne, takie jak czcionki, ładowały się idealnie na dev (tj react-scripts start.).

Jednak gdy tworzyłem i przesyłałem kompilacje przejściowe .cssi produkcyjne, podczas gdy .jspliki i ładowały się prawidłowo, czcionki nie były. Skompilowany.css plik ma poprawną ścieżkę, ale żądanie HTTP przeglądarki otrzymywało bardzo złą ścieżkę (pokazaną poniżej).

Skompilowany main.fc70b10f.chunk.cssplik:

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

Żądanie http przeglądarki jest pokazane poniżej. Zwróć uwagę, jak to się dodaje, /static/css/gdy plik czcionki po prostu znajduje się w/static/media/ a także kopiuje folder docelowy. Wykluczyłem, że winowajcą była konfiguracja serwera.

To też Refererjest częściowo wina.

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.jsonPlik miał homepagewłaściwość zestaw do ./note-taking-app. To powodowało problem.

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

Rozwiązanie

To było długie, ale rozwiązaniem jest:

  1. zmienić PUBLIC_URL zmienną env w zależności od środowiska
  2. usunąć homepagewłaściwość z package.jsonpliku

Poniżej znajduje się moja .env-cmdrcteczka. Używam .env-cmdrcponad zwykłego, .envponieważ utrzymuje wszystko razem w jednym pliku.

{
  "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 przez również react-router-domdziała dobrze - po prostu użyj PUBLIC_URLzmiennej env jako basenamewłaściwości.

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

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

export { createRouter };

Konfiguracja serwera jest ustawiona tak, aby kierować wszystkie żądania do ./index.htmlpliku.

Wreszcie, oto main.fc70b10f.chunk.cssjak wygląda skompilowany plik po wprowadzeniu omówionych zmian.

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

Materiały do ​​czytania

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.