1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[メモ] sticky & Intersection Observer & opacityの併用はchromeでバグるっぽい

Last updated at Posted at 2021-05-09
  • position: sticky (by css)
    -> スクロールして画面上部で固定。弟要素が上にかぶさる

  • Intersection Observer (by js)
    -> 画面表示領域内への出入りでアニメーション用のクラス追加・削除

  • opacity (by css)
    -> Intersection Observerに伴うクラスによって表示/非表示アニメーション

の3点を組み合わせると、

上へのスクロールはできるけど、下へのスクロールができなくなる。
(上へのスクロールは通常だけど、下へスクロールは弟要素が画面下でバウンスして戻ってくる)
なんでだろう……。

どれか2個までの組み合わせなら動くんだけどな~。
この3つになると動かない…

↓書いたもの(一部省略)

parent.vue
<template>
  <div class="l-page">
    <section class="list">
      <Widgets-component
        v-for = "item in items"
        :item = "item"
        class = "item"
        :key = "item.id"
        :ref = "'item'"
      />
    </section>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [//**省略**//]
    }
  },
  updated() {
    let targets = [];
    this.$refs.item.forEach(el => targets.push(el.$el));

    const observer = new IntersectionObserver((entries) => {
      let className_active = 'is-show';
      entries.forEach((entry) => {
        if (entry.intersectionRatio >= 0.8) {
          entry.target.classList.add(className_active);
        } else {
          entry.target.classList.remove(className_active);
        }
      });
    }, {
      root: null,
      rootMargin: '0px',
      threshold: 1   
    });

    targets.forEach((target) => {
      observer.observe(target);
    });

  }

}
</script>

<style lang="scss" scoped>
.list {
  height: 100%;
  overflow-y: auto;
  scroll-snap-type: y mandatory;
}
.item {
  position: sticky;
  top: 0;
  height: 82vh;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
.disc-item::v-deep {
  .item-body, .item-footer {
    opacity: 0;
    transition: opacity 600ms ease;
  }
  &.is-show {
    .item-body, .item-footer{
      opacity: 1;
    }
  }
}
</style>

child.vue
<template>
  <div>
    <div class="item-thumb">
      <img :src="item.images.url" />
    </div>
    <div class="item-body">
      some body element
    </div>
    <div class="item-footer">
      some footer element
    </div>
  </div>
</template>

<script>
export default {
  props: {
    item: { type: Object }
  }
}
</script>

ちなみにopacityじゃなくて、backgroundだと普通に動くんだよな~。
なんか別の理由かな~。

parent.vue
<style lang="scss" scoped>
.disc-item::v-deep {
  .item-body, .item-footer {
    background: red;
  }
  &.is-show {
    .item-body, .item-footer{
      background: blue;
    }
  }
}
</style>

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?