【问题标题】:Change the background color with a sticky element使用粘性元素更改背景颜色
【发布时间】:2019-03-05 06:42:14
【问题描述】:

我想用粘性元素更改滚动的主体颜色背景。

body {
  margin: 0;
  background: lightblue;
}

.blue-container {
  height: 70vh;
}

.blue {
  height: 40vh;
  position: sticky;
  width: 70%;
  top: 0;
  background: blue;
  margin: auto;
}

.pink {
  height: 500px;
  position: relative;
  width: 70%;
  margin-right: auto;
  margin-left: auto;
  background: pink;
  text-align: center;
}
<div class='blue-container'>
  <div class='blue'></div>
</div>

<div class='pink'> When I touch the blue bloc, I would like the 'body background' change into an other color (for exemple : orange)</div>

这是我的jsFiddle,了解我想要什么。

【问题讨论】:

    标签: jquery html css colors sticky


    【解决方案1】:

    您可以使用intersection observer 来检测视口内何时有足够的.pink 元素触摸.blue 元素:

    const body = document.querySelector('body');
    const blue = document.querySelector('.blue');
    const target = document.querySelector('.pink');
    
    const getHeight = (el) => el.getBoundingClientRect().height;
    
    // get the threshold in which enough of the pink elment would be inside the viewport to touch the blue element
    const threshold = (window.innerHeight - getHeight(blue)) / getHeight(target);
    
    const options = {
      rootMargin: '0px',
      threshold
    };
    
    let prevRatio = 0;
    
    const handleIntersect = (entries, observer) => {
      entries.forEach(function(entry) {
        // if going up (above the previous threshold & above the threshold
        if (entry.intersectionRatio >= threshold && entry.intersectionRatio > prevRatio) {
          body.classList.add('body--intersected');
        } else {
          body.classList.remove('body--intersected');
        }
    
        prevRatio = entry.intersectionRatio;
      });
    }
    
    const observer = new IntersectionObserver(handleIntersect, options);
    
    observer.observe(target);
    body {
      margin: 0;
      background: lightblue;
    }
    
    .body--intersected {
      background: pink;
    }
    
    .blue-container {
      height: 70vh;
    }
    
    .blue {
      height: 40vh;
      position: sticky;
      width: 70%;
      top: 0;
      background: blue;
      margin: auto;
    }
    
    .pink {
      height: 500px;
      position: relative;
      width: 70%;
      margin-right: auto;
      margin-left: auto;
      background: pink;
      text-align: center;
    }
    <div class='blue-container'>
      <div class='blue'></div>
    </div>
    
    <div class='pink'> When I touch the blue bloc, I would like the 'body background' change into an other color (for exemple : orange)</div>

    【讨论】:

      【解决方案2】:

      我不知道你是否可以在纯 CSS 中做到这一点,但这里有一个 vanillaJS 解决方案:

      • 我们在滚动时触发一个事件
      • 我们检查蓝色的底部位置和粉色的顶部位置
      • 如果它们相等,我们就会触发逻辑。

      var blue = document.querySelector('.blue')
      var pink = document.querySelector('.pink')
      var onTouch = false;
      
      //http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html#event-type-scroll
      function onScrollEventHandler(ev) {
          var bottom = blue.getBoundingClientRect().bottom
          var top = pink.getBoundingClientRect().top
          // we set
          if (bottom == top && !onTouch) {
              document.body.style.backgroundColor = 'orange' 
              onTouch = true
          }
          // we reset
          if (bottom != top && onTouch) {
            document.body.style.backgroundColor = 'lightblue' 
            onTouch = false
          }
      } 
      
      var el=window;
      if(el.addEventListener)
          el.addEventListener('scroll', onScrollEventHandler, false);   
      else if (el.attachEvent)
          el.attachEvent('onscroll', onScrollEventHandler); 
      body {
        margin:0;
        background:lightblue;}
      
      .blue-container {
       height:70vh;
      }
      
      .blue {
       height:40vh;
       position:sticky;
       width:70%;
       top:0;
       background:blue;
       margin:auto;
      }
      
      .pink {
       height:500px;
       position:relative;
       width:70%;
       margin-right:auto;
       margin-left:auto;
       background:pink;
        text-align:center;
      }
      <div class='blue-container'>
        <div class='blue'></div>
      </div>
      
      <div class='pink'> When I touch the blue bloc, I would like the 'body background' change into an other color (for exemple : orange)</div>

      此代码正在进行中。欢迎所有意见。

      【讨论】:

        【解决方案3】:

        您可以计算blue div 和pink div 之间的空白空间($('.blue-container').height() - $('.blue').height()),然后当文档滚动到该错误时,您知道粉红色的 div 已触及蓝色的 div。

        $(function(){
        
          $(window).scroll(function(){
            var margin = $('.blue-container').height() - $('.blue').height();
            if($(this).scrollTop()>=margin){
                $("body").addClass("orange")
            } else{
            	$("body").removeClass("orange")
            }
          });
        });
        body {
          margin:0;
          background:lightblue;}
        
        .blue-container {
         height:70vh;
        }
        
        .blue {
         height:40vh;
         position:sticky;
         width:70%;
         top:0;
         background:blue;
         margin:auto;
        }
        
        .pink {
         height:500px;
         position:relative;
         width:70%;
         margin-right:auto;
         margin-left:auto;
         background:pink;
          text-align:center;
        }
        
        .orange{
          background:orange
        }
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
        <div class='blue-container'>
          <div class='blue'></div>
        </div>
        
        <div class='pink'> When I touch the blue bloc, I would like the 'body background' change into an other color (for exemple : orange)</div>

        【讨论】: