如何使用transform:translateX在父级上水平移动子元素100%

mat*_*ler 32 html5 css3 css-transitions css-transforms

所有,

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

挑战在于百分比是translateX指元素本身,而不是父母.

所以,例如,如果我的html看起来像这样:

<div id="parent">
    <div id="child">
</div>
Run Code Online (Sandbox Code Playgroud)

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

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

这不起作用 - 孩子只移动20px(自身的100%),而不是整个父移动.(你可以在jsfiddle上看到这个):

在此输入图像描述

我可以做这个:

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

这工作(在jsfiddle上再次看到 ),因为它首先移动子300px(父的全宽),减去20px(子的宽度).然而,这取决于具有固定的已知像素尺寸的父母.

在此输入图像描述

但是,在我的响应式设计中 - 我不知道父级的宽度,它会改变.

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

有没有办法做到这一点?

提前致谢.

val*_*als 28

我最初没有发表我的想法,因为它涉及创建一个额外的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%);
}
Run Code Online (Sandbox Code Playgroud)

由于包装器是父级的100%宽度,因此将其100%翻译按预期工作.

小提琴

请注意,正如您所说,包装器正在翻译100%.但是,看起来你真正想要的是将元素移动100% - 宽度.要实现这一点,您必须在相反的方向上将子项100%(现在这适用于子宽度)进行翻译.

更正:子应该共享包装器的transition属性:

#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%);
}
Run Code Online (Sandbox Code Playgroud)
<div id="parent">
    <div id="wrapper">
        <div id="child"></div>
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)


小智 11

使用Flexbox有一个非常酷的解决方案.关键是要利用flex-grow属性.

假设你有一些看起来像这样的HTML:

<div class="flex-container">
  <div class="flex-spacer"></div>
  <div class="slider"></div>
</div>
Run Code Online (Sandbox Code Playgroud)

首先,为.flex-container提供基本显示: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;
}
Run Code Online (Sandbox Code Playgroud)
<div class="flex-container">
  <div class="flex-spacer"></div>
  <div class="slider"></div>
</div>
Run Code Online (Sandbox Code Playgroud)

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

随意用这支钢笔玩它.

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

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

  • 这样做的问题是它会触发油漆闪烁,所以它不是很平滑/高效。 (3认同)

Squ*_*cle 5

随着最近添加的“大小容器查询”,现在可以通过在父元素中设置属性container-typeinline-size然后将子元素平移 100cqw - 100% 来实现此目的,其中 100cqw 是父元素的全宽度,100% 是父元素的宽度。孩子。

#parent {
    position: relative;
    width: 300px;
    height: 100px;
    background-color: black;
    
    container-type: inline-size;
}
#child {
    position: absolute;
    width: 20px;
    height: 100px;
    background-color:red;
    transform: translateX(calc(100cqw - 100%));
}
Run Code Online (Sandbox Code Playgroud)
<div id="parent">
    <div id="child">
</div>
Run Code Online (Sandbox Code Playgroud)