【问题标题】:Why does translating div remove overflow?为什么翻译 div 会消除溢出?
【发布时间】:2021-06-15 02:00:53
【问题描述】:

我并不完全清楚 CSS 转换如何影响文档的流布局和元素的定位。根据 MDN 和 W3C 上的文档,CSS 转换不会干扰流布局:

来自MDN on CSS transforms(强调我的):

通过修改坐标空间,CSS 变换会改变受影响内容的形状和位置不会破坏正常的文档流

因此,如果我们翻译一个元素,原始流布局应该保持不变,并且转换的结果应该是纯视觉的。 一个简单的例子如下所示:

.container {
  background: white;
  margin: 0 auto;
  border: 1px solid grey;
}

.block {
  width: 100%;
  height: 100px;
}

.blue {
  background: blue;
}

.red {
  background: yellow;
}

.transform {
  transform: translateY(-200%);
}
<div class="container">
  <div class="block red transform"></div>
  <div class="block blue"></div>
</div>

在这个例子中,有两个div 元素,上面的元素被垂直平移,因此不再可见。但是,流布局保持不变,文档中没有溢出。也就是说,转换的结果是纯视觉的。

现在,考虑一个具有固定宽度包装器的页面布局,这样子元素的宽度由包装器元素限定。现在添加一个比包装器更宽的 positioned 元素并添加一个偏移量(例如left)。在“足够窄”的窗口中,主体溢出,我们能够水平滚动。但是,如果我们翻译相同的元素并将其重新居中,溢出就会消失,这意味着转换不是纯视觉的。

下面的示例展示了这种效果。最初,偏移元素没有被转换。您可以尝试调整窗口大小以查看溢出,然后使用中间的按钮切换转换。

document.getElementById('toggle').addEventListener('click', function(event) {
  const blocks = document.querySelectorAll('.block.wide');
  for(let i=0;i<blocks.length;i++) {
    const block = blocks[i];
      block.classList.toggle('transform');
    }
});
html, body {
  background: #ddd;
}

.container {
  background: white;
  max-width: 1152px;
  margin: 0 auto;
}

.content {
  border: 1px solid grey;
}

.block.wide {
  background: yellow;
  max-width: 1380px;
  width: 100vw;
  position: relative;
  left: 50%;
}

.block.wide.transform {
  transform: translateX(-50%);
}
<div class="container">
  <div class="content">
    <div class="block">
      <h1>Lorem ipsum dolor sit amet</h1>
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
      <p><strong>Click the button below to toggle the transform and see the overflow vanish</strong></p>
      <button id="toggle">Toggle Transform</button>
  </div>
    <div class="block wide">
      <h1>Lorem ipsum dolor sit amet</h1>
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
  </div>
</div>

这是符合规范的预期行为吗?偏移量和变换如何相互作用?

在我所有的测试用例中,CSS 转换都达到了期望的结果。但是,我觉得我是靠运气而不是技术规范。

【问题讨论】:

    标签: css css-position overflow css-transforms


    【解决方案1】:

    这里有几个要点。

    来自 CSS 转换规范,3. The Transform Rendering Model 部分说:

    对于布局由 CSS 盒子模型控制的元素,transform 属性不会影响转换后元素周围内容的流动。但是,溢出区域的范围考虑了变换的元素。此行为类似于通过相对定位偏移元素时发生的情况。因此,如果溢出属性的值是滚动或自动,滚动条将根据需要出现,以查看在可见区域之外转换的内容。 具体来说,transform 可以扩展(但不会缩小)溢出区域的大小,溢出区域的大小是在应用 transform 之前和之后元素边界的并集。

    这意味着转换应该会影响溢出和滚动。但是,在您的第一个示例中,溢出是到负坐标空间和that overflow is always clipped,因此它不会生成任何新的滚动条。

    但是您的第二个示例,直接阅读,似乎与规范相矛盾,变换缩小了溢出区域。我认为这里发生的是位置相对偏移,并且转换是,正如上面引用所承认的,非常相似的操作,并且转换是 撤消相对定位。

    换句话说,溢出区域被计算为在应用相对定位变换之前和之后元素边界的并集。

    【讨论】:

    • 感谢您的贡献,@alohci。你的解释听起来很合理,我可以想象这确实是正在发生的事情。我最近才开始质疑我的解决方案是否适合包括“广泛的内容”,因为从技术规范中不清楚我是否依赖于指定和定义的行为。为了达到示例二中概述的预期结果,您会依赖翻译内容还是您认为我应该考虑其他方法?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-27
    • 2012-11-17
    • 1970-01-01
    • 2020-04-29
    • 2021-01-24
    • 2021-10-28
    • 2017-09-04
    相关资源
    最近更新 更多