0

Consider the following example app, which produces an output that looks like this:

Sandbox Here

enter image description here

JS (React)

export default function App() {
  return (
    <>
      <div className="container">
        <div className="animation">
          <div className="scrollable">
            {Array(10)
              .fill(0)
              .map((_, i) => (
                <div className={`box ${i % 2 ? "" : "top"}`} />
              ))}
          </div>
        </div>
      </div>
      <div className="overlay" />
    </>
  );
}

CSS

.animation {
  /* transform: scale(0.95); */
}

.scrollable {
  display: flex;
}

.box {
  width: 100px;
  height: 100px;
  margin-right: 10px;
  flex-shrink: 0;
  background: fuchsia;
}

.box.top {
  z-index: 10;
}

.overlay {
  position: fixed;
  width: 100%;
  height: 100%;
  top: 0px;
  left: 0px;
  background: rgba(0, 0, 0, 0.5);
}

We have a position: fixed overlay on top of a scrollable collection of pink boxes. The scrollable flex container is wrapped in an .animation class, which we want to apply a transform to (like transform: scale(0.95).

If we uncomment the transform line, all the boxes appear below the overlay, like so:

enter image description here

We can add position: absolute and z-index: 10 to the .animation class in order to place all the boxes on top of the overlay, but that isn't desired either. What we want is to allow some boxes to appear above the overlay, and others below, as shown in the first image above. We need to be able to manipulate the transform of the .animation class, so removing that is not an option.

Making the following adjustments on Safari does the trick, but does not seem to work on Chrome.

CSS

.animation {
  transform: scale(0.95);
  transform-style: preserve-3d;
}

.box.top {
  z-index: 10;
  transform: translateZ(10px);
}

Is it possible, without changing the HTML structure, to reliably achieve the desired effect?

You can find a Sandbox Here

CaptainStiggz
  • 1,787
  • 6
  • 26
  • 50

1 Answers1

-1

You can use nth-child pseudo class.

You need to make overlay element and scrollable element in one parent.

.box:nth-child(2n - 1) {
  /* Select every 2 element start from first element */
  z-index: 10;
  position: relative;
}
<div className="container">
  <div className="overlay" />
  <div className="scrollable">
    {{Array(10)
        .fill(0)
        .map((_, i) => (
          <div className="box" />
    ))}
  </div>
</div>

Example: Code sandbox

kennarddh
  • 2,186
  • 2
  • 6
  • 21
  • This sort of produces a similar screenshot, but doesn't really address the spirit of the question. What I really need to do is have the alternating boxes appear on top of the overlay. If there was a way to force a new root-level stacking context, that's what I need. – CaptainStiggz Aug 26 '22 at 07:11
  • What is the use of transition class – kennarddh Aug 26 '22 at 07:44
  • I have edited the codesandbox and answer – kennarddh Aug 26 '22 at 07:53