缩放子元素后的溢出滚动:在X和Y轴上表现不同

6
这里有一段代码展示了我的问题。

.container {
  width: 200px;
  height: 200px;
  overflow: auto;
}

.child {
  width: 400px;
  height: 400px;
  /* When scaling down, no more X scrolling because size is 200px, but still Y scrolling :( */
  transform: scale(0.5);
  /* Both axis working the same (no more scrolling) when absolutely positioned */
  /* position: absolute; */
}

/* Irrelevant styling */
.container {
  border: 2px solid palevioletred;
  position: relative;
}

.child {
  background-color: pink;
  transform-origin: top left;
}
<div class="container">
  <div class="child">
    Child
  </div>
</div>

Try to scroll down or right within the box.

  • 有一个固定大小的容器,其中包含一个同样具有固定大小的子元素。
  • 存在溢出滚动。
  • 然后我使用缩放变换将子元素缩小一半大小。

    • X轴滚动条消失了,因为子元素的宽度为200像素(更准确地说,容器的scrollWidth属性相应缩小)。
    • Y轴滚动条仍然存在,容器的scrollHeight属性仍然是原来的值。

我可以理解每个轴的行为,但不知道它们为什么表现不同

理想情况下,我希望Y轴的表现与X轴相同。

如果我在子元素上设置position:absolute,则Y轴的表现就像X轴一样(两个滚动条都消失了)。

.container {
  width: 200px;
  height: 200px;
  overflow: auto;
}

.child {
  width: 400px;
  height: 400px;
  position:absolute;
  transform: scale(0.5);
}

/* Irrelevant styling */
.container {
  border: 2px solid palevioletred;
  position: relative;
}

.child {
  background-color: pink;
  transform-origin: top left;
}
<div class="container">
  <div class="child">
    Child
  </div>
</div>

Try to scroll down or right within the box.

同样的情况出现在我设置display:inline-block时。两个轴表现一致(两个滚动条都不受缩放影响)。

.container {
  width: 200px;
  height: 200px;
  overflow: auto;
}

.child {
  width: 400px;
  height: 400px;
  display:inline-block;
  transform: scale(0.5);
}

/* Irrelevant styling */
.container {
  border: 2px solid palevioletred;
  position: relative;
}

.child {
  background-color: pink;
  transform-origin: top left;
}
<div class="container">
  <div class="child">
    Child
  </div>
</div>

Try to scroll down or right within the box.

在初始情况下,为什么行为会不同?为什么有些情况下,当我们使用position:absolute时,比例尺会改变滚动条,而在其他情况下则不会(当我们使用display:inline-block时)。
顺便说一句,transform是一种不影响布局的视觉效果,因此在所有情况下滚动条都不应该改变。

这是另一个:将子元素设置为inline-block,滚动条就不会改变。 - Temani Afif
呵呵,不错的发现 :) - Renaud
我编辑了这个问题并添加了更多的细节;)希望能吸引更多的关注。 - Temani Afif
谢谢 :) 我忘了提到它在Edge上正常工作(滚动永远不受影响) - Renaud
2个回答

2
我在w3.org网站中发现了一些关于可滚动溢出的令人困惑的陈述,这可能解释了为什么实现不一致。它们更像是待办标记,因为这是一个草案。

问题1:

有关滚动模型存在争议。2.1 版本似乎定义了滚动 内容 区域;内容将溢出内容框,并将该溢出与内容框合并以找到可滚动区域。特别是,这意味着内容将被起始侧填充偏移,但如果它溢出,则会直接到达结束侧的边缘。这是 Firefox 和 IE 所做的。至少一些作者(和规范作者)认为,填充框是可滚动的,因此当您滚动到溢出的末尾时,右/下填充就会出现。至少 Chrome / WebKit 在块轴上是这样做的。他们在内联轴上有些不一致;他们处理行框的方式有些奇怪。
看起来,块轴填充可能是符合网络兼容性的。不清楚内联轴填充是否符合。需要进一步实验。
问题 2:
这个对于处理变换的描述足够准确吗?
注:
可滚动的溢出矩形在盒子自己的坐标系中始终是一个矩形,但由于变换(CSS3-TRANSFORMS),在其他坐标系中可能是非矩形的。这意味着滚动条有时会在实际上不必要的情况下出现。
无论如何,似乎我们需要依靠“position:absolute”作为Chrome的解决方法。或者转换容器而不是子元素。甚至创建一个额外的容器级别也可以。希望能有所帮助!

第一个问题似乎只涉及填充,而不是变换。第二个问题需要一些上下文。您能否详细说明一下?这个注释似乎只适用于其他坐标系,而不适用于此问题。 - Mr. Hugo
1
问题1涉及填充,正如w3c的“可滚动溢出”定义所描述的那样:“框的可滚动溢出是指扩展到该框填充边缘之外的一组内容,需要提供滚动机制。” - Fabio Manzano
1
问题2涉及可滚动溢出区域的一部分:“所有框的边框框,对于其中它是包含块并且其边框框不完全位于其块起始或内联起始填充边缘之外的框,通过将每个框投影到建立其3D渲染上下文的元素的平面来计算变换。” - Fabio Manzano
1
总的来说,我试图指出一些参考资料,证明在可滚动溢出中,转换行为没有明确的定义。 - Fabio Manzano

1
我认为这种行为上的差异与transform-origin有关。当调整原点以使子元素靠右而不是靠左(并删除inline-block显示)时,水平滚动条会重新出现,子元素仅在滚动覆盖时可见(请参见代码片段)。由于子元素的默认“静态”位置(即使没有被转换)将从容器顶部显示,这就是为什么它不会像我理解的那样影响垂直滚动条的原因。
正如其他人所指出的,CSS变换还有一些未完成的任务。我不认为这是一个bug(尽管我明白你的观点)。也许在未来,w3c会提供更好的解释/更清晰的说明。

.container {
  width: 200px;
  height: 200px;
  overflow: auto;
  border: 2px solid palevioletred;
  position: relative;
}

.child {
  width: 400px;
  height: 400px;
  transform: scale(0.5);
  background-color: pink;
  transform-origin: top right;
}
<div class="container">
  <div class="child">
    Child
  </div>
</div>

Transform-origin changed to top right (as opposed to top left)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接