如何使用 transform:translateX 将子元素水平移动 100% 穿过父元素

新手上路,请多包涵

全部,

我希望能够使用 translateX 为子元素设置 100% 的动画(即从左边缘到右边缘)。

挑战在于 translateX 中的百分比指的是元素本身,而不是父元素。

因此,例如,如果我的 html 如下所示:

 <div id="parent">
    <div id="child">
</div>

我的 CSS 是这样的(省略了供应商前缀):

 #parent {
    position: relative;
    width: 300px;
    height: 100px;
    background-color: black;
}
#child {
    position: absolute;
    width: 20px;
    height: 100px;
    background-color:red;
    transform: translateX(100%);
}

这是行不通的——孩子只移动 20px(100% 自身),而不是一直穿过父级。 (你可以在 jsfiddle 上看到这个):

在此处输入图像描述

我可以做这个:

 #child {
    position: absolute;
    width: 20px;
    height: 100px;
    background-color:red;
    -webkit-transform: translateX(300px) translateX(-100%);
    transform: translateX(300px) translateX(-100%);
}

这行得通( 在 jsfiddle 上再次看到这里),因为它首先将子项移动 300px(父项的全宽),减去 20px(子项的宽度)。但是,这取决于具有固定的已知像素尺寸的父级。

在此处输入图像描述

然而,在我的响应式设计中——我不知道父级的宽度,它会改变。

我知道我可以使用 left:0right:0 ,但是左/右的动画性能比 translateX 差得多( 感谢 Paul Irish! )。

有没有办法做到这一点?

提前致谢。

原文由 mattstuehler 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.7k
2 个回答

我最初没有发布我的想法,因为它涉及创建一个额外的 HTML 层,并期待更好的解决方案。

由于这还没有发生,我解释一下我的评论。我的意思是:

 #parent {
    position: relative;
    width: 300px;
    height: 100px;
    background-color: black;
}
#wrapper {
    position: absolute;
    width: 100%;
    height: 100px;
    border: solid 1px green;
    transition: all 1s;
}
#wrapper:hover {
    -webkit-transform: translateX(100%);
    transform: translateX(100%);
}
#child {
    position: absolute;
    width: 20px;
    height: 100px;
    background-color:red;
}
#wrapper:hover #child {
    -webkit-transform: translateX(-100%);
    transform: translateX(-100%);
}

由于包装器是父级的 100% 宽度,因此将其转换为 100% 会按预期工作。

小提琴

请注意,正如您所说,包装器正在 100% 翻译。但是,似乎您真正想要的是将元素移动 100% - 宽度。为实现这一点,您必须将孩子也 100% 平移到相反方向(现在这适用于孩子的宽度)。

更正:孩子应该共享包装器的过渡属性:

 #parent {
    position: relative;
    width: 300px;
    height: 100px;
    background-color: black;
}
#wrapper {
    position: absolute;
    width: 100%;
    height: 100px;
    border: solid 1px green;
    transition: all 5s;
}
#wrapper:hover {
    transform: translateX(100%);
}
#child {
    position: absolute;
    width: 50px;
    height: 100px;
    background-color:red;
    transition: inherit;
}
#wrapper:hover #child {
    transform: translateX(-100%);
}

 <div id="parent">
    <div id="wrapper">
        <div id="child"></div>
    </div>
</div>

原文由 vals 发布,翻译遵循 CC BY-SA 3.0 许可协议

使用 Flexbox 可以很好地解决这个问题。关键是要利用 flex-grow 属性。

假设您有一些如下所示的 HTML:

 <div class="flex-container">
  <div class="flex-spacer"></div>
  <div class="slider"></div>
</div>

首先,给 .flex-container 基本的 display: flex 属性,并将其 flex-direction 设置为 row 。将子元素的定位设置为 relative ,这样它们就会在 .flex-container 中并排放置。

默认情况下, flex-grow 属性设置为 0 ,这正是我们一开始想要的。这意味着 .flex-spacer 和 .slider 将只有它们的正常尺寸开始。我们只需将 .flex-spacer 保持为空,它的 宽度 将为 0

现在为动画。我们只需要两个 CSS 规则就可以让它工作:在某些事件期间向 .flex-spacer 添加 过渡 并在 .flex-spacer 上将 flex-grow 设置为 1 。第二条规则将 .flex-container 中所有未使用的 宽度 赋予 .flex-spacer 的 _宽度_,第一条规则为宽度的变化设置动画。 .slider 元素被推到 .flex-container 的边缘。

CSS 看起来像这样——我为 .flex-spacer 添加了一个背景以使其更加明显,并在用户将鼠标悬停在 .flex-container 上时将 flex-grow 设置为 1

 body * {
  box-sizing: border-box;
}

.flex-container {
  cursor: pointer;
  display: flex;
  flex-flow: row nowrap;
  width: 100%;
  border: 2px solid #444;
  border-radius: 3px;
}

.flex-spacer,
.slider {
  flex-grow: 0;
  position: relative;
}

.slider {
  padding: 25px;
  background-color: #0DD;
}

.flex-spacer {
  background-color: #DDD;
  transition: all .4s ease-out;
}

.flex-container:hover .flex-spacer {
  flex-grow: 1;
}
 <div class="flex-container">
  <div class="flex-spacer"></div>
  <div class="slider"></div>
</div>

Flexbox 也使它变得非常可配置。例如,假设我们希望 .slider 从右向左移动。我们所要做的就是将 .flex-container 中的 flex-direction 属性切换为 row-reverse ,我们就完成了!

在这支 中尽情发挥吧。

请记住,如果我们想要为不同类型的事件制作动画,事情会变得有点棘手。例如,我在尝试在用户输入输入元素时为标签设置动画时遇到了这个问题。需要更多的 HTML 和 CSS 才能使其工作(我也使用了一些 JS),但概念是相同的。

这是另一 支笔,这次是在带有输入的表单的上下文中。

原文由 Brady Lambert 发布,翻译遵循 CC BY-SA 3.0 许可协议

推荐问题