Why is my local font not being applied with Emotion global styling? - reactjs

I am trying to use a locally hosted font in a React project that utilizes Emotion, and its Global component. This method works great for web fonts, like Google Fonts, but when I downloaded that same font and tried to apply it as a local .ttf file using #font-face, I couldn't achieve the same result.
Here's the important file, App.js:
import React from "react";
import { Global, css } from "#emotion/core";
import styled from "#emotion/styled";
const GlobalStyles = css`
#import url("https://fonts.googleapis.com/css?family=Dancing+Script&display=swap");
#font-face {
font-family: "Local Font";
src: url("fonts/DancingScript-Regular.ttf");
}
* {
text-align: center;
}
`;
const FromGoogle = styled.h1`
font-family: "Dancing Script";
`;
const FromLocal = styled.h1`
font-family: "Local Font";
`;
function App() {
return (
<div className="App">
<Global styles={GlobalStyles} />
<FromGoogle>This text's font family is from Google.</FromGoogle>
<FromLocal>
This text's font family should be the same, except it comes from a local
font file, and it's not working.
</FromLocal>
</div>
);
}
export default App;
For some reason, the text in FromGoogle uses the Google font fine, while the text from FromLocal doesn't. My first thought was that it's an issue with the path, but if it is, I couldn't tell.
Here's the full project on GitHub. I used Create React App, and removed all the irrelevant boilerplate.

In my Next.js app I am using emotion with these versions:
"#emotion/react": "^11.1.1",
"#emotion/styled": "^11.0.0",
My global styles are:
export const GlobalStyles = () => (
<Global
styles={css`
#font-face {
font-family: 'Faustina';
font-style: normal;
font-weight: 700;
src: local(''),
url('/fonts/Faustina/Faustina.woff') format('woff'),
url('/fonts/Faustina/Faustina.ttf') format('truetype');
}
* {
box-sizing: border-box;
font-family: Faustina;
}
html,
body {
width: 100%;
height: 100%;
min-height: 100%;
padding: 0;
margin: 0;
}
`}
/>
);
My fonts are in
project_root/public/fonts/Faustina
// explicitly
project_root/public/fonts/Faustina/Faustina-Bold.ttf
project_root/public/fonts/Faustina/Faustina-Bold.woff
In order to see font changes, I needed to restart dev server, e.g. yarn dev. Before restarting I had same issue where fonts weren't displayed (even downloaded in dev tools Network tab).

am using these versions in my gatsby project;
"#emotion/react": "^11.8.1",
"gatsby": "^4.8.0"
index.html file is not available so you can't add <style> html tag and embed #font-face inside it.
Host your downloaded fonts inside your src/myfonts directory then import any of your fonts using the static import statement.
import font1 from './myfonts/font1.ttf';
then call url(font1) css function with the font1
const globalStyle = css`
#font-face {
font-family: 'font1';
src: url(${font1}) format('truetype');
};
`;
it worked in my case;

In my case, the solution was as in this answer.
I needed to define the fonts in a css file that is imported into the index.html like so:
<link rel="stylesheet" type="text/css" href="/styles/fonts.css" />
I was then able to reference the font family names in my emotion theme and have them load correctly.

Related

custom font is loaded but not applying in react typescript

I've developing react typescript project and trying to load custom font.
But I can see font is loaded in Network tab but font is still not changed to what I want.
I tried many related post in StackOverflow but still the same.
The last I did is this link.
Here's my current code I added for font.
assets/fonts/globalfonts.ts
import { url } from 'inspector';
import {createGlobalStyle} from 'styled-components';
export const GlobalFonts = createGlobalStyle`
#font-face {
font-family: 'Trixie Plain';
font-style: normal;
font-weight: 400;
src: url("./assets/fonts/Trixie-Plain.otf") format('opentype')
}
`
src/components/TopBar/components/Nav.tsx
import React from 'react'
import { NavLink } from 'react-router-dom'
import styled from 'styled-components'
import { GlobalFonts } from '../../../assets/fonts/globalfonts'
const Nav: React.FC = () => {
return (
<StyledNav>
<GlobalFonts />
<StyledLink exact activeClassName="active" to="/">
Home
</StyledLink>
</StyledNav>
)
}
const StyledNav = styled.nav`
align-items: center;
display: flex;
font-family: 'Trixie Plain';
`
[
You need to define a declaration file d.ts as mentioned in the
https://dev.to/anteronunes/comment/171a3
Can you try altering the globals font face as below?
export const GlobalFonts = createGlobalStyle`
#font-face {
font-family: TrixiePlain;
// rest of declaration
}
`
Note above the font-family value without space/quotes. Thus, in styled components:
const StyledNav = styled.nav`
align-items: center;
display: flex;
font-family: TrixiePlain;
`
Did you tried by creating rules in the webpack?
module.exports = {
module: {
rules: [
{
test: /\.(woff2|woff|eot|ttf|otf)$/,
use: ["file-loader"],
},
],
},
}
Check if you installed the file-loader.
npm i -D file-loader

Encountering white-space at top of react-app

enter image description here
Image
encountering white space at top of the react-app
Check the image
There's weird whitespace occurring at the top of the react-app. My developed app not even a big react-app but there something occupying the space there and creating a white space there. I have deleted the old project and did this new one thinking it'll remove my error but the same result. I'm using a routing package to route through my app react-route-dom. I tried all the possible ways but couldn't find out the error or the line of code that is triggering the white-space at the top of the react-app. Please anyone help I have to submit my project!.
App.js
import React from 'react'
import './App.css';
function App() {
return (
<div className="App">
<h1>Hello</h1>
</div>
);
}export default App
App.css
.App {
text-align: center;
background: red;
height: 30%;
}
Index.js
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom'
const app = <BrowserRouter><App/></BrowserRouter>
ReactDOM.render(
<React.StrictMode>
{app}
</React.StrictMode>,
document.getElementById('root') );
reportWebVitals()
**index.css**
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
background: #333;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
Add this to your index.css :
*{
margin: 0;
padding: 0;
box-sizing: border-box; // not neccesary
}
This happens because chrome by default adds some padding to your page
user agent stylesheet is doing that. For instance Chrome styles h1 by default like so:
h1 {
display: block;
font-size: 2em;
margin-block-start: 0.67em;
margin-block-end: 0.67em;
margin-inline-start: 0px;
margin-inline-end: 0px;
font-weight: bold;
}
This will create those margins you're complaining about. All you need to do is explicitly style your h1 in your CSS file. Something like this: h1{margin: 0px}. Do the same for the body.
Also note that If <!DOCTYPE> is missing in your HTML content oftentimes the browser gives preference to the "user agent stylesheet" over your custom stylesheet.
In my case, the space provoked the css property place-items: center from the index.css file.

My font does not appear in Network (reactjs, styled components)

I am actually blocked by an issue with the font import in a React project (working with styled-components).
This is my Fonts file:
import { createGlobalStyle } from 'styled-components';
import NameOfYourFontWoff from './ClickerScript.woff';
import NameOfYourFontWoff2 from './ClickerScript.woff2';
export default createGlobalStyle`
#font-face {
font-family: 'Font Name';
src: local('Font Name'), local('FontName'),
url(${NameOfYourFontWoff2}) format('woff2'),
url(${NameOfYourFontWoff}) format('woff');
font-weight: 300;
font-style: normal;
}
`;
and this is my index.js where I import my font and styles :
import GlobalStyles from './styles/globalStyles';
import GlobalFonts from './fonts/Fonts';
ReactDom.render((
<React.Fragment>
<ThemeProvider theme={theme}>
<GlobalFonts />
<GlobalStyles />
<Provider store={store}>
<Main />
</Provider>
</ThemeProvider>
</React.Fragment>
), document.getElementById('tetris'));
With this, I can see the font is given to my div, but I have no change, and my font does not appear in the Network flow. Any idea ?
I don't know these fonts, but if they are any different, add them in two times
in this example i took it like one of them was italic
#font-face {
font-family: 'ClickerScript';
src: url(${NameOfYourFontWoff}) format('woff'),
font-weight: 300;
font-style: normal;
}
#font-face {
font-family: 'ClickerScript';
src: url(${NameOfYourFontWoff2}) format('woff2'),
font-weight: normal;
font-style: italic;
}
Let me know if it works and for clarification, you don't see any of these font loaded (even failed) in the request tab ?

How to insert a Local Font in my Project?

I used IconMoon to create custom icon fonts.
In the .html that is generated by it, it works perfectly. But when I try to use it in my project with React and Styled-Components, instead of being displayed the icon displays its content in HTML.
My fonts are in the path: src/assets/fonts/icons
Fonts are being downloaded by the browser and no errors are displayed:
Soon I am trying to create a component for my fonts, similar to FontAwesome and this happens:
MY COMPONENT:
import React from "react";
import styled from "styled-components";
const Tst = styled.i`
font-family: "spotify" !important;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
::before {
content: "\e900";
color: red;
}
`;
const SaveFavorite = () => {
return <Tst />;
};
export default SaveFavorite;
MY GLOBAL STYLES:
import { createGlobalStyle } from "styled-components";
const GlobalStyle = createGlobalStyle`
#font-face {
font-family: "spotify";
font-weight: normal;
font-style: normal;
src: url("../assets/fonts/spotify.eot?") format("embedded-opentype"),
url("../assets/fonts/spotify.ttf?") format("truetype"),
url("../assets/fonts/spotify.woff?") format("woff"),
url("../assets/fonts/spotify.svg?") format("svg");
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
outline: 0;
}
body {
font-family: 'CircularSpUIv3T', sans-serif;
color: white;
text-rendering: optimizeLegibility !important;
-webkit-font-smoothing: antialiased !important;
-moz-osx-font-smoothing: grayscale !important;
user-select: none;
}
img {
width: 100%;
max-width: 100%;
height: auto;
}
`;
export default GlobalStyle;
If you look at the css generated by Styled Components, you'll find that the font paths aren't resolved at all, they are exactly the way you typed them. The browser won't be able to find relative paths in the src directory without some help from Babel, and the way you have it now these paths would just be passed as-is.
You have two options, although I'm not sure if both will work.
Option 1: move your fonts to the public directory
Files in the public directory can be found by the browser just like any old HTML page. In your global style, you would then have to use a path that is relative to public/index.html.
Your file structure would be something like:
project
|-- public
|-- index.html
|-- fonts
|-- spotify.eot
|-- spotify.ttf
|-- spotify.woff
|-- spotify.svg
|-- src
|-- global.style.js
|-- (...)
And your global.style.js:
const GlobalStyle = createGlobalStyle`
#font-face {
font-family: "spotify";
src: url("fonts/spotify.eot?") format("embedded-opentype"),
url("fonts/spotify.ttf?") format("truetype"),
url("fonts/spotify.woff?") format("woff"),
url("fonts/spotify.svg?") format("svg");
}
Option 2: keep your fonts in src, but make Babel resolve the paths for you
To make Babel resolve the paths, we need to import the files in our global.style.js, and then use the resolved path instead of the static one:
import SpotifyEOT from '../assets/fonts/spotify.eot';
// etc
const GlobalStyle = createGlobalStyle`
#font-face {
font-family: "spotify";
src: url(${SpotifyEOT}?) format("embedded-opentype"),
// [etc]
}
I don't know what the question mark is actually for but I assume you can just place it after the resolved path like I did.

React.js styled-components importing images and using them as div background

I am using styled-components and am trying to set a background image like so
const HeaderImage= styled.div`
background-image: url('../../assets/image.png');
';
I've also tried without the quotes, like so
const HeaderImage= styled.div`
background-image: url(../../assets/image.png);
';
In both cases, I get the same result
http://localhost:3000/assets/image.png Failed to load resource: the server responded with a status of 404 (Not Found)
I am using Richard Kall's react starter
The file is definitely in the specified location.
Am I loading it incorrectly?
I should mention, I'm very new to this (React, and styled-components)
You should import images in the following manner (assuming that you have webpack configured for importing media assets).
import myImage from '../../assets/image.png';
/* ... */
const HeaderImage = styled.div`
background-image: url(${myImage});
`;
EDIT : this answer was edited after the question title was updated, due to misleading question title.
Using image as background-image CSS property :
import LogoSrc from './assets/logo.png';
/* ... */
const LogoDiv = styled.div`
background-image: url(${LogoSrc});
/* width and height should be set otherwise container will have either have them as 0 or grow depending on its contents */
`;
/* ... */
<LogoDiv />
Normal way of importing and using images :
import LogoSrc from './assets/logo.png';
/* ... */
const Logo = styled.img`
width: 30px;
height: 30px;
margin: 15px;
`;
/* ... inside the render or return of your component ... */
<Logo src={LogoSrc} />
EDIT 2: For reference there is another way to use styled-components, mostly used when using components that you already import (i.e. ant-design components of from other component library) or in case of components that don't work using styled._cp_name_ notation.
NOTE: components need to be compatible with styled-components.
Imagine you would export Logo on a file and import it on another component file :
const Logo = styled.img`
width: 30px;
height: 30px;
margin: 15px;
`;
export default Logo;
Then, on the file where you would import it, you could add more styles by :
import Logo from '../components/Logo';
const L = styled(Logo)`
border: 1px dashed black;
`;
/* ... then inside render or return ... */
<L />
import logo from 'public/images/logo.jpg';
/* ... */
const HeaderImg = styled.img.attrs({
src: `${logo}`
})`
width: 50px;
height: 30px;
`;
Importing files is one way of doing it as is suggested above, but it isn't the only way.
Here is an alternative solution, referencing file paths, the original way, using a custom express extension to target your dist folder. (Personally I prefer this approach because it keeps the css clean from the jsx and is self readable)
Disclaimer:
This solution is for webpack-dev-server for testing, but once the code is deployed, as long as you have generated your assets with your dist folder it will work by default.
Example:
component.tsx
const Button = styled.button`
background: url('/assets/file.svg');
`
webpack.config.js
const dist = path.resolve(__dirname, 'dist');
{
devServer: {
contentBase: dist,
historyApiFallback: true,
before: app => {
app.use('/assets', express.static(path.resolve(dist, '/assets')));
}
}
}
You can pass props to a component like this:
export const ImgTop = styled.div`
display: block;
background-image: ${props => `url(${props.background})`};
background-size: cover;
`
<ImgTop background={urlimagen}></ImgTop>
For those seeking a dynamic solution, you can also make something work with the <img> element. Some psuedo code that could make this possible:
// styles.tsx
import styled from "styled-components";
export const Relative = styled.div`
position: relative;
`;
//using the img function is no more supported
export const Image = styled.img`
z-index: 0;
position: absolute;
top: 0;
left: 0;
`;
export const TextInFrontOfImage = styled.p`
z-index: 1;
`;
// index.tsx
//..
<Relative>
<Image src={props.url}></Image>
<TextInFrontOfImage>Lorem Ipsum</TextInFrontOfImage>
</Relative>
Using some combination of position: relative/absolute and z-index you should be able to achieve similar results to the background-image property.

Resources