CSS 溢出的奇怪效果在 parent 元素的位置隐藏与可见
Strange effect of CSS overflow hidden vs. visible on position of parent element
我从未读过任何内容表明元素的溢出 属性 会对我在此处看到的元素定位产生奇怪的影响:
https://codepen.io/kshetline/pen/ZEzLVxN
切换示例中的切换按钮,观察 <div>
的背景如何神秘地向上滑动,覆盖之前的内容,而其内容保持在相同的 screen-relative 位置(意思是相对于其 parent 的背景,内容正在向下移动。
这个例子是我试图用一个 Angular 组件做的事情的一个非常简化的版本,它意味着扩展它的 <ng-content>
— 但这个例子只是 CSS 和HTML 略微 JavaScript,没有 Angular,因为我试图隔离相关变量。
HTML 元素的 内容 可以使用 transform: scale(
less-than-1 比例因子 )
,但即使元素的内容被渲染得更小,默认情况下元素的像素尺寸保持不变,内容(除非另有说明)向元素的中心收缩,并且空白space 将元素保留在其原始未缩放尺寸的内容周围..
您需要计算与缩放程度相匹配的负边距,以便将元素本身视为更小。我已经这样做了,但我发现除非缩放元素的容器将 CSS overflow
设置为 hidden
,否则可能会出现一些奇怪的定位,就好像额外的空白 space 应该被负边距删除的 required 仍然有一些部分,hard-to-explain 对其他元素的整体布局有影响。
我在 Chrome、Firefox、Safari 和 Edge 中看到了这种行为——所以我猜这是 "proper" CSS 的行为,但这对我来说毫无意义,我希望有人可以解释发生了什么。我希望能够将 overflow
设置为 visible
,以便缩放后的内容仍然可以执行一些操作,例如显示不会在元素边界处被剪裁的浮动下拉菜单。
let hidden = true;
const inner = document.getElementById('inner')
function toggleOverflow() {
hidden = !hidden;
inner.style.overflow = hidden ? 'hidden' :
'visible'
}
html, body {
height: calc(100vh - 10em);
}
.page {
font: 32px Arial, Helvetica, sans-serif;
height: calc(100% - 1em);
}
.container {
background-color: #ACF;
height: 100%;
}
.outer-wrapper {
background-color: rgba(187, 255, 204, 0.5);
font-size: 2em;
margin: 0 1em;
position: relative;
}
.inner-wrapper {
overflow: hidden;
position: relative;
width: fit-content;
}
.ng-content {
margin: -18.75px 0;
transform: scale(0.5);
}
.container-text {
display: inline-block;
position: absolute;
bottom: 1em;
}
<div class="page">
<button onclick="toggleOverflow()">Toggle Overflow</button><br>
Content outside of the<br>
panel being scaled and its<br>
containing <div>, 32pt font<br>
<div class="container">
<!--Angular component start tag goes here -->
<div class="outer-wrapper">
<div id="inner" class="inner-wrapper">
<div class="ng-content">
50% scaled content goes here, 64pt font
</div>
</div>
</div>
<!-- Angular component end tag goes here -->
<span class="container-text">This is an absolutely positioned <span> in the same <div></span>
</div>
</div>
您在 .ng-content 中设置了负边距。如果 overflow 设置为 hidden,它将隐藏负边距。将边距设置为正数,就可以解决这个跳跃问题。
.ng-content { margin: 18.75px 0; }
如果您尝试上下更改元素的高度,请尝试使用 max-height
和 overflow: hidden
。当最大高度设置为 0 时,它将被隐藏。当设置为 500 像素时,您的内容将会显示!
跟进...
我在这里为我的第一个代码笔创建了一个变体:
https://codepen.io/kshetline/pen/WNeRmOo
在这种情况下,我在缩放时使用 transform-origin: top center
,并将所有需要的负边距放在缩放元素的底部,而不是在顶部和底部之间平均分割。这消除了奇怪的垂直位置偏移。
overflow: hidden
仍然需要从其容器的 "leaking out" 隐藏多余的背景颜色,但在缩放元素的背景是透明的(常见)情况下,会有使用 overflow: visible
没有明显的效果,并且不用担心缩放元素内部产生的下拉菜单被剪裁。
后续 #2...
这是最好的解决方案,使用 padding: 0.05px
来处理 @Alochi 帮助我理解的真正问题 — 停止边框折叠:
Margins of elements that establish new block formatting contexts (such as floats and elements with 'overflow' other than 'visible') do not collapse with their in-flow children.
所以添加 overflow:hidden
是为了防止边距折叠。
我从未读过任何内容表明元素的溢出 属性 会对我在此处看到的元素定位产生奇怪的影响:
https://codepen.io/kshetline/pen/ZEzLVxN
切换示例中的切换按钮,观察 <div>
的背景如何神秘地向上滑动,覆盖之前的内容,而其内容保持在相同的 screen-relative 位置(意思是相对于其 parent 的背景,内容正在向下移动。
这个例子是我试图用一个 Angular 组件做的事情的一个非常简化的版本,它意味着扩展它的 <ng-content>
— 但这个例子只是 CSS 和HTML 略微 JavaScript,没有 Angular,因为我试图隔离相关变量。
HTML 元素的 内容 可以使用 transform: scale(
less-than-1 比例因子 )
,但即使元素的内容被渲染得更小,默认情况下元素的像素尺寸保持不变,内容(除非另有说明)向元素的中心收缩,并且空白space 将元素保留在其原始未缩放尺寸的内容周围..
您需要计算与缩放程度相匹配的负边距,以便将元素本身视为更小。我已经这样做了,但我发现除非缩放元素的容器将 CSS overflow
设置为 hidden
,否则可能会出现一些奇怪的定位,就好像额外的空白 space 应该被负边距删除的 required 仍然有一些部分,hard-to-explain 对其他元素的整体布局有影响。
我在 Chrome、Firefox、Safari 和 Edge 中看到了这种行为——所以我猜这是 "proper" CSS 的行为,但这对我来说毫无意义,我希望有人可以解释发生了什么。我希望能够将 overflow
设置为 visible
,以便缩放后的内容仍然可以执行一些操作,例如显示不会在元素边界处被剪裁的浮动下拉菜单。
let hidden = true;
const inner = document.getElementById('inner')
function toggleOverflow() {
hidden = !hidden;
inner.style.overflow = hidden ? 'hidden' :
'visible'
}
html, body {
height: calc(100vh - 10em);
}
.page {
font: 32px Arial, Helvetica, sans-serif;
height: calc(100% - 1em);
}
.container {
background-color: #ACF;
height: 100%;
}
.outer-wrapper {
background-color: rgba(187, 255, 204, 0.5);
font-size: 2em;
margin: 0 1em;
position: relative;
}
.inner-wrapper {
overflow: hidden;
position: relative;
width: fit-content;
}
.ng-content {
margin: -18.75px 0;
transform: scale(0.5);
}
.container-text {
display: inline-block;
position: absolute;
bottom: 1em;
}
<div class="page">
<button onclick="toggleOverflow()">Toggle Overflow</button><br>
Content outside of the<br>
panel being scaled and its<br>
containing <div>, 32pt font<br>
<div class="container">
<!--Angular component start tag goes here -->
<div class="outer-wrapper">
<div id="inner" class="inner-wrapper">
<div class="ng-content">
50% scaled content goes here, 64pt font
</div>
</div>
</div>
<!-- Angular component end tag goes here -->
<span class="container-text">This is an absolutely positioned <span> in the same <div></span>
</div>
</div>
您在 .ng-content 中设置了负边距。如果 overflow 设置为 hidden,它将隐藏负边距。将边距设置为正数,就可以解决这个跳跃问题。
.ng-content { margin: 18.75px 0; }
如果您尝试上下更改元素的高度,请尝试使用 max-height
和 overflow: hidden
。当最大高度设置为 0 时,它将被隐藏。当设置为 500 像素时,您的内容将会显示!
跟进...
我在这里为我的第一个代码笔创建了一个变体:
https://codepen.io/kshetline/pen/WNeRmOo
在这种情况下,我在缩放时使用 transform-origin: top center
,并将所有需要的负边距放在缩放元素的底部,而不是在顶部和底部之间平均分割。这消除了奇怪的垂直位置偏移。
overflow: hidden
仍然需要从其容器的 "leaking out" 隐藏多余的背景颜色,但在缩放元素的背景是透明的(常见)情况下,会有使用 overflow: visible
没有明显的效果,并且不用担心缩放元素内部产生的下拉菜单被剪裁。
后续 #2...
这是最好的解决方案,使用 padding: 0.05px
来处理 @Alochi 帮助我理解的真正问题 — 停止边框折叠:
Margins of elements that establish new block formatting contexts (such as floats and elements with 'overflow' other than 'visible') do not collapse with their in-flow children.
所以添加 overflow:hidden
是为了防止边距折叠。