Styling the Material UI ImageList with a fade scroll effect

I am currently working on a horizontal scrolling ImageList using Material UI V5, and I'm looking to create a smoother transition at the edges of the list. I have managed to fade the edges, but my goal is to only fade them when the user has reached the beginning or end of the list. Essentially, I want the right edge to fade when the user is at the start and the left edge to fade when at the end. On larger screens with no scroll, there should be no fade effect. How can I accomplish this within MUI ImageList? While I can conditionally style the object, I'm struggling to determine the scroll position.

https://i.sstatic.net/L8BwM.jpg

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',
  },
];

Answer №1

Take a peek at this functional codesandbox that seems to align with what you're searching for.

Below is your code updated with the solution:

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>
  );
}

I hope this proves useful.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the reason behind the shifting behavior of e.currentTarget when using event delegation in jQuery?

Click here for the code snippet <div id="container"> <button id="foo">Foo button</button> <button id="bar">Bar button</button> </div> $('#container').on('click', function(e) { var targ ...

What is the best way to retrieve the Child Key from an Object?

Having trouble looping through my child array, particularly with the child elements. The loop works fine for the first items but not for the children. "candidateApplication": [ { "label": "Are you currently attending sc ...

Input hidden is not detecting keyup or change events are not firing

One way to monitor and implement something when the Hidden input value changes, after taking its value from a text input, is by using jQuery. Here's an example of how you can achieve this: $('#input2').on('keyup, change', function ...

Creating an HTML SELECT element without a default blank option in the dropdown list using Angular

Issue: I am encountering a problem with setting a blank item to appear in the dropdown list of my form in Angular and JavaScript. As someone who is new to both languages, I have not been able to find a solution yet. Currently, my code looks like this: $ ...

Sending a variable to a VueJS component

I'm looking to pass a variable down to a component in my current setup. Here's the structure: Main: Meet.vue <html> <div class="carousel-cell"> <Category :searchTerm="woman"></Category> </div> <div cla ...

The error message "TypeError: Unable to access the country_code property of a null value" is caused by

I am currently utilizing React to display a table that is populated based on data retrieved from an API call returning JSON format. The issue I am encountering is a TypeError due to the inability to read the location object, and despite my efforts, I have ...

Sending a parameter to a function using ng-init

I am trying to display repeated data within a div element, with another iteration within that div using the id value from the first iteration. I am attempting to pass this value using a function in ng-init, but I am encountering an error. <div ...

Does adding the async attribute to a script impact the timing of the onload event?

I am facing an issue with a webpage that contains a script tag in the HEAD section: <script src="somescript.js" type="text/javascript" async></script> Since it has the async attribute, this script loads asynchronously, allowing the browser to ...

Convert XML to an HTML table in real-time as new elements are introduced

Currently, I have JSON and AJAX code that fetches XML data every second, which is working smoothly. When I added an XML element, it automatically gets added to an HTML table. The issue arises when I call the function every 3 seconds; the page refreshes due ...

JavaScript Error: value.toUpperCase is not a valid method

I am attempting to implement a script that allows users to filter rows in a table based on the value they input. After updating a row, the page refreshes and all rows are displayed again. I am looking for a way to maintain the filtered rows after the refre ...

Extracting text from HTML response and implementing a condition in Node.js

Hello, I am a beginner when it comes to node js and haven't had much experience with it before. I could really use some assistance in resolving an issue that I am facing. Below is the code snippet that I am working with: async function reserved_slot(p ...

Swapping one word with a different word in a sentence without altering any other word that shares a common substring in Javascript

Is there a way to replace the word "has" with "had" in a string without affecting instances of the word "hash" that contains the substring "has"? I'm currently using the function below but it also replaces "has" within "hash". Any suggestions on how t ...

The parameters in VueJS are malfunctioning on this webpage

I created my vue in an external file and included it at the bottom of my webpage, but I am encountering issues with its functionality. One specific problem arises when using v-model, resulting in a template error displayed on the page: Error compiling t ...

Encountering issues with ng-repeat in the third iteration

Having Trouble with ng-repeat on the Third Loop (Third Level) <div ng-repeat="child in jdata.children"> <div ng-repeat="childsub in child.children"> <div ng-repeat="text in childsub.text"> {{ text.va ...

Is it possible to design a Controller and View that can manage the creation of one-to-many objects, specifically a single "container" object along with an unlimited number of "content"

One of the functionalities for users on the website will be the ability to create documents made up of chapters in a one-to-many relationship. Traditionally, this would involve creating separate views for chapter and document creation. How can I develop ...

Troubleshooting Cordova's ng-route functionality issue

I am currently working on an Angular application that includes the following code: // app.js var rippleApp = angular.module('rippleApp', ['ngRoute', 'ngAnimate', 'ngAria', 'ngMaterial']); // configure ou ...

Encountering an issue when trying to pass a variable using a constructor

Whenever I run my TypeScript file in Angular, I encounter an error in the console. Error: compiler.js:215 Uncaught Error: Can't resolve all parameters for SearchNameComponent: ([object Object], ?). Below is my complete code: import { Component, O ...

Is there a way to make an accordion close from a nested component in react?

I'm in the process of developing a page to update product information on an e-commerce platform using NextJS. On the individual item page, I have structured the image upload section within an accordion. After the images are uploaded, I want to reset t ...

Leveraging entities within entities with connections and seeding data in Nest JS / TypeORM

Imagine we are developing our initial entities for a brand new web application. We start with an entity for users: @Entity() export class User { @PrimaryGeneratedColumn() id: number; @Column() username: string; @Column() password: string; ...

Tips for effectively transferring date from PHP into JavaScript

I have obtained the current date using a PHP script $time_local_js = date('Y,m,d,H,i', strtotime('now')); and now I need to transfer it into a JavaScript script <span id="countdown"></span> <script type="text/javascri ...