Can't import Google Fonts with Styled Components and Next.js - css

I'm having the following issue when trying to load Google Fonts. I read that I'm supposed to write something like this in _document.js to import it inside a head tag
import React from 'react';
import Document, { Html, Head, Main, NextScript } from 'next/document';
class MyDocument extends Document {
render() {
return (
<Html lang="en">
<Head>
<link
rel="preload"
href="/fonts/noto-sans-v9-latin-regular.woff2"
as="font"
crossOrigin=""
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;
but this is the code I had to use to make Styled Components work with Next.js
import Document, { DocumentContext } from 'next/document';
import { ServerStyleSheet } from 'styled-components';
export default class MyDocument extends Document {
static async getInitialProps(ctx: DocumentContext) {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />),
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
),
};
} finally {
sheet.seal();
}
}
}
So my question is: how can I modify my _document.js file to use the styles of Google Fonts?
Also, if it's of any help, this is the GlobalStyle I'm using and that doesn't import the fonts
import { createGlobalStyle } from '#xstyled/styled-components';
const GlobalStyle = createGlobalStyle`
#import url('https://fonts.googleapis.com/css2?family=Lato&family=Rubik&display=swap');
* {
margin: 0;
padding: 0;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
html {
box-sizing: border-box;
font-size: 62.5%;
position: relative;
background: grey;
}
body {
font-family: 'Lato', sans-serif;
}
`;
const BasicLayout = ({ children }: { children: any }) => {
return (
<>
<GlobalStyle />
{children}
</>
);
};
export default BasicLayout;

Head to this page.
https://nextjs.org/docs/advanced-features/custom-app
Please read about custom _app.js and then do as following:
First, You need to create a custom _app.js for your app. (This must be in the root of your pages directory)
Then you need to create _app.css in the same directory
Then import the css file into your _app.js
import "./_app.css";
Then in your _app.css file, import your google font like the following:
#import url("https://fonts.googleapis.com/css?family=PT+Sans+Narrow:400,700&display=swap");
in the css file and in the body tag add the following line:
body {
font-family: "PT Sans Narrow", sans-serif;
etc..
}

I came across the same issue, but wasn't a fun of Hooman's answer as that requires the need of having a .css file only to contain the google font import.
Instead, here's the proper way to load your fonts while using styled-components:
import Document, {
Html,
Head,
Main,
NextScript,
DocumentContext,
DocumentInitialProps,
} from "next/document";
import { ServerStyleSheet } from "styled-components";
class MyDocument extends Document {
// Load styles before rendering
static async getInitialProps(ctx: DocumentContext): Promise<DocumentInitialProps> {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />),
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
),
};
} finally {
sheet.seal();
}
}
render() {
return (
<Html lang="en">
<Head>
{/* Google Fonts */}
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
<link
href="https://fonts.googleapis.com/css2?family=Libre+Franklin:wght#400;500&display=swap"
rel="stylesheet"
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;
Make sure your render method is not defined as static.

Related

MDX styling (next-mdx-remote) fails after I install Tailwind css in a Next.js app

I'm using next-mdx-remote to make use of MDX in my Next.js project.
I've been following JetBrains WebStorm guide to build this, here they've used bootstrap as their CSS but my choice of CSS framework was tailwind css.
The thing is when I install tailwind css or any other CSS based on tailwind css like flowbite, the MDX page loses it's styling.
Expected
What I Get after adding tailwind
tailwind.config.js
module.exports = {
content: [
"./pages/**/*.{js,ts,jsx,tsx}",
"./components/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
};
_app.tsx
import "../styles/globals.css";
import type { AppProps } from "next/app";
import Head from "next/head";
import Script from "next/script";
import Nav from "../components/Nav";
function MyApp({ Component, pageProps }: AppProps) {
return (
<>
<Head>
{/* <link
rel="stylesheet"
href="https://unpkg.com/#themesberg/flowbite#1.2.0/dist/flowbite.min.css"
/> */}
</Head>
<Script src="https://unpkg.com/#themesberg/flowbite#1.2.0/dist/flowbite.bundle.js" />
<Nav />
<Component {...pageProps} />
</>
);
}
export default MyApp;
globals.css
#tailwind base;
#tailwind components;
#tailwind utilities;
html,
body {
padding: 0;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
}
a {
color: inherit;
text-decoration: none;
}
* {
box-sizing: border-box;
}
[blogId].tsx
// import fs from "fs";
import matter from "gray-matter";
import path from "path";
import { serialize } from "next-mdx-remote/serialize";
import { MDXRemote } from "next-mdx-remote";
import { connectToDatabase } from "../../utils/mongodb";
import { ObjectId } from "mongodb";
const BlogPg = ({ frontMatter: { title }, MDXdata }) => {
return (
<div className="px-5 md:px-80 py-10">
<p className="text-5xl mb-4">{title}</p>
<MDXRemote {...MDXdata} />
</div>
);
};
export const getStaticPaths = async () => {
let { db } = await connectToDatabase();
const posts = await db.collection("blogs").find({}).toArray();
const paths = posts.map((post) => ({
params: {
blogId: post._id.toString(),
},
}));
return {
paths,
fallback: false,
};
};
export const getStaticProps = async ({ params: { blogId } }) => {
// const fileContent = fs.readFileSync(
// path.join("posts", blogId) + ".mdx",
// "utf-8"
// );
let { db } = await connectToDatabase();
const post = await db
.collection("blogs")
.find({ _id: new ObjectId(blogId) })
.toArray();
const { data: frontMatter, content } = matter(post[0].text);
const MDXdata = await serialize(content);
return {
props: {
frontMatter,
blogId,
MDXdata,
},
};
};
export default BlogPg;
You may change content to purge and add require('#tailwindcss/typography') to plugins in tailwind.config.js.
And then to see typography changes you should cover your <MDXRemote .../> with a prose named div.
tailwind.config.js
module.exports = {
purge: [
"./pages/**/*.{js,ts,jsx,tsx}",
"./components/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [require('#tailwindcss/typography')],
};
[blogId].tsx
...
<div className="prose">
<MDXRemote {...MDXdata} />
</div>
</div>
);
};
...

Use Local Font in Next.js

I'm struggling to get a local font to work on my Next.js website and can't seem to find much on it. I used #font-face in my globals.css style-sheet. (I referenced https://kirazhang.com/posts/nextjs-custom-fonts).
#font-face {
font-family: "Adobe Caslon Pro";
src: url("/static/fonts/ACaslonPro-Regular.otf") format("opentype");
font-style: medium;
font-display: swap;
}
then in _app.js
import "../styles/globals.css";
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />;
}
export default MyApp;
I also added a _document.js file to my pages folder
import Document, { Html, Head, Main, NextScript } from "next/document";
class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx);
return { ...initialProps };
}
render() {
return (
<Html>
<Head />
<link
rel="preload"
href="/static/fonts/ACaslonPro-Regular.otf"
as="font"
crossOrigin=""
/>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;
When everything is said and done it gives me Times in New Roman when I inspect the webpage.
I think the installation of your font is good, but you have to call a class/className or style with this font-family inside your component.
Exemple:
<div style={{fontFamily: "Adobe Caslon Pro"}} >
Exemple
</div>

katex math is not rendering perfectly in react

React code
import React from "react";
import katex from "katex/dist/katex.mjs";
export default function App() {
return (
<div
dangerouslySetInnerHTML={{
__html: katex.renderToString("\\sum_{i=0}^{n-1}A[i]"),
}}
/>
);
}
/public/index.html
Included style
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex#0.13.18/dist/katex.min.css" integrity="sha384-zTROYFVGOfTw7JV7KUu8udsvW2fx4lWOsCEDqhBreBwlHI4ioVRtmIvEThzJHGET" crossorigin="anonymous">
Output
Expected output
Can anyone tell me that what mistake is here?
Answer to my question
const html = katex.renderToString(str, {
throwOnError: false,
displayMode: true // make it true
})
.katex-display,.katex-display > .katex, .katex-display > .katex > .katex-html {
display: inline !important;
// make it inline, so it can render with your text even after `displayMode:true`
}
.katex-display{
text-align:left !important;
}
.katex-display>.katex{
text-align:left !important;
}

Next JS Themeprovider not getting custom styles

I'm new to Next JS and can't figure out why my background color is not being received and used by my ThemeProvider.
I feel I've copied the tutorials correctly so I must be close right?
My error is TypeError: Cannot read property 'background' of undefined
globals.js
import { createGlobalStyle } from 'styled-components';
export const GlobalStyles = createGlobalStyle`
*,
*::after,
*::before {
box-sizing: border-box;
}
body {
background: {({ theme }) => props.theme.background};
}
_app.js
import { GlobalStyles } from '../styles/globals';
//Theming
import { ThemeProvider } from "theme-ui";
import { lightTheme } from '../styles/themes/theme';
function App({ Component, pageProps }) {
return (
<Provider session={pageProps.session}>
<ThemeProvider theme={lightTheme}>
<GlobalStyles />
<Component {...pageProps} />
</ThemeProvider>
</Provider>
)
}
export default App
theme.js
export const lightTheme = {
background: 'red'
}
I was stupidly using import { ThemeProvider } from 'theme-ui' instead of import { ThemeProvider } from 'styled-components'

Using Next.js how to add a class to body or _next div during SSR?

I have a use case where I have to add a class to a root element may it be body or _next during SSR. The class needs to be added conditionally/dynamically based on getInitialProps responses.
I want to know if such is possible in the current state of Next.js.
import React from "react";
import NextDocument, { Html, Head, Main, NextScript } from "next/document";
class Document extends NextDocument {
static async getInitialProps(ctx) {
const initialProps = await NextDocument.getInitialProps(ctx);
// Determine if class name should be added
return {
...initialProps,
shouldShow: true,
};
}
render() {
return (
<Html>
<Head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
{`#__next {
height: ${this.props.shouldShow ? "100%" : "0"}
}`}
</style>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default Document;

Resources