How to add Tailwind CSS scroll-smooth class to Next.js - next.js

I want to add scroll behaviour smooth to my Next.js app, and the Tailwind CSS documentation instructs us to add the utility class in <html/>.
<html class="scroll-smooth ">
<!-- ... -->
</html>
This file does not contain an html tag:
import Head from "next/head";
import "#material-tailwind/react/tailwind.css";
import "../styles/globals.css";
function MyApp({ Component, pageProps }) {
return (
<>
<Head>
<link
href="https://fonts.googleapis.com/icon?family=Material+Icons"
rel="stylesheet"
/>
</Head>
<Component {...pageProps} />
</>
);
}
export default MyApp;
How and where can I add the smooth-scroll utility class in my project?

The simplest solution, do it from your globals.css file...
#tailwind base;
#tailwind components;
#tailwind utilities;
#layer base {
html {
#apply scroll-smooth;
}
}

Use a custom _document.js and add it there - Here is an explanation of what it does -
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 class="scroll-smooth">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument

For those who will be using nextjs 13 . You can simply add the class (clasName) in the parent layout file like below :-
import '../styles/globals.css'
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html className='scroll-smooth'>
<head />
<body>{children}</body>
</html>
)
}

Related

Google font loads very weirdly after the deployment to the vercel

I have deployed the next js app to the server using vercel. I have referenced the two google fonts in _document.js. While I am running the app locally both font load without any problem.
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 href="https://fonts.googleapis.com/css2?family=Crete+Round&family=Work+Sans:wght#500;600&display=swap" rel="stylesheet" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
index.js
import Head from "next/head";
import Script from "next/script";
import Banner from "../components/Banner";
import { fetchAPI } from "../lib/api";
import Articles from "../components/Articles";
export default function Home({ articles })
{
return (
<>
<Head>
<title>Life Sciencify - Explore the mystery of life with Science! </title>
</Head>
<Articles articles={articles} />
</>
);
}
export async function getServerSideProps()
{
const [articlesRes] = await Promise.all([
fetchAPI("/posts", { populate: ["cover", "category"] })
]);
console.log(articlesRes)
return {
props: {
articles: articlesRes.data
}
};
}
app.js
import Script from "next/script";
import "bootstrap/dist/css/bootstrap.css";
import "../styles/globals.css";
import { useEffect } from "react";
import Header from "../components/Header";
import SearchBlock from "../components/SearchBlock";
import Footer from "../components/Footer";
function MyApp({ Component, pageProps })
{
useEffect(() =>
{
import("bootstrap/dist/js/bootstrap");
}, []);
return (
<>
<Component {...pageProps} />
</>
);
}
export default MyApp;
After the deployment it is showing the weird behavior.
Initially When I am in the home page the page doesn't load any font.
Now, when I click the link Post1 or Post 2, it will be redirected to the detail page.
at first font is not loaded in this page too.
Now, after the page refresh the font gets loaded.
Now, when I go to the back page in the browser, the home page will have the font loaded. But again when the page is refreshed the font will be gone.
What is the causing the weird behavior?
I am running the application in the next js version of "12.1.6".
Referenced:
google-font-display
font-optimization
In the _document.js i used two google fonts separately and it is working now.
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 href="https://fonts.googleapis.com/css2?family=Work+Sans:wght#500;600&display=swap" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css2?family=Crete+Round&display=swap" rel="stylesheet" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
and in index.js, change server side rendering to static props:
export async function getStaticProps()
{
const [articlesRes] = await Promise.all([
fetchAPI("/posts", { populate: ["cover", "category"] })
]);
console.log(articlesRes)
return {
props: {
articles: articlesRes.data
}
};
}
After this changes I deployed to vercel it worked fine, again after some time i changes to getServerSideProps, it was not working. So, the culprit was getServerSideProps with google font.

How to use TailwindCSS with Material UI?

I am using Next.js with Material UI. I am having troubles with using Tailwind with MUI. I've been following this guide but it still doesn't work. The file loads but the classes just don't apply. If someone could help, that would be wonderful!
My Tailwind Config
module.exports = {
important: "#__next",
content: ["./pages/**/*.{js,jsx}"],
theme: {
extend: {},
},
plugins: [],
}
My _app.js
//import '../styles/globals.css'
//function MyApp({ Component, pageProps }) {
// return <Component {...pageProps} />
//}
//export default MyApp
import '../styles/edit.css';
import * as React from 'react';
import PropTypes from 'prop-types';
import Head from 'next/head';
import { ThemeProvider, StyledEngineProvider } from '#mui/material/styles';
import CssBaseline from '#mui/material/CssBaseline';
import { CacheProvider } from '#emotion/react';
import theme from '../config/themeConfig';
import createEmotionCache from '../functions/createEmotionCache';
import Layout from "../components/Layout";
//import '../styles/tailwind.css';
// Client-side cache, shared for the whole session of the user in the browser.
const clientSideEmotionCache = createEmotionCache();
export default function MyApp(props) {
const { Component, emotionCache = clientSideEmotionCache, pageProps } = props;
return (
<Layout>
<CacheProvider value={emotionCache}>
<Head>
<meta name="viewport" content="initial-scale=1, width=device-width" />
</Head>
<ThemeProvider theme={theme}>
<StyledEngineProvider injectFirst>
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
<CssBaseline />
<Component {...pageProps} />
</StyledEngineProvider>
</ThemeProvider>
</CacheProvider>
</Layout>
);
}
MyApp.propTypes = {
Component: PropTypes.elementType.isRequired,
emotionCache: PropTypes.object,
pageProps: PropTypes.object.isRequired,
};
Thanks!
You didn't follow the guide ( https://mui.com/material-ui/guides/interoperability/#tailwind-css ) correctly.
In your tailwind.config.js file you need to set the corePlugins parameter to disable the preflight CSS. The preflight CSS is overriding some of the styles of MUI.

How to create dynamic route for top-level page in NEXT?

To support these URLs:
/account?tab=profile
/account?tab=pass
/account?tab=points
I know that I can change them to:
/account/profile
/account/pass
/account/points
And then create this route:
/pages/account/[tab].js
But this means that the accoun is a directory, not a file.
I want to have a account.js top-level file, and have a route for query strings on it.
I don't know how to do it. Something like /account?[tab] route. Is it possible?
import type { GetServerSideProps, NextPage } from 'next'
import Head from 'next/head'
import { ParsedUrlQuery } from 'querystring';
import styles from '../styles/Home.module.css'
const About: NextPage<{ query: ParsedUrlQuery }> = ({ query }) => {
console.log(query);
return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<h1>About</h1>
</main>
</div>
)
}
export const getServerSideProps: GetServerSideProps = async ({ query }) => {
return {
props: {
query
}
}
}
export default About

Ordering problem using css import alongside styled components in nextjs app

I am using NextJS and when I use direct css import ...css alongside a styled-component createGlobalStyle. My direct css imports are always included last in my html causing some overriding issues that I've setup in GlobalStyles.
How can I resolve this?
rendered html
<head>
<link href="/_next/static/chunks/main.js?ts=1609163560022">
<style></style> // global styled component
<style></style> // bootstrap imported after global styled component
</head>
_app.js
import { ThemeProvider } from "styled-components";
import 'bootstrap/dist/css/bootstrap.min.css' // this is always loaded last <head>
import GlobalStylesfrom 'styles/global'; // this is always loaded first in <head>
const theme = {
...
};
export default function App({ Component, pageProps }) {
return (
<ThemeProvider theme={theme}>
<GlobalStyles/>
<Component {...pageProps} />
</ThemeProvider>
)
}
_document.js
import Document, { Html, Head, Main, NextScript } from "next/document";
import { ServerStyleSheet } from "styled-components";
export default class MyDocument extends Document {
static getInitialProps({ renderPage }) {
const sheet = new ServerStyleSheet();
const page = renderPage(App => props =>
sheet.collectStyles(<App {...props} />)
);
const styleTags = sheet.getStyleElement();
return { ...page, styleTags };
}
render() {
return (
<Html>
<Head>{this.props.styleTags}</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}

using google fonts in nextjs with sass, css and semantic ui react

I have a next.config.js file that has the following configuration:
const withSass = require('#zeit/next-sass');
const withCss = require('#zeit/next-css');
module.exports = withSass(withCss({
webpack (config) {
config.module.rules.push({
test: /\.(png|svg|eot|otf|ttf|woff|woff2)$/,
use: {
loader: 'url-loader',
options: {
limit: 100000,
publicPath: './',
outputPath: 'static/',
name: '[name].[ext]'
}
}
})
return config
}
}));
This is great because it runs my semantic ui css files.
Now I have a problem. I can't seem to successfully import any google font url. I tried downloading the ttf file into my file path and tried to reference it with the #import scss function. However I get a GET http://localhost:3000/fonts/Cabin/Cabin-Regular.ttf net::ERR_ABORTED 404 (Not Found) error
Here is what I'm trying to do with google font:
#font-face {
font-family: 'Cabin';
src: url('/fonts/Cabin/Cabin-Regular.ttf') format('truetype');
}
$font-size: 100px;
.example {
font-size: $font-size;
font-family: 'Cabin', sans-serif;
}
I have also downloaded the relevant npm dependencies:
"#zeit/next-css": "^1.0.1",
"#zeit/next-sass": "^1.0.1",
"file-loader": "^2.0.0",
"next": "^7.0.2",
"node-sass": "^4.9.4",
"react": "^16.6.0",
"react-dom": "^16.6.0",
"semantic-ui-css": "^2.4.1",
"semantic-ui-react": "^0.83.0",
"url-loader": "^1.1.2"
I know in Next.js 9.3, you can copy the #import statement from Google Fonts:
#import url('https://fonts.googleapis.com/css2?family=Jost&display=swap');
and place this in some css file, lets say styles/fonts.css like so:
#import url('https://fonts.googleapis.com/css2?family=Jost&display=swap');
.jost {
font-family: 'Jost', sans-serif;
}
Then import that inside of your global _app.js file like so:
import `../styles/fonts.css`
Now you have global access to that class containing the Google Font in every next.js page
I think the other solution is to use fonts directly from Google. Just customize _app.js file and add a <link rel="stylesheet" /> in the <Head />
Example _app.js
import React from 'react';
import App, { Container } from 'next/app';
import Head from 'next/head';
export default class MyApp extends App {
static async getInitialProps({ Component, router, ctx }) {
let pageProps = {};
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
}
return { pageProps };
}
render() {
const { Component, pageProps } = this.props;
return (
<Container>
<Head>
<link
href="https://fonts.googleapis.com/css?family=Cabin"
rel="stylesheet"
key="google-font-cabin"
/>
</Head>
<Component {...pageProps} />
<style global jsx>{`
body {
font-family: 'Cabin', sans-serif;
}
`}</style>
</Container>
);
}
}
class NextApp extends App {
render() {
const { Component } = this.props
return (
<React.Fragment>
<Component {...pageProps} />
<style jsx="true" global>{`
#import url('https://fonts.googleapis.com/css?family=Roboto');
body {
margin: 0;
font-family: 'Roboto', sans-serif;
}
`}</style>
</React.Fragment>
</Provider>
</Container>
)
}
}
Including the font url from Google Fonts in styled-jsx worked for me.
As per the latest docs you can now add global css by updating the _app.js file and importing your css style. Follow the steps below
Create custom _app.js file in the pages directory by following the docs.
Add your styles.css file to the pages directory.
Include the styles as below
// _app.js
// Import styles
import './styles.css'
// Function to create custom app
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
// Export app
export default MyApp
and done. These styles styles.css will apply to all pages and components in your application. Due to the global nature of stylesheets, and to avoid conflicts, you may only import them inside _app.js.
I had to put the files into the static folder for it to work, must've been a specific setup for rendering images and fonts in nextjs
If you are using a functional custom app, then you can add google fonts or any cdn linked fonts to the head of the whole app as follows:
import Head from 'next/head';
// Custom app as a functional component
function MyApp({ Component, pageProps }) {
return (
<>
<Head>
<link
href="https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght#300;400;600;700&display=swap" rel="stylesheet"/>
</Head>
<Component {...pageProps}/>
</>
)
}
MyApp.getInitialProps = async ({ Component, ctx }) => {
let pageProps = {};
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
}
return { pageProps };
};
// Export app
export default MyApp
now you can use css to apply the font family to the body element to get the font applied throughout the webiste, as shown below.
body {
font-family: 'Source Sans Pro', sans-serif;
}
Hhis is now how I am currently loading external fonts nonblocking. In _document.js head:
<script dangerouslySetInnerHTML={{__html: '</script><link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" media="print" onload="this.media=\'all\'" /><script>' }} />
dangerouslySetInnerHTML and some script hacking to work around onload otherwise being removed from _document.js until this is resolved
source

Resources