Tuz
Tuz

Reputation: 1980

Change scrollbar by hover. (React /css) - Material-UI

I have a scrollbar in multiple lists in the React app.

My global CSS within Material-UI is:


  MuiCssBaseline: {
    ...theme.overrides?.MuiCssBaseline,
    '@global': {
      '@font-face': fontFace,
      '*::-webkit-scrollbar': {
        width: '1.3%',
        maxWidth: '5px'
      },
      '*::-webkit-scrollbar-thumb': {
        backgroundColor: 'white'
      },
      '*:focus': {
        outline: 'none'
      }
    }
  }
};

I am trying to add global state for hover. When I hover on the box(!) not on the scroll itself, the scrollbar should be changed to gray.

Let's say I have box like:

    <Box className={listStyle.root}>
      <AutoSizer>
        {({ height, width }) => (
          <List dense ...... 
              return (
                <ListItem
 
                />
              );
            })}
          </List>
        )}
      </AutoSizer>

I tried something like the following and it's not working:

.listStyle:{
   '&:hover':{
       '*::-webkit-scrollbar-thumb': {
        backgroundColor: 'gray'
      },
   }
}

How can I achieve that?

Upvotes: 1

Views: 5473

Answers (1)

Ryan Cogswell
Ryan Cogswell

Reputation: 81066

The primary issue I see is that when nesting a rule (e.g. ::-webkit-scrollbar-thumb pseudo-element within :hover pseudo-class), you need to use & to refer to the parent rule instead of using *. So your listStyle should look like:

.listStyle:{
   '&:hover':{
      '&::-webkit-scrollbar-thumb': {
        backgroundColor: 'gray'
      },
   }
}

It would also be equivalent to do the following:

.listStyle:{
   '&:hover::-webkit-scrollbar-thumb': {
      backgroundColor: 'gray'
   }
}

If you want to apply this globally, you can do something like the following (I've changed the colors just to make the effects more easily distinguishable from browser defaults):

const theme = createMuiTheme({
  overrides: {
    MuiCssBaseline: {
      "@global": {
        "*::-webkit-scrollbar": {
          width: "1.3%",
          maxWidth: "5px"
        },
        "*::-webkit-scrollbar-thumb": {
          backgroundColor: "purple"
        },
        "*:hover": {
          "&::-webkit-scrollbar-thumb": {
            backgroundColor: "green"
          }
        }
        /* Equivalent alternative:
        "*:hover::-webkit-scrollbar-thumb": {
          backgroundColor: "green"
        }
         */
      }
    }
  }
});

Edit change scrollbar on hover globally

Here is a full example showing both the global approach and overriding that using a class name at a lower level:

import React from "react";
import CssBaseline from "@material-ui/core/CssBaseline";
import {
  ThemeProvider,
  createMuiTheme,
  makeStyles
} from "@material-ui/core/styles";

const theme = createMuiTheme({
  overrides: {
    MuiCssBaseline: {
      "@global": {
        "*::-webkit-scrollbar": {
          width: "1.3%",
          maxWidth: "5px"
        },
        "*::-webkit-scrollbar-thumb": {
          backgroundColor: "purple"
        },
        "*:hover": {
          "&::-webkit-scrollbar-thumb": {
            backgroundColor: "green"
          }
        }
        /* Equivalent alternative:
        "*:hover::-webkit-scrollbar-thumb": {
          backgroundColor: "green"
        }
         */
      }
    }
  }
});

const useStyles = makeStyles({
  divStyle: {
    "&:hover::-webkit-scrollbar-thumb": {
      backgroundColor: "red"
    }
  }
});
export default function App() {
  const classes = useStyles();
  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <div style={{ height: "200px", overflowY: "scroll" }}>
        <h1>
          Div with enough content to scroll. Globally controlled scrollbar hover
          color
        </h1>
        <h2>1</h2>
        <h2>2</h2>
        <h2>3</h2>
        <h2>4</h2>
        <h2>5</h2>
        <h2>6</h2>
      </div>
      <div
        style={{ height: "200px", overflowY: "scroll" }}
        className={classes.divStyle}
      >
        <h1>
          Div with enough content to scroll. Scrollbar hover color controlled by
          classes.divStyle.
        </h1>
        <h2>1</h2>
        <h2>2</h2>
        <h2>3</h2>
        <h2>4</h2>
        <h2>5</h2>
        <h2>6</h2>
      </div>
    </ThemeProvider>
  );
}

Edit change scrollbar on hover globally

Upvotes: 1

Related Questions