I'm sure this is going to be a very straight forward answer, but I can't for the life of me work out how to get my Gatsby/React site to start at the top of a new page without a scroll transition effect when I click on an internal link.
Example:
On my home page I scroll to the bottom, then click on a link to take me to an 'About Me' page. The About Me Page loads with the browser scroll position still at the bottom of the page and then the window scrolls to the top of the page. This only takes a few milliseconds but when I click on a link I want to start at the top of the page without any transition.
The links are all standard Gatsby Links:
<Link className="" to="/aboutme/">
About Me
</Link>
Thanks!
EDIT
Adding in my layout wrapper, with useScrollRestoration hooks added:
import React from 'react'
import PropTypes from 'prop-types'
import useScrollRestoration from 'gatsby'
import NavBar from './NavBar/NavBar'
import Footer from './Footer/Footer'
import './layout.scss'
const Layout = ({ children }) => {
const aboutMeScrollRestoration = useScrollRestoration(`page-component-main`)
return (
<>
<NavBar />
<main className="bumpdown" {...aboutMeScrollRestoration}>
{children}
</main>
<Footer />
</>
)
}
Layout.propTypes = {
children: PropTypes.node.isRequired,
}
export default Layout
I managed to work this out in the end after a lot of Googling. It appears not to be a scrollRestoration issue but a Bootstrap issue. In bootstrap/scss/_reboot.scss there's the following code:
:root {
font-size: $font-size-root;
#if $enable-smooth-scroll {
#media (prefers-reduced-motion: no-preference) {
scroll-behavior: smooth;
}
}
}
This can be turned off either using $enable-reduced-motion: true; or $enable-smooth-scroll: false; in bootstrap overrides which stops the scrolling behaviour when a new page opens.
I'm using the enable-smooth-scrolling:false option as the other option may have further knock on effects.
I created a custom.scss file and imported it into the gatsby-browser.js file. The contents of the scss file is overriding the default value of the scroll-behaviour in bootstrap:
$enable-smooth-scroll: false;
:root {
scroll-behavior: auto !important;
}
#import "node_modules/bootstrap/scss/bootstrap";
This issue is known as Scroll Restoration. #reach/router (from where Gatsby extends its routing) handles it automatically. However, in some cases, it fails, especially when rendering containers that have their own scroll values. To bypass this "issue", Gatsby exposes a useScrollRestoration hook to restore the scroll position. For example:
import { useScrollRestoration } from "gatsby"
import countryList from "../utils/country-list"
export default function PageComponent() {
const ulScrollRestoration = useScrollRestoration(`page-component-ul-list`)
return (
<ul style={{ height: 200, overflow: `auto` }} {...ulScrollRestoration}>
{countryList.map(country => (
<li>{country}</li>
))}
</ul>
)
}
So, in your destination component (/aboutme/ page), use the useScrollRestoration hook in your outer wrapper to restore the scroll position.
I created a React application with npx create-react-app.
Then following these instructions
https://fontawesome.com/how-to-use/on-the-web/using-with/react
I installed the Font Awesome dependences:
npm i #fortawesome/fontawesome-svg-core
npm i #fortawesome/free-solid-svg-icons
npm i #fortawesome/react-fontawesome
Then I changed the App.js to this:
import logo from './logo.svg';
import './App.css';
import { FaSpinner } from 'react-icons/fa';
function App() {
return (
<div className="App">
<FaSpinner icon="spinner" spin /> This is a test.
</div>
);
}
export default App;
But it only displays a spinner icon that is not spinning:
How do I get the spinner to spin?
NOTE:
Outside of React, Font Awesome works fine without doing any extra work to animate the icons, e.g. this simple HTML code shows an animated icon:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet"
type="text/css"
href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" />
<title>testspin</title>
</head>
<body>
<i class="fa fa-spinner fa-spin"
aria-hidden="true"></i>
This is a test
</body>
</html>
What do I need to do in order to get the React version to work this easily?
By default, the spinner will not spin. But a simple way to trigger it to spin just like the logo of React after creating a new react app.
Add a className of spin to the icon and add a little css to trigger it spinning such like that below:
App.js
import react from 'react';
import './App.css';
import { FaSpinner } from 'react-icons/fa';
function App() {
return (
<div className="App">
<FaSpinner icon="spinner" className="spinner" /> This is a test.
</div>
);
}
export default App;
App.css
.spinner {
animation: spin infinite 5s linear;
/*You can increase or decrease the timer (5s) to
increase or decrease the speed of the spinner*/
}
#keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
Actually you just need to add the class fa-spin, no need to add any custom css, this is already included with React-Fontawesome for the class fa-spin. Here is an example from a project of mine:
import React, { useState } from 'react'
import { faCog, faFilePdf } from '#fortawesome/free-solid-svg-icons'
import { Button } from 'react-bootstrap'
const MyComponent = () => {
const [pdfCreatingState,setPdfCreatingState] = useState(false);
const handleClick = ev => {
setPdfCreatingState(true);
setTimeout(() => generatePDFDocument(docData,docName));
}
const generatePDFDocument = async (docData,docName) => {
...
}
return(
<Button className="mr-4" onClick={handleClick}>
<FontAwesomeIcon icon={pdfCreatingState ? faCog : faFilePdf} title={"Generate PDF report"} className={pdfCreatingState ? "fa-spin" : ""} />
</Button>
);
}
I had the same situation with Nextjs and noticed that the proper <style> tag for animation was not being generated. So I solved the problem by directly importing it. In my case, Adding import "#fortawesome/fontawesome-svg-core/styles.css" fixes the issue, and FontAwesome works as intended.
In my project I'm using react-icons/fa and the answer provided by #Qudusayo worked very well for smooth spinners. If anyone is trying to create a 'pulsed' or 'step' spinner, here's how you can do that:
CSS:
.icon_pulse {
animation: circle 1.2s steps(8) infinite;
}
#keyframes circle {
from {
transform: rotate(90deg);
}
to {
transform: rotate(450deg);
}
}
JSX:
<FaSpinner className="icon_pulse" />
i am two page in reactjs
pageOne.js:
import React from "react";
import { Link } from "react-router-dom";
import "./pageOne.css";
const PageOne = () => {
return (
<div>
one
<br />
<Link to="/pageTwo">Two Page</Link>
</div>
);
};
export default PageOne;
pageTwo.js:
import React from "react";
import { Link } from "react-router-dom";
import "./pageTwo.css";
const PageTwo = () => {
return (
<div>
two
<br />
<Link to="/">One Page</Link>
</div>
);
};
export default PageTwo;
i am define two css files for change background color when page loaded.
pageOne.css
body {
background-color: whitesmoke !important;
}
pageTwo.css
body {
background-color: crimson !important;
}
it's problem.in pageOne background color is crimson and in pageTwo background color is crimson.
sample
As I said earlier, there is only one body tag in the DOM tree by default. So when you try to style it whatever comes last will override the previous ones and in your case, the page two style will override the page one style.
To solve this, you got several options, but I will go with the easiest one. You can make a container for each of your pages and then assign a colour to that container to make the whole page background as you desired (You can simply make a layout component then wrap each of the components within it and with similar approach make it reusable). So, for example, you can create your first page like this:
<div className="crimson">
two
<br />
<Link to="/">one Page</Link>
</div>
and style it like this:
.crimson {
background-color: crimson;
min-height: 100vh; /* minimum height of page would be equal to available view-port height */
}
This goes the same for your other page. But you need to consider you have to remove the default margins from the body itself to prevent any disorder.
Working Demo:
I would solve this with Layout component:
const Layout = ({ backgroundColor = '#fff', children }) => (
<div style={{ backgroundColor }} className="layout">
{children}
</div>
)
then remove your css(and try not to use important in your css)
<Layout backgroundColor="#fff"><PageOne /></Layout>
and
<Layout backgroundColor="#f00"><PageTwo /></Layout>
I have recently upgraded to Next.js 8.0.3 from 6.1.1 and I am now encountering a very intense flash of un-styled content (FOUC) for my header content which is using styled-jsx. It loaded just fine before updating Next.js.
The header code that is flashing is a custom built npm module that uses styled-jsx (but not next) and is being imported and placed into a layout page that is rendered with every next page.
This was the implementation in the _document.js file before updating next and it was working:
import Document, { Head, Main, NextScript } from 'next/document'
import { ServerStyleSheet, injectGlobal } from 'styled-components'
import styledNormalize from 'styled-normalize'
import flush from 'styled-jsx/server'
injectGlobal`
${styledNormalize}
`
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()
const styles = flush()
return { ...page, styleTags, styles }
}
render() {
return (
<html>
<Head>
{this.props.styleTags}
</Head>
<body>
<Main />
<NextScript />
</body>
</html>
)
}
}
Based on the docs I have also tried this (where I wait for the initial props):
import Document, { Head, Main, NextScript } from 'next/document'
import { ServerStyleSheet, injectGlobal } from 'styled-components'
import styledNormalize from 'styled-normalize'
import flush from 'styled-jsx/server'
injectGlobal`
${styledNormalize}
`
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet()
const page = ctx.renderPage(App => props =>
sheet.collectStyles(<App {...props} />)
)
const initialProps = await Document.getInitialProps(ctx)
const styleTags = sheet.getStyleElement()
const styles = flush()
return { ...initialProps, ...page, styles, styleTags }
}
render() {
return (
<html>
<Head>
{this.props.styleTags}
</Head>
<body>
<Main />
<NextScript />
</body>
</html>
)
}
}
The flash might be a result of where I am implementing the module but not sure.
It seems like the code coming in from the module is not being properly bundled with the rest of the pages and thus giving the page flash. Any thoughts or feedback would be appreciated.
I ended up fixing the issue by refactoring the custom npm module to not use styled-jsx but instead use styled-components. Not really a fix but more of a work around
I'm using React.js and want to change the background color of the entire page. I can't figure out how to do this. Please help, thank you.
Edit (Sep 2 '18): I have a project on GitHub that I'm linking here. I don't have this project online right now, but in the /client folder is the client server. Check it out. This is how I answered the question.
The simplest solution is a bit hacky, but you can use raw javascript to modify the body style:
document.body.style = 'background: red;';
// Or with CSS
document.body.classList.add('background-red');
A cleaner solution could be to use a head manager like react-helmet or next.js Head component.
import React from 'react';
import {Helmet} from 'react-helmet';
class Application extends React.Component {
render () {
return (
<div className="application">
<Helmet>
<style>{'body { background-color: red; }'}</style>
</Helmet>
...
</div>
);
}
};
Some css-in-js also offers tools to manage global level styles; like styled-components injectGlobal.
In the end, there's a lot of tools providing cleaner ways to handle this. But if you don't want to rely on third party, the raw JS option might be good enough if you don't make it too interactive.
The simplest solution without doing anything fancy is to:
1) Open public/index.html
2) Add an inline style to your body like this:
<body style="background-color: red">
try this to your code
componentDidMount() {
document.body.style.backgroundColor = "red"
}
React Helmet (https://github.com/nfl/react-helmet)
I really found this library very helpfull. Really clean solution i would say.
Sample Usage:
import Helmet from 'react-helmet';
<Helmet bodyAttributes={{style: 'background-color : #fff'}}/>
The above solutions tell about adding the external library to give the required functionality but instead what you can do is just go to your Index.css file and inside the already written 'body' tag put "background-color: 'color'" and its done
The basic idea is to use the browser API in raw JavaScript without installing any packages. I don't recommend to use Helmet because it is unsafe to the life cycle of a class component.
// Update the document body background using the browser API
// in render() function for class component or directly in functional component
document.body.style.background = 'red';
Other application:
If you are constantly changing the body's background color, and you want to have the code to run on every render, following is an example. Be careful where you call the browser API.
For a class component, update it in componentDidUpdate().
import React from 'react';
class Example extends React.Component {
// ...
componentDidUpdate() {
// change background color with a random color
const color = Math.floor(Math.random()*16777215).toString(16);
document.body.style.background = color;
}
// ...
}
For a functional component, using Effect Hook useEffect(). You can look more into React Hook here.
import { useEffect } from 'react';
function Example() {
// ...
// Similar to componentDidMount and componentDidUpdate in class component:
useEffect(() => {
// change background color with a random color
const color = Math.floor(Math.random()*16777215).toString(16);
document.body.style.background = color;
});
// ...
}
If you want to change background color before the page loads you can do something like this.
import React, { useLayoutEffect } from 'react'
useLayoutEffect(() => {
document.body.style.backgroundColor = "red"
});
For further reference on useLayoutEffect check here
I just fiddled around with this for a bit. Simple solution for me, not entirely intuitive, all in public/index.html:
<html style="background-color: red">
that gets the bottom of the page, and a second entry:
<body style="background-color: red">
that gets you the top of the page ie. your react code.
Two entries for one problem but it's all in one file, needs no new libs and seems to work.
Please Don't need to install any packages is very easy and simple !
add
document.body.style = 'background: red;';
to your JS code or via CSS like below:
const Changebackground = () => {
const stylesObj = {
background: "green"
};
return ( <
div id = "hello-world"
style = {
stylesObj
}
className = "container" >
<
/div>
)
}
export default Changebackground;
//ReactDOM.render( < Changebackground / > , document.getElementById('App'));
.container {
position: fixed;
width: 100%;
height: 100%;
z-index: -10;
text-align: center;
transition: all 500ms ease;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.5.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.5.1/umd/react-dom.production.min.js"></script>
please check this one to see how its easy !
https://codepen.io/farbod-aprin/pen/dadJyb
After some time scouring the internet, I found this solution on a now deprecated github repo:
document.body.style.backgroundColor = "INSERT_COLOR";
You can post it outside of your function (That's how I used it)
It worked for me in my project: https://github.com/antdke/styled-input-bar/blob/master/src/App.tsx
I needed it to color the background for the entire app.
Where I found the code snippet (At top of the README.md): https://github.com/happylinks/react-body-backgroundcolor
Hope it helps you all out like it helped me :)
You should have a root component (e.g., a div) that is affected by the color you want as the background. That's the react-way to think about it.
<div className ="bg-primary"> // this should cover everything in the background
<div className="container mx-auto bg-secondary"> // this could be a centered container that has a different color.
<MyReactComponent />
</div>
</div>
The style property is not writable in Typescript but setAttribute works okay. Just pop it in your App component. It may not be a good idea to have a random bit of styling outside of React's many other styling mechanisms, it might make it hard to find, but if it's what you need it's what you need. It's what I needed today anyway!
document.body.setAttribute('style', 'background: red;')
You can use a CSS module in React. Below is the Javascript code for a file named Home.js
import styles from './Home.module.css';
const Home = ()=>{
return(
<div className = {styles}>
</div>
);
}
export default Home;
And in a css module named Home.module.css (format is [name].module.css), put the following and your page will have a background colour of blue
body{
background-color: blue;
}
I faced this issue too and this is my solution.
body{
margin:0;
background-color:blue;
}
This was simplest solution for me:
// in your css file
.background-white {
background-color: white !important;
}
// in your react component
componentDidMount() {
document.body.classList.add("background-white");
}
componentWillUnmount() {
document.body.classList.remove("background-white");
}
Using componentWillMount did not work reliably. Using document.body.style did not work reliably either.
If you are using React with Bootstrap, just include a background-color Bootstrap class to the <body> tag, in the index.html file, like this:
<body class="bg-light">
You can choose other colors from https://getbootstrap.com/docs/4.3/utilities/colors/#background-color
In your react src folder you should have a custom.css file.
Add 'body {background-color: ; }' in that custom.css file.
By default, assuming you've used npx Create-React-app MyAppName your React app will have an index.css.
This contains css which controls the default grey background. Just edit this to what you require.
body {
margin: 0;
background-color: #3f3f3f;
}
create index.css file like this
body {
margin: 0;
background-color: rgba(0, 0, 0, 0.07);
}
Then import it in your index.ts file
import "./index.css";
Also keep in mind the background color property might get overwritten if you import other css files below
So your index.ts file look like this
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import "bootstrap/dist/css/bootstrap.css";
import "./index.css";
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);
This works for me as long as my body's data has content in it
body { background-color : rgba(235,232,232,0.767); }
Similarly, you can alter the root tag as well.
#root{ background-color: rgba(235, 232, 232, 0.767); }
Make a wrapper componenet with an id like "wrapper" and then create a style with the color state:
getInitialState: function () {
return { color: "white" }; // Set your color for initial state.
},
changeColor: function () {
this.setState({ color: "black" }); // Set your changed color.
},
render: function () {
var style = { backgroundColor: this.state.color };
// The wrapper (root) component
return (
<div id="fullscreen" style={style}>
<a onClick={this.changeColor}>change</a>
</div>
);
}
The result should be something like:
<body>
<div id="fullscreen" style="background-color: YOUR CUSTOM COLOR">
<a onclick="THE REACT FUNCTION"></a>
</div>
</body>
It's been a while since I asked this question. What I've started doing since then is using Facebook's create-react-app setup, and editing CSS files directly.