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

时间:2014-02-04 16:09:33

标签: html5 css3 css-transitions css-transforms

所有

我希望能够使用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)上看到这一点:

enter image description here

我可以这样做:

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

这有效(见here again on jsfiddle),因为它首先移动子300px(父级的全宽),减去20px(子级的宽度)。但是,这取决于具有固定的已知像素尺寸的父级。

enter image description here

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

我知道我可以使用left:0right:0,但左/右的动画效果要比translateX(Thanks Paul Irish!)差。

有办法做到这一点吗?

提前致谢。

3 个答案:

答案 0 :(得分:27)

我最初没有发表我的想法,因为它涉及创建一个额外的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%翻译按预期工作。

fiddle

请注意,正如您所述,包装器正在翻译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%);
}
<div id="parent">
    <div id="wrapper">
        <div id="child"></div>
    </div>
</div>

答案 1 :(得分:8)

使用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上将 flex-grow 设置为 1 -spacer在某些事件中。第二个规则将.flex-container中的所有未使用的 width 提供给.flex-spacer的 width ,第一个规则为宽度的变化设置动画。 .slider元素被推送到.flex-container的边缘。

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

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 ,我们就完成了!

随意在此pen中播放。

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

这是另一个pen,这次是在带输入的表单的上下文中。

答案 2 :(得分:3)

如果您使用包装器解决方案(如用户面包车&#39;方法),我更喜欢引用1%而不是父宽度的100%,并将翻译后的值乘以100.这样可以避免可点击项目出现问题在子元素旁边。

例如,如果要将子元素转换为父元素的中心:

#wrapper {
  position: absolute;
  left: 0;
  top: 0;

  width: 1%;
  overflow: visible;

  transform: translateX(5000%);
}

#child {
  transform: translateX(-50%);
}

HTML

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

    </div>
  </div>
  <a onclick="alert('im still clickable')">
    click me
  </a>
</div>

http://codepen.io/anon/pen/BLxYXO