<div class="image1"></div>

<div class="text">
  <h2>
    background-attachment <br><br>
    - scroll (기본) <br>
    - fixed (고정)<br>
  </h2>
</div>

<div class="image2"></div>

<div class="text">
  <h2>
    background-attachment 속성으로, <br>
    배경 이미지를 고정시켜보세요!
  </h2>
</div>

<div class="image3"></div>
h2 {
  transform: translateX(-50%);
  opacity: 0;
  transition: .8s;
}

h2.active {
  transform: translateX(0);
  opacity: 1;
}

div {
  width: 100%;
  height: 100vh;
  position: relative;
}

.image1 {
    background: url(https://cdn.pixabay.com/photo/2020/07/14/16/18/snow-5404785_960_720.jpg) no-repeat;
  background-attachment: fixed;
}

.image2 {
    background: url(https://cdn.pixabay.com/photo/2022/08/23/06/55/village-7405160_960_720.jpg) no-repeat;
  background-attachment: fixed;
}

.image3 {
    background: url(
https://cdn.pixabay.com/photo/2022/08/30/15/33/nature-7421337_960_720.jpg) no-repeat;
  background-attachment: fixed;
}

 /* ----------- */

.text {
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
  color: #fff;
  background: #1e3932;
  font-size: .9rem;
}

@import url("https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css");

* {
  font-family: Pretendard;
  padding: 0;
  margin: 0;
}
const options = {
  root: null, // viewport
  rootMargin: "0px",
  threshold: .5,  // 50%가 viewport에 들어와 있어야 callback 실행
}

const observer = new IntersectionObserver(entries => {
  entries.forEach(entry => {
    console.log(entry.isIntersecting);
    if (entry.isIntersecting) {
      entry.target.classList.add("active");
    } else {
      entry.target.classList.remove("active");
    }
  });
}, options);

const titleList = document.querySelectorAll('h2');

// 반복문을 돌려 모든 DOM에 적용
titleList.forEach(el => observer.observe(el));

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.