New Front-ender here. I am trying to create a container full of divs using flex-box or grid (grid container flexed in this example) where only the divs show the background-image and I want the rest of the container to be white. There is a similar question/answer here:

How can I set a background image for multiple divs?

but this won't work if you want to use a grid with divs inside or a flex container and want to use border-radius.

I have tried absolute positioning of two layers, z-index, background-clip, background-color: transparent and also thought about an overlay but couldn't work through that scenario. I left the borders off the top layer container of divs just to show that there are two layers. If you add in the z-index for the top-container you can kind of see what I'm trying to get but I can't get the divs to become transparent (while the space around is white) and shows the color underneath.

body {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
}

.container-bottom-layer {
  position: absolute;
  display: grid;
  grid: auto-flow / 1fr 1fr 1fr;
  background-image: linear-gradient(90deg, yellow, purple);
  border-radius: 15px;
  padding: 20px;
  border: 1px solid black;
  z-index: 1;
}

.container-item-bottom {
  margin: 15px;
  width: 100px;
  height: 100px;
  border: 1px solid black;
  border-radius: 10px;
}

.container-top-layer {
  position: absolute;
  display: grid;
  grid: auto-flow / 1fr 1fr 1fr;

  background-color: white;
  padding: 15px;

  /* background-clip: padding-box; */
  /* background-clip: padding-box; */
  /* -webkit-background-clip: padding-box; */
  /* color: transparent; */

  /* z-index: 1; */
}

.container-item-top {
  margin: 15px;
  width: 100px;
  height: 100px;
  border: 1px solid black;

  /* background-clip: content-box; */
  /* -webkit-background-clip: content-box; */
  background-color: transparent;

  z-index: 2;
}
<body>

    <div class="container-bottom-layer">
        <div class="container-item-bottom"></div>
        <div class="container-item-bottom"></div>
        <div class="container-item-bottom"></div>
        <div class="container-item-bottom"></div>
        <div class="container-item-bottom"></div>
        <div class="container-item-bottom"></div>
        <div class="container-item-bottom"></div>
        <div class="container-item-bottom"></div>
        <div class="container-item-bottom"></div>
    </div>

    <div class="container-top-layer">
        <div class="container-item-top"></div>
        <div class="container-item-top"></div>
        <div class="container-item-top"></div>
        <div class="container-item-top"></div>
        <div class="container-item-top"></div>
        <div class="container-item-top"></div>
        <div class="container-item-top"></div>
        <div class="container-item-top"></div>
        <div class="container-item-top"></div>
    </div>

</body>

1

There are 1 best solutions below

2
On

There is no need to create a complicated overlay structure. Your grid items (.grid > * in the snippet) need to share the same fixed background-image:

  • .grid > * { background-image: your gradient; background-attachment: fixed }
  • for a shared image you might need to add background-size, background-cover and background-repeat, depending on the size of the image used.

For the snippet I ripped your original code apart and removed all obsolete code:

/* Grid items background setup, shared gradient */
.grid > * {
    background-image: linear-gradient(90deg, yellow, purple);
    background-attachment: fixed;  /* [MANDATORY]  */

    background-size      : cover;     /* When combined with image */
    background-position  : center;    /* Toy with this */
    background-repeat    : no-repeat; /* For very small images */

/*    background-blend-mode: normal;    /* When combined with image */
}

/*******************/
/* Demo grid setup */
/*******************/
* { box-sizing: border-box }

body {
    display: flex; flex-wrap: wrap;
    justify-content: center; align-items: center;
    margin: 0; height: 100vh;
}

.grid { /* grid container */
    display: grid;
    grid: auto-flow / 1fr 1fr 1fr;
    padding: 20px;
    border-radius: 15px;
}
.grid > * { /* grid items */
    margin: 15px;
    width: 100px;
    height: 100px;
    border-radius: 10px;
}
.grid, .grid > * { border: 1px solid black }
<div class="grid">
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
</div>