所有
我希望能够使用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%);
}
这有效(见here again on jsfiddle),因为它首先移动子300px(父级的全宽),减去20px(子级的宽度)。但是,这取决于具有固定的已知像素尺寸的父级。
然而,在我的响应式设计中 - 我不知道父级的宽度,它会改变。
我知道我可以使用left:0
和right:0
,但左/右的动画效果要比translateX(Thanks Paul Irish!)差。
有办法做到这一点吗?
提前致谢。
答案 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%翻译按预期工作。
请注意,正如您所述,包装器正在翻译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>