javascriptreactjsmaterial-uijsxparticles.js

Particles.js does not cover the entire page but instead it is inside the card component


I wanted the Particles.js to be served as background. However, it only shows inside the Card Component. And also how can I make the particles.js not pass through the card. As of now, the card is like a transparent one where you could just see the lines passing through it. I just wanted the Particles.js to stay behind the Card. How can I do this? Thank you.

I recreated it here: https://codesandbox.io/s/basiccard-material-demo-forked-p644e?file=/Form.js

Card Component

import React from "react";
import Card from "@mui/material/Card";
import CardContent from "@mui/material/CardContent";
import { CardHeader, styled } from "@mui/material";

const StyledCard = styled((props) => <Card {...props} />)(({ theme }) => ({
  maxWidth: 500,
  margin: "0 auto",
  marginBottom: "1rem",
  marginTop: "1rem"
}));

const CardComponent = (props) => {
  const { title, content } = props;

  return (
    <StyledCard sx={{ minWidth: 275 }} elevation={5}>
      <CardHeader title={title} />
      <CardContent>{props.children}</CardContent>
    </StyledCard>
  );
};

export default CardComponent;

Form

import React from "react";
import CardComponent from "./CardComponent";
import { TextField } from "@mui/material";

const Form = (props) => {
  const { children } = props;

  return (
    <CardComponent>
      <form
        style={{
          position: "relative",
          width: "100%",
          height: "200px"
        }}
      >
        <TextField
          label="sample1"
          style={{
            position: "absolute",
            top: "25%",
            left: "50%",
            marginLeft: "-150px",
            width: "300px",
            zIndex: "1",
            color: "red"
          }}
        />

        <TextField
          label="sample2"
          style={{
            position: "absolute",
            bottom: "25%",
            left: "50%",
            marginLeft: "-150px",
            width: "300px",
            zIndex: "1"
          }}
        />
        {children}
      </form>
    </CardComponent>
  );
};

export default Form;

Particles.js

import React, { Component } from "react";
import Particles from "react-tsparticles";

class Canvas extends Component {
  render() {
    return (
      <Particles
        style={{
          position: "absolute",
          top: "0",
          left: "0",
          height: "100%",
          width: "100%",
          margin: "0",
          padding: "0",
          zIndex: "0"
        }}
        options={{
          fullScreen: {
            enable: false
          },
          particles: {
            number: {
              value: 80,
              density: {
                enable: true,
                area: 800
              }
            },
            color: {
              value: "#fbc106"
            },
            shape: {
              type: "circle"
            },
            opacity: {
              value: { min: 0.1, max: 0.4 },
              animation: {
                enable: true,
                speed: 1,
                sync: false
              }
            },
            size: {
              value: { min: 0.1, max: 3 },
              animation: {
                enable: true,
                speed: 2,
                sync: false
              }
            },
            links: {
              enable: true,
              distance: 100,
              color: "#fbc106",
              opacity: 1,
              width: 1
            },
            move: {
              enable: true,
              speed: 1,
              direction: "none",
              random: false,
              straight: false,
              outModes: {
                default: "out"
              }
            }
          },
          interactivity: {
            detectsOn: "window",
            events: {
              onHover: {
                enable: false
              },
              onClick: {
                enable: false
              },
              resize: true
            }
          },
          detectRetina: true
        }}
      />
    );
  }
}

export default Canvas;

Demo.js

import React from "react";

import Particles from "./Particles";

import Form from "./Form";

const styles = {
  root: {
    fontFamily: "sans-serif",
    textAlign: "center",
    height: "100%",
    background: "#222",
    display: "flex",
    justifyContent: "center",
    alignItems: "center"
  }
};

export default function BasicCard() {
  return (
    <div
    //  style={styles.root}
    >
      <Form>
        <Particles />
      </Form>
    </div>
  );
}

Solution

  • The Form component is currently controlling the stacking context for its children (being positioned relatively), including Particles. In other words, Particles, which is absolutely positioned within Form, is constrained within Form's stacking context.

    One solution is to make <Form /> and <Particles /> siblings in demo.js. For example:

    <div>
      <Particles /> {/* Removes `Particles` from the `Form` stacking context entirely */}
      <Form />
    </div>
    

    And then define the zIndex, position, and backgroundColor for the StyledCard:

    const StyledCard = styled((props) => <Card {...props} />)(({ theme }) => ({
      ...
      backgroundColor: "#fff", // Added -- You're going to have to define this based on the theme
      position: "relative" // Added so it can be "lifted"
      zIndex: "10", // Added to "lift" it above the particles
    }));
    

    There are better solutions for your problem, but this is the simplest fix because it requires the least refactoring.

    Note: The card itself does not have a background color -- you'll either need to include another component that does, such as Paper, or add your own background color to it. I added white (#fff) as an example, but you'll probably want to pull this off the theme object if you go this route.

    Working CodeSandbox: https://codesandbox.io/s/basiccard-material-demo-forked-6lyk8?file=/CardComponent.js

    If you're interested in exploring how Stacking Contexts works, this demo that I created a few years ago might be helpful.