我有一个垂直的项目堆栈,用户可以通过点击一个按钮来附加一个项目,大致是这样的。
<ol>
<li><textarea></textarea></li>
<li><textarea></textarea></li>
</ol>
<a data-action="additem">Add another</a>
我正在尝试编写一个CSS动画,以便在插入新的li
时,“添加另一个”可以平滑地滑动到新的休息位置。 li
标签上的固定高度不是一个选项,我试图避免使用max-height
动画黑客,因为它可能有奇怪的布局效果。
我发现我可以将{em> 中的margin-bottom
动画设为0并获得所需的效果,但我无法弄清楚如何在CSS中表达我想要的当前高度应用此规则的元素的大小。百分比是相对于元素的 width 测量的,这不是我在这里需要的,我想不出一个聪明的技巧,使用calc
或类似来表达我的意思想要浏览器。
建议?
修改
我正在使用带有重复绑定的模板将项目添加到列表中。 JS只将另一个对象推送到一个可观察的数组中,框架处理实际的DOM插入。 li
标记上有以下CSS以使其顺利进入:
animation: append forwards .5s;
append
定义为:
@keyframes append {
from {
transform: translateX(10%);
opacity: 0;
margin-bottom: _____;
}
to {
transform: none;
opacity: 1;
margin-bottom: 0;
}
}
答案 0 :(得分:4)
我多次遇到这个令人沮丧的问题,总是尝试为非数字值设置动画,将当前元素的特定属性作为动画值访问,或者将未指定的值设置为指定的值。一般来说,我总是要回到某种形式的不太完美的max-height
动画(就像你已经提到的那样)或者混合使用CSS和JavaScript / jQuery。
对于您的问题,有一些选项,但没有一个是您正在追求的。
bottom
和position:relative
translateY
经常用于CSS-hack的一个技巧是复制标记 - 在这个例子中,链接自己 - 并将其放在将通过不同方式打开或关闭的父包装器中。这种方法的缺点是你会得到一个相当难看的标记,并且在这个特定的例子中,一个子弹数字看起来很不稳定(因为必须将不透明度动画从li
移动到textarea
)
此方法的好处是,通过移动li
内的链接,您可以使用翻译或其他偏移方法在y轴上使用-100%
。奇怪的是,虽然我无法解决translateY(-100%)
基于... 计算的内容,但它似乎不是父高,也许它本身就是高度。出于这个原因,我已经更新了小提琴以使用 bottom
和相对定位,尽管在Firefox(在Mac上)这个故障很短暂。
似乎translateY
是根据它自己的高度来计算百分比,所以为了解决这个问题我必须使用绝对位置并强制链接层假设与li
相同的维度...令人讨厌,因为它涉及对链接上方的textarea
进行z索引,并使用内部span
来偏移链接文本,但至少它确实有效
以下代码适用于最新的Firefox,并且如果所有不同的浏览器前缀都被正确用于定义动画关键帧,则可以在其他现代浏览器中使用,但我现在没有时间将它们全部设置。
<强>标记:强>
<ol class="list">
<li><textarea></textarea><a class="add" href="#"><span>Add another</span></a></li>
<li><textarea></textarea><a class="add" href="#"><span>Add another</span></a></li>
</ol>
<强>的CSS:强>
ol li {
position: relative;
}
ol li .add {
display: none;
}
ol li:last-child .add {
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
width: 100%;
height: 100%;
display: block;
animation-duration: 1s;
animation-name: slide;
}
ol li:last-child .add span {
position: absolute;
bottom: -20px;
}
.list li textarea {
position: relative;
animation-duration: 1s;
animation-name: append;
z-index: 1;
}
@keyframes append {
from {
transform: translateX(10%);
opacity: 0;
}
to {
transform: none;
opacity: 1;
}
}
@keyframes slide {
from {
transform: translateY(-100%);
}
to {
transform: none;
}
}
以下显然没有考虑到您使用模板引擎为DOM操作提供动力这一事实,但所有代码需要正常工作的是列表的前后高度(以计算差异) height),以及在添加新列表项的位置触发的事件。
可悲的是,现在还不可能在纯CSS中完成这一切,至少在我看到的情况下,或许calc
已经升级了......?或者,如果引入某种方式来引用当前元素维度,而不仅仅是它的偏移父级。
应该注意的是,我没有使用Internet Explorer来测试它,但所有其他现代浏览器似乎都很高兴。
<强>标记:强>
<ol class="list">
<li><textarea></textarea></li>
<li><textarea></textarea></li>
</ol>
<div class="add">
<a href="#">Add another</a>
</div>
javascript(使用jQuery):
function prefix(){
for ( var a = ['Webkit','Moz','O','ms'], i=0, l = a.length; i<l; i++ ) {
if ( document.body.style[a[i]+'AnimationName'] !== undefined ) {
return { js: a[i], css: '-' + a[i].toLowerCase() + '-' };
}
}
return { css:'', js:'' };
}
$(function(){
$('.add a').click(function(e){
e.preventDefault();
var pref = prefix(),
link = $(this).parent(),
list = $('.list'),
lihi = list.height(),
liad = $('<li><textarea></textarea></li>').appendTo(list),
lihd = lihi - list.height();
link.css(pref.css + 'transform', 'translateY(' + lihd + 'px)');
setTimeout(function(){link.addClass('translate-zero transition-all');},0);
setTimeout(function(){
link.css(pref.css + 'transform', '');
link.removeClass('translate-zero transition-all');
},500);
});
});
<强>的CSS:强>
.transition-all {
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
-ms-transition: all 0.5s;
-o-transition: all 0.5s;
transition: all 0.5s;
}
.translate-zero {
-webkit-transform: translateY(0) !important;
-moz-transform: translateY(0) !important;
-ms-transform: translateY(0) !important;
-o-transform: translateY(0) !important;
transform: translateY(0) !important;
}
.list li {
animation-duration: 1s;
animation-name: append;
}
@keyframes append {
from {
transform: translateX(10%);
opacity: 0;
}
to {
transform: none;
opacity: 1;
}
}
我曾多次遇到类似问题,但发现重新设计有助于解决问题,并且通常可以提高实用性。在你的情况下,最好将“添加链接”放在列表上方(或右上角),或者将按钮集成为某个地方的浮动图标......无论你把它放在哪里,最好试着保留它在静态位置,移动交互点可能会让用户烦恼,特别是如果他们希望快速连续添加多个项目。
答案 1 :(得分:-1)
我能想到的最简单的解决方案就是这个。
添加新的li元素时,只需将其附加到dom。
liMarkup = '<li><textarea></textarea></li>'
$('ol').append(liMarkup);
$('ol').find('li').last().css('display','none');
$('ol').find('li').last().show('fast');
这可以按照你的要求工作:)我希望它有所帮助。
工作Jsfiddle
编辑:在JS中使用它很容易,也更好。