Home > other >  How can I layer an absolutely-positioned element between children of a sibling element?
How can I layer an absolutely-positioned element between children of a sibling element?

Time:01-14

I am using vue-slick-carousel package.

I have three main elements with which I want to interact. The first one is a picture with a character with the class slide__person The second one is a text with the class slide__text and a picture with a cloud with the class banner__slider-cloud.

I need the text to overlap the cloud, and the cloud, in turn, overlaps the picture with the person.

The cloud must remain static and cannot be moved inside the slider

I want to achieve something like this.

.banner__slider-cloud {
   z-index: 1;
}

.slide__text {
    z-index: 2;
}

.slide__person {
   z-index: 0;
}

I tried different options, interacted with the z-index property, tried to apply the position property, but I could not solve this problem

You can also see my code in the online sandbox codesandbox

<script>
import VueSlickCarousel from "vue-slick-carousel";
import "vue-slick-carousel/dist/vue-slick-carousel.css";
// optional style for arrows & dots
import "vue-slick-carousel/dist/vue-slick-carousel-theme.css";

export default {
  name: "HelloWorld",

  components: { VueSlickCarousel },
};
</script>

<template>
  <div >
    <main >
      <div >
        <VueSlickCarousel :arrows="true" :dots="true">
          <div >
            <div>
              <img
                
                src="https://www.wikihow.com/images/6/61/Draw-a-Cartoon-Man-Step-15.jpg"
              />

              <p >
                Lorem ipsum dolor sit amet, consectetur adipisicing elit.
                Aliquam architecto, corporis deserunt distinctio dolor dolores
                ea ex hic iste magnam nihil optio perferendis perspiciatis
              </p>
            </div>
          </div>

          <div >
            <div>
              <img
                
                src="https://www.wikihow.com/images/6/61/Draw-a-Cartoon-Man-Step-15.jpg"
              />

              <p >
                Lorem ipsum dolor sit amet, consectetur adipisicing elit.
                Aliquam architecto, corporis deserunt distinctio dolor dolores
                ea ex hic iste magnam nihil optio perferendis perspiciatis
              </p>
            </div>
          </div>
        </VueSlickCarousel>

        <img  src="../assets/cloud.png" />
      </div>
    </main>
  </div>
</template>

<style>
img {
  max-width: 100%;
}

.slick-slide > div {
  display: flex;
  justify-content: center;
}

.slide {
  max-width: 500px;
  border: 2px solid orange;
  padding: 1rem;
}

.slide .slide__text {
  border: 2px solid green;
  padding: 8px;
}

.banner__slider-cloud {
  border: 1px solid;
  max-width: 960px;
  margin: auto;
  position: absolute;
  right: 0;
  left: 0;
  top: 5%;
}
</style>

img {
  max-width: 100%;
}

.slick-slide>div {
  display: flex;
  justify-content: center;
}

.slide {
  max-width: 500px;
  border: 2px solid orange;
  padding: 1rem;
}

.slide .slide__text {
  border: 2px solid green;
  padding: 8px;
}

.banner__slider-cloud {
  border: 1px solid;
  max-width: 960px;
  margin: auto;
  position: absolute;
  right: 0;
  left: 0;
  top: 5%;
}
<div >
  <main >
    <div >
      <div >
        <div>
          <img  src="https://www.wikihow.com/images/6/61/Draw-a-Cartoon-Man-Step-15.jpg" />

          <p >
            Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam architecto, corporis deserunt distinctio dolor dolores ea ex hic iste magnam nihil optio perferendis perspiciatis
          </p>
        </div>
      </div>

      <img  src="https://via.placeholder.com/500" />
    </div>
  </main>
</div>

CodePudding user response:

z-index only works on elements within the same stacking context

By moving the cloud image element to be a sibling of the text and person image elements, their z-indexes will cause them to overlap the way you want

<div>
  <img
    
    src="https://www.wikihow.com/images/6/61/Draw-a-Cartoon-Man-Step-15.jpg"
  />

  <p >
    Lorem ipsum dolor sit amet, consectetur adipisicing elit.
    Aliquam architecto, corporis deserunt distinctio dolor dolores
    ea ex hic iste magnam nihil optio perferendis perspiciatis
  </p>
  <img  src="../assets/cloud.png" />
</div>
.slide .slide__person {
  position: relative;
  z-index: 0;
}
.slide .slide__text {
  border: 2px solid green;
  padding: 8px;
  position: relative;
  z-index: 2;
}

.banner__slider-cloud {
  border: 1px solid;
  max-width: 960px;
  margin: auto;
  position: absolute;
  left: 17%;
  top: 5%;
  z-index: 1;
}

updated codesandbox

CodePudding user response:

Although I believe a full solution is impossible, due to the DOM manipulation that the Vue Slick Carousel library uses, there is a workaround to the z-index limitation using transform-style: preserve-3d.

So long as all the elements in the DOM hierarchy being manipulated have the preserve-3d CSS attribute applied (this property is not automatically inherited), you can use transform: translateZ() to sort elements' layering even when they are not siblings in the stacking context. See the edited snippet below.

img {
  max-width: 100%;
}

/* ### Added this block ### */

.banner * {
  transform-style: preserve-3d;
}

.slick-slide>div {
  display: flex;
  justify-content: center;
}

.slide {
  max-width: 500px;
  border: 2px solid orange;
  padding: 1rem;
}

.slide .slide__text {
  border: 2px solid green;
  padding: 8px;
  transform: translateZ(1px); /* ### Added this line ### */
}

.banner__slider-cloud {
  border: 1px solid;
  max-width: 960px;
  margin: auto;
  position: absolute;
  right: 0;
  left: 0;
  top: 5%;
}
<div >
  <main >
    <div >
      <div >
        <div>
          <img  src="https://www.wikihow.com/images/6/61/Draw-a-Cartoon-Man-Step-15.jpg" />

          <p >
            Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam architecto, corporis deserunt distinctio dolor dolores ea ex hic iste magnam nihil optio perferendis perspiciatis
          </p>
        </div>
      </div>

      <img  src="https://via.placeholder.com/500" />
    </div>
  </main>
</div>

  • Related