Colin S
Colin S

Reputation: 133

Material UI fade scroll styling on ImageList

I have a horizontally scrolling ImageList using Material UI V5, and I would like to fade the edges so that the cutoff isn't as harsh. I have figured out how to fade the edges, but I would only like the edges to fade until the user has scrolled to the start or end of the list (so when the user is at the start of the list the right is faded, and at the end the left is faded, and on larger screens with no scroll there is no fade). What is the easiest way for me to achieve this within MUI ImageList? I can style the object conditionally but can't seem to get scroll position.

enter image description here

import * as React from 'react';
import Image from 'next/image';
import ImageList from '@mui/material/ImageList';
import ImageListItem from '@mui/material/ImageListItem';
import ImageListItemBar from '@mui/material/ImageListItemBar';
import { styled } from "@mui/system"
import { NoEncryption } from '@mui/icons-material';


export default function TitlebarBelowImageList() {

  return (
    <AdBarContainer>
    <ImageList sx={{ 
      width: "100%",
      gridAutoFlow: "column",
      gridTemplateColumns: "repeat(auto-fill,minmax(15em, 1fr)) !important",
      gridAutoColumns: "minmax(15em, 1fr)",
      overflowX:'scroll',
      maskImage: 'linear-gradient(to left, black calc(100% - 48px), transparent 100%)',
      maskImage: 'linear-gradient(to right, transparent 0%, black 48px, black calc(100% - 48px), transparent 100%)',
      }}
      gap= {10}
      variant= 'standard'
      rowHeight= "auto"
      >
      {itemData.map((item) => (
        <ImageListItem key={item.key}>
          <img
            src={`${item.img}?w=248&fit=crop&auto=format`}
            srcSet={`${item.img}?w=248&fit=crop&auto=format&dpr=2 2x`}
            alt={item.title}
            loading="lazy"
            style={{borderRadius: 10}}
          />
          <ImageListItemBar
            title={item.title}
            subtitle={<span>{item.subtitle}</span>}
            position="below"
          />
        </ImageListItem>
      ))}
    </ImageList>
    </AdBarContainer>
  );
}

const itemData = [
  {
    key: 1,
    img: '/img.jpg',
    title: 'title',
    subtitle: 'subtitle',
  },
  {
    key: 2,
    img: '/img.jpg',
    title: 'title',
    subtitle: 'subtitle',
  },
  {
    key: 3,
    img: '/img.jpg',
    title: 'title',
    subtitle: 'subtitle',
  },
  {
    key: 4,
    img: '/img.jpg',
    title: 'title',
    subtitle: 'subtitle',
  },
  {
    key: 5,
    img: '/img.jpg',
    title: 'title',
    subtitle: 'subtitle',
  },
];

Upvotes: 3

Views: 1186

Answers (1)

Akis
Akis

Reputation: 2252

Have a look at this working codesandbox which I think is what you are looking for.

Here is you code updated with the answer:

import React, { useEffect, useState } from "react";
import Image from "next/image";
import ImageList from "@mui/material/ImageList";
import ImageListItem from "@mui/material/ImageListItem";
import ImageListItemBar from "@mui/material/ImageListItemBar";
import { styled } from "@mui/system";
import { NoEncryption } from "@mui/icons-material";

const itemData = [
  {
    key: 1,
    img: "/img.jpg",
    title: "title",
    subtitle: "subtitle"
  },
  {
    key: 2,
    img: "/img.jpg",
    title: "title",
    subtitle: "subtitle"
  },
  {
    key: 3,
    img: "/img.jpg",
    title: "title",
    subtitle: "subtitle"
  },
  {
    key: 4,
    img: "/img.jpg",
    title: "title",
    subtitle: "subtitle"
  },
  {
    key: 5,
    img: "/img.jpg",
    title: "title",
    subtitle: "subtitle"
  }
];

export default function TitlebarBelowImageList() {
  const [horizontalScroll, setHorizontalScroll] = useState(0);

  useEffect(() => {
    const imageListEl = document.querySelector("#imageList");

    imageListEl?.addEventListener(
      "scroll",
      () => {
        console.log("position left is", imageListEl.scrollLeft);
        setHorizontalScroll(imageListEl?.scrollLeft);
      },
      { passive: true }
    );
  }, [horizontalScroll]);

  return (
    <AdBarContainer>
    <ImageList
      id="imageList"
      sx={{
        width: "100%",
        gridAutoFlow: "column",
        gridTemplateColumns: "repeat(auto-fill,minmax(15em, 1fr)) !important",
        gridAutoColumns: "minmax(15em, 1fr)",
        overflowX: "scroll",
        maskImage:
          horizontalScroll > 0
            ? [
                "linear-gradient(to left, black calc(100% - 48px), transparent 100%)",
                "linear-gradient(to right, transparent 0%, black 48px, black calc(100% - 48px), transparent 100%)"
              ]
            : [""]
      }}
      gap={10}
      variant="standard"
      rowHeight="auto"
    >
      {console.log("pos", horizontalScroll)}
      {itemData.map((item) => (
        <ImageListItem key={item.key}>
          <img
            src={`${item.img}?w=248&fit=crop&auto=format`}
            srcSet={`${item.img}?w=248&fit=crop&auto=format&dpr=2 2x`}
            alt={item.title}
            loading="lazy"
            style={{ borderRadius: 10 }}
          />
          <ImageListItemBar
            title={item.title}
            subtitle={<span>{item.subtitle}</span>}
            position="below"
          />
        </ImageListItem>
      ))}
    </ImageList>
    </AdBarContainer>
  );
}

Hope it helps.

Upvotes: 1

Related Questions