【问题标题】:Prevent absolutely positioned div from swallowing click events without disabling scrollbar在不禁用滚动条的情况下防止绝对定位的 div 吞下点击事件
【发布时间】:2018-01-18 12:35:27
【问题描述】:

版本 1

代码

以下代码是我在项目中使用的布局(简化版):

document.getElementById("map").addEventListener("click", function(e) {
  alert("Map clicked!");
});

document.getElementById("control1").addEventListener("click", function(e) {
  alert("Control 1 clicked!");
});

document.getElementById("control2").addEventListener("click", function(e) {
  alert("Control 2 clicked!");
});
body, html {
  position: relative;
  width: 100%;
  height: 100%;
  margin: 0;
}

.map {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background: #0c0;
  padding: 10px;
}

.controlgroup {
  position: absolute;
  top: 10px;
  bottom: 10px;
  right: 10px;
  width: 200px;
  overflow: scroll;
  overflow-y: auto;
  overflow-x: hidden;
}

.control {
  padding: 10px;
}

#control1 {
  background: #c00;
}

.control {
  background: #00c;
}
<div class="map" id="map">
  MAP
</div>
<div class="controlgroup">
  <div class="control" id="control1">
    This is control 1<br />
    This is control 1<br />
    This is control 1<br />
    This is control 1<br />
    This is control 1<br />
    This is control 1<br />
    This is control 1<br />
  </div>
  <div class="control" id="control2">
    This is control 2<br />
    This is control 2<br />
    This is control 2<br />
    This is control 2<br />
    This is control 2<br />
    This is control 2<br />
    This is control 2<br />
  </div>
</div>

问题

这按预期工作,除非我的浏览器的高度大于我的控制组的高度。

然后,控件下方的点击会被我的对照组吞下,而不是传递到地图。


版本 2

代码

版本 1 的一个天真的修复方法是在我的 CSS 中添加一个 pointer-events 属性以忽略对控件组的点击,然后为控件重新启用它们:

document.getElementById("map").addEventListener("click", function(e) {
  alert("Map clicked!");
});

document.getElementById("control1").addEventListener("click", function(e) {
  alert("Control 1 clicked!");
});

document.getElementById("control2").addEventListener("click", function(e) {
  alert("Control 2 clicked!");
});
body, html {
  position: relative;
  width: 100%;
  height: 100%;
  margin: 0;
}

.map {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background: #0c0;
  padding: 10px;
}

.controlgroup {
  position: absolute;
  top: 10px;
  bottom: 10px;
  right: 10px;
  width: 200px;
  overflow: scroll;
  overflow-y: auto;
  overflow-x: hidden;
  pointer-events: none;
}

.control {
  padding: 10px;
}

#control1 {
  background: #c00;
}

.control {
  background: #00c;
  pointer-events: auto;
}
<div class="map" id="map">
  MAP
</div>
<div class="controlgroup">
  <div class="control" id="control1">
    This is control 1<br />
    This is control 1<br />
    This is control 1<br />
    This is control 1<br />
    This is control 1<br />
    This is control 1<br />
    This is control 1<br />
  </div>
  <div class="control" id="control2">
    This is control 2<br />
    This is control 2<br />
    This is control 2<br />
    This is control 2<br />
    This is control 2<br />
    This is control 2<br />
    This is control 2<br />
  </div>
</div>

问题

不幸的是,这破坏了我的控制组滚动条的行为。现在我不能再用滚动条滚动我的控制组了。


问题

在我的实际项目中,控件的实际内容和控件的数量对于不同的URL是不同的,但是下面的CSS代码是对所有控件和控件组收费的。此外,我实际项目中的控件是由 JavaScript 以编程方式生成的,某些控件可以根据用户输入隐藏或显示。

所以我宁愿不根据所有控件的总高度硬编码我的控件组的高度,因为这意味着在加载所有控件后以编程方式计算高度,然后每次重新计算控件的高度添加/删除。我想避免这种情况,但我正在努力想办法做到这一点!

考虑到这些标准,我应该怎么做才能防止我的对照组在不禁用滚动条的情况下吞下应该应用于地图的点击?

我更喜欢纯 CSS 解决方案,但我可以接受基于 JS 的解决方案。

【问题讨论】:

    标签: javascript html css mouseevent dom-events


    【解决方案1】:

    您可以从.controlgroup 中删除bottom:10px,这将使控件组的高度自动,因此它不会覆盖页面的整个高度,然后添加max-height: calc(100% - 20px // Reduce space from top and bottom 10px + 10px );

    document.getElementById("map").addEventListener("click", function(e) {
      alert("Map clicked!");
    });
    
    document.getElementById("control1").addEventListener("click", function(e) {
      alert("Control 1 clicked!");
    });
    
    document.getElementById("control2").addEventListener("click", function(e) {
      alert("Control 2 clicked!");
    });
    body, html {
      position: relative;
      width: 100%;
      height: 100%;
      margin: 0;
    }
    
    .map {
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      background: #0c0;
      padding: 10px;
    }
    
    .controlgroup {
        position: absolute;
        top: 10px;
        /* bottom: 10px; */
        right: 10px;
        width: 200px;
        overflow: scroll;
        overflow-y: auto;
        overflow-x: hidden;
        max-height: calc(100% - 20px);
    }
    
    .control {
      padding: 10px;
    }
    
    #control1 {
      background: #c00;
    }
    
    .control {
      background: #00c;
    }
    <div class="map" id="map">
      MAP
    </div>
    <div class="controlgroup">
      <div class="control" id="control1">
        This is control 1<br />
        This is control 1<br />
        This is control 1<br />
        This is control 1<br />
        This is control 1<br />
        This is control 1<br />
        This is control 1<br />
      </div>
      <div class="control" id="control2">
        This is control 2<br />
        This is control 2<br />
        This is control 2<br />
        This is control 2<br />
        This is control 2<br />
        This is control 2<br />
        This is control 2<br />
      </div>
    </div>

    【讨论】:

    • 我很确定我在某个时间点尝试过max-height 方法,但不知何故我无法让它工作。不知道我现在在做什么不同,但现在它确实按预期工作。感谢您为我指明正确的方向!
    猜你喜欢
    • 2019-07-22
    • 1970-01-01
    • 2015-07-05
    • 2021-05-12
    • 2014-05-10
    • 1970-01-01
    • 2011-08-17
    • 1970-01-01
    • 2016-01-27
    相关资源
    最近更新 更多