CSS 转换不适用于高内容

CSS Transform not working with tall content

当使用变换使内容垂直居中时,如果内容不高于视​​口则效果很好,但如果它更高,则无法滚动查看最顶部。有修复吗?

See example of content being pushed off screen.

CSS

.center {
    position: $position;
    top: 50%;
    transform: translateY(-50%);
}
p{
  height: 1500px;
}

HTML

<div class="center">
  <h1>I am pushed off screen!?</h1>
  <p>Tall Content...</p>
</div>

请查看 CSS 转换渲染模型(来自 W3C 规范):

Specifying a value other than none for the transform property establishes a new local coordinate system at the element that it is applied to. The mapping from where the element would have rendered into that local coordinate system is given by the element’s transformation matrix. Transformations are cumulative. That is, elements establish their local coordinate system within the coordinate system of their parent. From the perspective of the user, an element effectively accumulates all the transform properties of its ancestors as well as any local transform applied to it. The accumulation of these transforms defines a current transformation matrix (CTM) for the element.

进一步阅读:https://www.w3.org/TR/css3-transforms/#transform-rendering


让我们从基础开始,这是 parent:

中 child 的默认行为

.parent {
  width:200px;
  height:200px;
  border: 1px dashed #666;
}

.child {
  border: 1px solid red;
  width:100px;
  height:100px;
}
<p>Container: 200 x 200 px</p>
<div class="parent">
  <div class="child">
    <h4>100 x 100</h4>
  </div>
</div>

现在如果我们想使用top偏移量,我们需要使用定位。

.parent {
  width:200px;
  height:200px;
  border: 1px dashed #666;
}

.child {
  border: 1px solid red;
  width:100px;
  height:100px;
  position: relative;
  top:50%;
}
<p>Container: 200 x 200 px</p>
<div class="parent">
  <div class="child">
    <h4>100 x 100</h4>
  </div>
</div>

此时,您想通过添加 transform: translateY(-50%); 来垂直对齐 child 但在我们这样做之前,让我们看看如果 parent 没有定义 height 会发生什么], IE。高度是动态的,基于 child:

.parent {
  width:200px;
  border: 1px dashed #666;
}

.child {
  border: 1px solid red;
  width:100px;
  height:100px;
  position: relative;
  top:50%;
}
<p>Container: 200 x AUTO px</p>
<div class="parent">
  <div class="child">
    <h4>100 x 100</h4>
  </div>
</div>

如您所见,top 偏移几乎被忽略了,因为浏览器无法计算 auto 高度的百分比。因此,当您尝试添加 transform: translateY 属性 时,该元素将超出 parent:

的范围

.parent {
  width:200px;
  border: 1px dashed #666;
}

.child {
  border: 1px solid red;
  width:100px;
  height:100px;
  position:relative;
  top:50%;
  transform:translateY(-50%);
}
<p>Container: 200 x AUTO px</p>
<div class="parent">
  <div class="child">
    <h4>100 x 100</h4>
  </div>
</div>

总而言之,transform 属性无法正常工作,因为当 position 偏移量以百分比表示时无法计算,而 parent 具有 auto / 动态高度。如果您使用固定高度,它应该按预期工作:

.parent {
  width:200px;
  border: 1px dashed #666;
}

.child {
  border: 1px solid red;
  width:100px;
  height:100px;
  position:relative;
  top:50px; /* half of 100px is 50px - instead of 50% */
  transform:translateY(-50%);
}
<p>Container: 200 x AUTO px</p>
<div class="parent">
  <div class="child">
    <h4>100 x 100</h4>
  </div>
</div>

当然,这不是动态的。您可以使用 JavaScript 到 get/update 固定像素尺寸。

正如 W3C 规范所解释的那样,由于转换后的元素创建了一个相对于元素本身的坐标,如果元素溢出视口或其 parent,则不会创建滚动条,参见示例:

div {
  width:100px;
  height:100px;
  border:1px dashed #666;
  position: fixed;
}

div.red {
  background:red;
  transform:translate(-50px, -50px);
}
<div></div>
<div class="red"></div>


如果你想保留它,你必须使用 JavaScript 到 运行 计算动态高度,否则,你可以使用 vertical-align: middle [=139] 垂直对齐项目=],parent 设置为 table-cell,即 display: table 的 child。因此,例如,如果您知道确切的最高值,它将起作用:

.wrapper {
  min-height: 100px;
  width: 48%;
  border: 1px dashed #666;
  position: relative;
  top:50px;
  float:left;
}

.center {
  border: 1px solid red;
  width:100px;
  height:150px;
}

.transform .center {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}

/* table wrapper */

.wrapper.table {
  float:right;
  display: table;
}

.table .center {
  display: table-cell;
  vertical-align:middle;
}
<div class="wrapper transform">
  <div class="center">
    <h4>I am pushed off screen!?</h4>
  </div>
</div>

<div class="wrapper table">
  <div class="center">
    <h4>I'm smarter.</h4>
  </div>
</div>


编辑:Flexbox 解决方案

除了老派 table 解决方案外,您还可以使用现代方法:Flexbox。

.flexbox {
  border:1px dashed #666;
  display: flex;
  justify-content: center; /* horizontal centering */
  align-items: center; /* vertical centering */
  flex-direction: column; /* makes sure children are under each other */
  min-height:200px;
}

.flexbox * {
  border:1px solid red;
}

.flexbox p {
  height:300px;
}
<div class="flexbox">
    <h4>Flexbox Magic</h4>
    <p>The center of attention!</p>
</div>

flex 容器基于其 children 进行扩展,因此它是一个非常巧妙的动态解决方案。

Flexbox 支持:Can I Use: Flexbox