【问题标题】:Hide overflow behind stacked div with transparent background on top of body with SVG background在具有 SVG 背景的主体顶部隐藏具有透明背景的堆叠 div 后面的溢出
【发布时间】:2018-05-08 02:23:30
【问题描述】:

我的布局包含一个带有按钮的fixed div (#navigation)。布局还包括可滚动内容 (.card)。

#navigation 目前有一个绿色背景用于演示目的。像这样:

#navigation {
  position: fixed;
  top: 20px;
  left: 50%;
  transform: translate(-50%, 0%);
  background: green;
  padding: 25px;
}
<div id="navigation"><button id="btn1">Button</button>
  <button id="btn2">Button</button>
  <button id="btn3">Button</button>
  <button id="btn4">Button</button>
</div>

我想隐藏任何.card 元素的任何部分,只要它位于绿色背景后面。所以,我使用 z-index 堆叠顺序并且效果很好。像这样:

#card-wrapper {
  width: 250px;
  margin: 100px auto;
}

.card {
  height: 200px;
  width: 200px;
  background: #131418;
  margin: 1em auto;
  display: inline-block
}

#navigation {
  position: fixed;
  top: 20px;
  left: 50%;
  transform: translate(-50%, 0%);
  z-index: 1;
  background: green;
  padding: 25px;
}

#main {
  text-align: center;
}
<div id="main">

  <div id="navigation"><button id="btn1">Button</button>
    <button id="btn2">Button</button>
    <button id="btn3">Button</button>
    <button id="btn4">Button</button>
  </div>

  <div id="card-wrapper">
    <div class="card"></div>
    <div class="card"></div>
    <div class="card"></div>
    <div class="card"></div>
    <div class="card"></div>
    <div class="card"></div>
  </div>

</div>

但是,我也不想在生产中使用绿色背景。这意味着#navigation 不应该有背景,只有里面的按钮应该是可见的。

所以我的问题是,如何在 #card-wrapper 到达假设的绿色背景后立即隐藏顶部溢出?

#card-wrapper {
  width: 250px;
  margin: 100px auto;
}

.card {
  height: 200px;
  width: 200px;
  background: #131418;
  margin: 1em auto;
  display: inline-block
}

#navigation {
  position: fixed;
  top: 20px;
  left: 50%;
  transform: translate(-50%, 0%);
  z-index: 1;
  padding: 25px;
  border: 1px solid;
  background: transparent
}

#main {
  text-align: center;
}

body {
  margin: 0 auto;
  background: url(http://svgur.com/i/42T.svg);
  background-attachment:fixed;
  background-size:cover;
}
<div id="main">

  <div id="navigation"><button id="btn1">Button</button>
    <button id="btn2">Button</button>
    <button id="btn3">Button</button>
    <button id="btn4">Button</button>
  </div>

  <div id="card-wrapper">
    <div class="card"></div>
    <div class="card"></div>
    <div class="card"></div>
    <div class="card"></div>
    <div class="card"></div>
    <div class="card"></div>
  </div>

</div>

注意,body 元素有一个 SVG 背景,我不能为#navigation 添加任何背景,因为它看起来很糟糕。

我对所有 CSS/JS/jQuery 解决方案持开放态度,只要它们不涉及硬编码值

【问题讨论】:

  • 1.应该使用真实的背景吗? 2、一定要用background-size: cover吗?
  • @Flying 1. 是的,最后一个 sn-p 中的背景是我打算使用的背景,因此您可以基于此解决方案。 2. 是的,背景填满了整个视口。
  • 你的背景是半透明的,所以即使背景会被同步——你也不会得到“隐形”块,而是this外观。真的是你想要的吗?
  • @Flying 如果你可以很好地跨设备同步背景并调整视口大小,那么不要担心透明度,这是我稍后会处理的另一个问题。
  • 除了浏览器,也可以在sn-p上测试

标签: javascript jquery css


【解决方案1】:

经过多次反复试验,我得到了这个我认为是迄今为止最好的解决方案

#card-wrapper {
  width: 250px;
  margin: 100px auto;
}

.card {
  height: 200px;
  width: 200px;
  background: #131418;
  margin: 1em auto;
  display: inline-block
}

#navigation {
  position: fixed;
  top: 20px;
  left: 25%;
  right:25%;
  z-index: 1;
  padding: 25px;
  border-top: 0.1px dotted;    
  border-bottom: 0.1px dotted;
  background: white url(http://svgur.com/i/42T.svg) top left/cover no-repeat fixed;
}

#main {
  text-align: center;
}

body {
  margin: 0 auto;
  background: white url(http://svgur.com/i/42T.svg) top left/cover no-repeat fixed;
}
<div id="main">

  <div id="navigation">
    <button id="btn1">Button</button>
    <button id="btn2">Button</button>
    <button id="btn3">Button</button>
    <button id="btn4">Button</button>
  </div>

  <div id="card-wrapper">
    <div class="card"></div>
    <div class="card"></div>
    <div class="card"></div>
    <div class="card"></div>
    <div class="card"></div>
    <div class="card"></div>
  </div>

</div>

【讨论】:

    【解决方案2】:

    JavaScript 解决方案

    解决方案的精神:

    Tested on CH62, FF57 and IE11

    如果您不介意格式,虽然 kastriotcunaku 的回答很好, 该解决方案保持与给定参数相同的参数, 在这里,我将尝试为#navigation 提供一个看起来和定位为主体的背景,以使用 JavaScript 使其具有响应性,从而产生透明的错觉。

    #navigation div 上的Background-size:cover 会使它看起来更密集。所以我会尝试模仿cover,通过拉伸背景覆盖整个身体,并且仍然只出现在导航元素上:

    navigationElement.style.backgroundSize=(document.body.clientHeight/imgH)*imgW+"px";
    

    /* imgW image width, imgH original image height. A trick to maintain the width/height ratio of the SVG. You can programmaticallyget size of the image
    For some reason I've needed that even on the body for IE11 who doesn't seem to handle "cover" properly */

    然而,对于背景定位,存在浏览器差异。令人惊讶的是IE11是最直接的

        n=document.getElementById('navigation');    
        var isChrome = !!window.chrome && !!window.chrome.webstore;
        var isIE = /*@cc_on!@*/false || !!document.documentMode;
        var imgH=647.7;
        var imgW= 2351.2;
    
           function resizeHandler(){ 
                r=n.getBoundingClientRect();
                n.style.backgroundSize=(innerHeight/imgH)*imgW+"px";
                if (isChrome){
                    n.style.backgroundPosition=r.width/2+"px 0px"
                } else if (isIE){
                    n.style.backgroundPosition=0
            document.body.style.backgroundSize=(innerHeight/imgH)*imgW+"px";
                } else{
                    n.style.backgroundPosition=-r.x+"px -20px"
                }
           }    
           addEventListener("resize",resizeHandler);
           document.addEventListener ("DOMContentLoaded",resizeHandler);
           
           
    #card-wrapper {
      width: 250px;
      margin: 100px auto;
    }
    
    .card {
      height: 200px;
      width: 200px;
      background: #131418;
      margin: 1em auto;
      display: inline-block
    }
    
    #navigation {
      position: fixed;
      top: 20px;
      left: 50%;
      transform: translate(-50%, 0%);
      z-index: 1;
      padding: 25px;
      border: 0.1px dotted;     
      background: #ffffff url(http://svgur.com/i/42T.svg);
      background-attachment: fixed;
    }
    
    #main {
      text-align: center;
    }
    
    body {
      margin: 0 auto;
      background:#ffffff  url(http://svgur.com/i/42T.svg);
      background-attachment:fixed;
      background-size:cover;
      background-position:0;
    }
    <div id="main">
    
      <div id="navigation">
        <button id="btn1">Button</button>
        <button id="btn2">Button</button>
        <button id="btn3">Button</button>
        <button id="btn4">Button</button>
      </div>
    
      <div id="card-wrapper">
        <div class="card"></div>
        <div class="card"></div>
        <div class="card"></div>
        <div class="card"></div>
        <div class="card"></div>
        <div class="card"></div>
      </div>
    
    </div>

    【讨论】:

      【解决方案3】:

      您可以将导航用作固定导航,并且只允许滚动到您的内容区域。为此,您必须将 position: absolute; 添加到 #card-wrapper 并从 .card 中删除 display:inline-block

      #card-wrapper {
        position: absolute;
        top: 100px;
        bottom: 0;
        left: 0;
        right: 0;
        overflow: auto;
      }
      
      .card {
        height: 200px;
        width: 200px;
        background: #131418;
        margin: 1em auto;
        clear:both;
      }
      
      #navigation {
        position: fixed;
        top: 20px;
        left: 50%;
        transform: translate(-50%, 0%);
        z-index: 1;
        padding: 25px;
        border: 1px solid;
        background: transparent
      }
      
      #main {
        text-align: center;
      }
      
      body {
        margin: 0 auto;
        background: url(http://svgur.com/i/42T.svg);
        background-attachment:fixed;
        background-size:cover;
      }
      <div id="main">
      
        <div id="navigation"><button id="btn1">Button</button>
          <button id="btn2">Button</button>
          <button id="btn3">Button</button>
          <button id="btn4">Button</button>
        </div>
      
        <div id="card-wrapper">
          <div class="card"></div>
          <div class="card"></div>
          <div class="card"></div>
          <div class="card"></div>
          <div class="card"></div>
          <div class="card"></div>
        </div>
      
      </div>

      【讨论】:

        【解决方案4】:

        我真的,真的,真的,真的很想找到一个使用一些新的 CSS 功能的解决方案,比如 clipbackdrop-filter。最后,我找到了一个解决方案,但它确实很短,而且不像 kastriotcunaku 的解决方案那么优雅。

        下面的解决方案使用实验性的backdrop-filter property 使#screen 元素后面的内容具有opacity(0)。不幸的是,这样做有缺点:

        • 需要几行 JavaScript 来设置 #screen 元素的尺寸以匹配 #navigation 元素 - 如果事先知道 #screen 元素的宽度/高度/位置,则可以避免这种情况李>
        • 只能在支持 backdrop-filter 属性的浏览器中工作 - 主要是 Safari,或在启用了 Experimental Web Platform 功能标志的 Chrome 中(您可以通过转到 chrome://flags/#enable-experimental-web- 进行设置) Chrome 中的平台功能)

        最终结果是:

        如果您使用的是支持backdrop-filter 的浏览器,您可以在下面查看它的运行情况:

        var screen = document.getElementById("screen");
        var navigation = document.getElementById("navigation");
        var navigationStyle = window.getComputedStyle(navigation, null);
        
        screen.style.height = navigationStyle.getPropertyValue('height');
        screen.style.width = navigationStyle.getPropertyValue('width');
        screen.style.border = navigationStyle.getPropertyValue('border');
        screen.style.borderColor = "transparent";
        #card-wrapper {
          width: 250px;
          margin: 100px auto;
        }
        
        .card {
          height: 200px;
          width: 200px;
          background: #131418;
          margin: 1em auto;
          display: inline-block
        }
        
        #screen,
        #navigation {
          position: fixed;
          top: 20px;
          left: 50%;
          transform: translate(-50%, 0%);
          padding: 25px;
        }
        
        #screen {
          backdrop-filter: opacity(0%);
          -webkit-backdrop-filter: opacity(0%);
        }
        
        #navigation {
          z-index: 10;
          border: 1px solid;
        }
        
        #main {
          text-align: center;
        }
        
        body {
          margin: 0 auto;
        }
        
        .bkg {
          position: fixed;
          z-index: 10;
          top: 0;
          left: 0;
          width: 100%;
          height: 100%;
          background: url(http://svgur.com/i/42T.svg);
          background-attachment:fixed;
          background-size:cover;
          
        }
        <div id="main">
        
          <div id="screen"></div>
          
          <div class="bkg"></div>
          
          <div id="navigation">
            <button id="btn1" onclick="alert()">Button</button>
            <button id="btn2">Button</button>
            <button id="btn3">Button</button>
            <button id="btn4">Button</button>
          </div>
        
          <div id="card-wrapper">
            <div class="card"></div>
            <div class="card"></div>
            <div class="card"></div>
            <div class="card"></div>
            <div class="card"></div>
            <div class="card"></div>
          </div>
          
        
        </div>

        如果#screen#navigation 的宽度/高度是固定的,我们将取消JavaScript。

        #card-wrapper {
          width: 250px;
          margin: 100px auto;
        }
        
        .card {
          height: 200px;
          width: 200px;
          background: #131418;
          margin: 1em auto;
          display: inline-block
        }
        
        #screen,
        #navigation {
          position: fixed;
          top: 20px;
          left: 50%;
          transform: translate(-50%, 0%);
          padding: 25px;
          width: 280px;
          height: 71px;
          box-sizing: border-box;
        }
        
        #screen {
          backdrop-filter: opacity(0%);
          -webkit-backdrop-filter: opacity(0%);
        }
        
        #navigation {
          z-index: 10;
          border: 1px solid;
        }
        
        #main {
          text-align: center;
        }
        
        body {
          margin: 0 auto;
        }
        
        .bkg {
          position: fixed;
          z-index: 10;
          top: 0;
          left: 0;
          width: 100%;
          height: 100%;
          background: url(http://svgur.com/i/42T.svg);
          background-attachment:fixed;
          background-size:cover;
          
        }
        <div id="main">
        
          <div id="screen"></div>
          
          <div class="bkg"></div>
          
          <div id="navigation">
            <button id="btn1" onclick="alert()">Button</button>
            <button id="btn2">Button</button>
            <button id="btn3">Button</button>
            <button id="btn4">Button</button>
          </div>
        
          <div id="card-wrapper">
            <div class="card"></div>
            <div class="card"></div>
            <div class="card"></div>
            <div class="card"></div>
            <div class="card"></div>
            <div class="card"></div>
          </div>
          
        
        </div>

        【讨论】:

          【解决方案5】:

          如果您不介意按钮的height 具有固定值 - 那么您的任务可以通过background-clip 样式解决。在下面的示例中,我还为卡片和按钮添加了点击处理程序,以证明卡片仍然是可点击的。

          $('.card').on('click',function(){
            $(this).addClass('clicked');
          })
          $('button').on('click',function(){
            $('.card').removeClass('clicked');
          })
          #card-wrapper {
            width: 250px;
            margin: 100px auto;
          }
          
          .card {
            height: 200px;
            width: 200px;
            background: #131418;
            margin: 1em auto;
            display: inline-block
          }
          
          #navigation {
            background-image: url(http://svgur.com/i/42T.svg);
            background-attachment: fixed;
            background-size: cover;
            background-clip: content-box;
            border: 0 none;
            padding: 0;
            top: 0;
            left: 0;
            bottom: 0;
            right: 0;
            position: fixed;
            z-index: 1;
            box-sizing: border-box;
          /**
          calc() calculation values:
           25px - .buttons-list padding  
           20px - top offset of #navigation (it is also padding-top value)
           30px - button height;
          */
            padding: 20px 0 calc(100vh - 25px * 2 - 20px - 30px);
            pointer-events: none;
          }
          
          button {
            height: 30px
          }
          
          #main {
            text-align: center;
          }
          
          body {
            margin: 0 auto;
            background: url(http://svgur.com/i/42T.svg);
            background-attachment:fixed;
            background-size:cover;
          }
          
          .buttons-list {
            padding: 25px;
            pointer-events: initial;
          }
          
          /* Just for click events demonstration */
          .card.clicked{
            background-color: green;
          }
          <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
          <div id="main">
          
            <div id="navigation">
              <div class="buttons-list">
                <button id="btn1">Button</button>
                <button id="btn2">Button</button>
                <button id="btn3">Button</button>
                <button id="btn4">Button</button>
              </div>
            </div>
          
            <div id="card-wrapper">
              <div class="card"></div>
              <div class="card"></div>
              <div class="card"></div>
              <div class="card"></div>
              <div class="card"></div>
              <div class="card"></div>
            </div>
          
          </div>

          【讨论】:

            【解决方案6】:

            也尝试为#navigation 设置相同的背景,具有相同的背景位置(参见下面的示例)

            #card-wrapper {
              width: 250px;
              margin: 100px auto;
            }
            
            .card {
              height: 200px;
              width: 200px;
              background: #131418;
              margin: 1em auto;
              display: inline-block
            }
            
            #navigation {
              position: fixed;
              top: 0;
              left: 0;
              right: 0;
              z-index: 1;
              padding: 40px 25px 25px 25px;
              background: #ffffff url(http://svgur.com/i/42T.svg);
              background-attachment: fixed;
              background-size: cover;
              background-position: 0 0;
            }
            
            #main {
              text-align: center;
            }
            
            body {
              margin: 0 auto;
              background: #ffffff url(http://svgur.com/i/42T.svg);
              background-attachment: fixed;
              background-size: cover;
              background-position: 0 0;
            }
            <div id="main">
            
              <div id="navigation">
                <button id="btn1">Button</button>
                <button id="btn2">Button</button>
                <button id="btn3">Button</button>
                <button id="btn4">Button</button>
              </div>
            
              <div id="card-wrapper">
                <div class="card"></div>
                <div class="card"></div>
                <div class="card"></div>
                <div class="card"></div>
                <div class="card"></div>
                <div class="card"></div>
              </div>
            
            </div>

            【讨论】:

            • 漂亮而优雅的解决方案。这是要走的路。
            • 在问题中#navigation 有一个top: 20px;
            • @DannyFardyJhonstonBermúdez 你仍然可以使用padding-top: 20px;从顶部添加该空间
            • @kastriotcunaku 很高兴在您的答案中添加该详细信息。
            • @kastriotcunaku 的意思是用top: 0;padding-top: 20px; 替换top:20px
            猜你喜欢
            • 1970-01-01
            • 2017-02-21
            • 2012-12-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多