How to Override Scroll Bar CSS Styling Globally in Next.js

Introduction

This short post will go over how-to add a custom scrollbar using Material UI theme. Adding this flexibility to UIs will make your site more attractive to a variety of users and their visual preferences. However, sometimes we need to go beyond the default styling and customize our components to make them stand out a bit more. In this article, we’ll look at one of many techniques to override CSS in Next.js, letting you to take full control of your styles and create an impressive user interface.

For more detailed information on CSS in React.js please check out https://www.w3schools.com/react/react_css.asp.

Scrollbar Generators

http://webkit-scroll-gen.sourceforge.net

https://scriptgenerator.net/html-css-custom-scrollbar-code-generator

Prerequisites

MUI – Material UI v5.4.3 and Joy UI v5.0.0-alpha.42

npm install @mui/material @emotion/react @emotion/styled

Material UI Icons – Optional

npm install @mui/icons-material

Create a Example Page Containing a List

The component ScrollDemoComp.jsx renders a list inside a box with a fixed height and vertical overflow enabled.

import * as React from 'react';
import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import ListItemText from '@mui/material/ListItemText';
import ListSubheader from '@mui/material/ListSubheader';

export default function ScrollDemoComp(props) {
  return (
    <List
      sx={{
        mt: 10,
        width: '100%',
        maxWidth: 360,
        bgcolor: 'background.paper',
        position: 'relative',
        overflow: 'auto',
        maxHeight: 300,
        '& ul': { padding: 0 },
      }}
      subheader={<li />}
    >
      {[0, 1, 2, 3, 4].map((sectionId) => (
        <li key={`section-${sectionId}`}>
          <ul>
            <ListSubheader>{`I'm sticky ${sectionId}`}</ListSubheader>
            {[0, 1, 2].map((item) => (
              <ListItem key={`item-${sectionId}-${item}`}>
                <ListItemText primary={`Item ${item}`} />
              </ListItem>
            ))}
          </ul>
        </li>
      ))}
    </List>
  );
}

Setting up a Global Theme in _app.js

In _app.js create a theme and store the it with useMemo(). This was the app can cache the so that it does not need to be recalculated every time it renders.
A state variable can also be defined in this section to switch between Light and Dark themes.

Source code for _app.js

import { useMemo } from 'react' ;
import CssBaseline from '@mui/material/CssBaseline';
import { ThemeProvider, createTheme } from '@mui/material/styles';
import { blue, red, teal, cyan, grey, deepOrange } from '@mui/material/colors';
import Layout from 'components/Layout';
import './custom.css';

export default function App() {
  
  const theme = useMemo(
    () =>
      createTheme({
        palette: {
          primary: {
            
            main: '#4674c3',            
          },
          secondary: {            
            main: '#11cb5f',
          },
          warning: {            
            main: red[300],            
          },
          dark: {            
            main: grey[700],            
          },          
          default: {            
            main: grey[50]          
          },
          mode: 'light' ,
        },
        components: {
          MuiCssBaseline: {
            styleOverrides: {
              body: {
              "&::-webkit-scrollbar, & *::-webkit-scrollbar": {              
                  borderRadius: 10,
                  height: 50,                                    
                },      
                "&::-webkit-scrollbar-track, & *::-webkit-scrollbar-track": {              
                  webkitBoxShadow: 'inset 0 0 6px rgba(0,0,0,0.3)',
                  borderRadius: '20px',
                  backgroundColor: '#F5F5F5',
                  marginTop:  '5px',
                  marginBottom:  '5px'
                },
                "&::-webkit-scrollbar-thumb, & *::-webkit-scrollbar-thumb": {
                  borderRadius: 8,
                  backgroundColor: "orangered",
                  minHeight: 24,
                  border: "3px solid orangered",
                },
              },
            },
          },
        },
        // CUSTOM BREAK POINTS - Disabled for now

        // breakpoints: {
        //   values: {
        //     xs: 0,
        //     sm: 600,
        //     md: 900,
        //     lg: 1700,
        //     xl: 1720,
        //   },
        // },
    }), []);


  return (
    <ThemeProvider theme={theme}>
        <CssBaseline />
        <Component {...pageProps} /> 
    </ThemeProvider>
  );
}

CSS webkit-scrollbar

::-webkit-scrollbar


::-webkit-scrollbar-thumb

"&::-webkit-scrollbar, & *::-webkit-scrollbar": {              
    borderRadius: 10,
    height: 50,                                    
},      
  "&::-webkit-scrollbar-track, & *::-webkit-scrollbar-track": {              
    webkitBoxShadow: 'inset 0 0 6px rgba(0,0,0,0.3)',
    borderRadius: '20px',
    backgroundColor: '#F5F5F5',
    marginTop:  '5px',
    marginBottom:  '5px'
},
  "&::-webkit-scrollbar-thumb, & *::-webkit-scrollbar-thumb": {
    borderRadius: 8,
    backgroundColor: "orangered",
    minHeight: 24,
    border: "3px solid orangered",
},

In App.js
Example below.

::-webkit-scrollbar can be written as scrollbarColor.
-webkit-box-shadow can be written as webkitBoxShadow.
::-webkit-scrollbar-thumb can be written as “&::-webkit-scrollbar-thumb, & *::-webkit-scrollbar-thumb”.
::-webkit-scrollbar-thumb:focus can be written as “&::-webkit-scrollbar-thumb:focus, & *::-webkit-scrollbar-thumb:focus”.


  const theme = useMemo(
    () =>
      createTheme({
        ...
        components: {
          MuiCssBaseline: {
            styleOverrides: {
              body: {
                "&::-webkit-scrollbar, & *::-webkit-scrollbar": {              
                  borderRadius: 10,
                  height: 50,                                    
                },      
                "&::-webkit-scrollbar-track, & *::-webkit-scrollbar-track": {              
                  webkitBoxShadow: 'inset 0 0 6px rgba(0,0,0,0.3)',
                  borderRadius: '20px',
                  backgroundColor: '#F5F5F5',
                  marginTop:  '5px',
                  marginBottom:  '5px'
                },
                "&::-webkit-scrollbar-thumb, & *::-webkit-scrollbar-thumb": {
                  borderRadius: 8,
                  backgroundColor: "orangered",
                  minHeight: 24,
                  border: "3px solid orangered",
                },

              },
            },
          },
        },
    ...
    }), [colorMode]);

Scrollbar With Gradient Colors

Adding a gradient to the scrollbar.


Example below.

 const theme = useMemo(
    () =>
      createTheme({
        palette: {
          ...
        },
          components: {
          MuiCssBaseline: {
            styleOverrides: {
              body: {              
                "&::-webkit-scrollbar, & *::-webkit-scrollbar": {              
                  borderRadius: 10,
                  height: 50,                                   
                  webkitBoxShadow: 'inset 2px 2px 2px hsla(0,0%,100%,.25), inset -2px -2px 2px rgba(0,0,0,.25)',                  
                },      
                "&::-webkit-scrollbar-track, & *::-webkit-scrollbar-track": {              
                  webkitBoxShadow: 'inset 0 0 6px rgba(0,0,0,0.3)',
                  borderRadius: '20px',
                  backgroundColor: '#F5F5F5',
                  marginTop:  '5px',
                  marginBottom:  '5px'
                },
                "&::-webkit-scrollbar-thumb, & *::-webkit-scrollbar-thumb": {              
                  borderRadius: 10,
                  height: 50,
                  backgroundColor: "orangered",
                  webkitBoxShadow: 'inset 2px 2px 2px hsla(0,0%,100%,.25), inset -2px -2px 2px rgba(0,0,0,.25)',
                  background: 'linear-gradient(180deg,#ff8a00,#e52e71)',                                    
                },                                
              },
            },
          },
        },

    }), []);