当我从flexbox中删除某个项目时,其余项目会立即“捕捉”到新位置而不是动画。
从概念上讲,由于项目正在改变其位置,我希望过渡适用。
我在所有涉及的元素(flexbox和子元素)上设置了过渡属性
有没有办法动画编辑(添加和删除)到flexbox?这对我来说实际上是一个showstopper,而且是flexbox的一个缺失部分。
答案 0 :(得分:22)
我根据Treehouse的这个例子修复了@ skyline3000的演示。如果浏览器发生变化,不确定这是否会再次中断,但这似乎是设置弹性尺寸变化动画的预期方式:
我也使用了jQuery,但技术上并不是必需的。
.flexed {
background: grey;
/* The border seems to cause drawing artifacts on transition. Probably a browser bug. */
/* border: 1px solid black; */
margin: 5px;
height: 100px;
flex-grow: 1;
transition: flex-grow 1000ms linear;
}
.removed {
/* Setting this to zero breaks the transition */
flex-grow: 0.00001;
}
关于CSS的一点需要注意的是你不能过渡到零flex-grow
,它不会过渡它会消失。你只需要一个非常小的值。在绘制边框时似乎还有一个伪影错误,所以我在这种情况下使用了背景。
答案 1 :(得分:11)
请记住,灵活盒模型和网格布局规范会不断变化,甚至是属性和有效值。浏览器的实现还远未完成。话虽如此,您可以在flex
属性上进行转换,以便元素平滑过渡,然后只需监听TransitionEnd
以最终从DOM树中删除该节点。
以下是在Chrome 21中运行的JSFiddle示例:http://jsfiddle.net/5kJjM/(点击中间div)
var node = document.querySelector('#remove-me');
node.addEventListener('click', function(evt) {
this.classList.add('clicked');
}, false);
node.addEventListener('webkitTransitionEnd', function(evt) {
document.querySelector('#flexbox').removeChild(this);
}, false);
#flexbox {
display: -webkit-flex;
-webkit-flex-flow: row;
}
.flexed {
border: 1px solid black;
height: 100px;
-webkit-flex: 1 0 auto;
-webkit-transition: -webkit-flex 250ms linear;
}
.clicked {
-webkit-flex: 0 0 auto;
}
<div id="flexbox">
<div class="flexed"></div>
<div class="flexed" id="remove-me"></div>
<div class="flexed"></div>
</div>
修改强>: 为了进一步说明,删除节点时,应将其flex设置为0,然后将其从DOM中删除。添加节点时,使用flex:0添加它,然后将其转换为flex:1
答案 2 :(得分:2)
对@ skyline3000和@ chris-nicola的解决方案的另一种改编:http://jsfiddle.net/2gbPg/2/
您可以简单地为max-width
(或视情况而定max-height
)进行动画处理,在删除时动画化为0
,在插入时动画化为100%
。
答案 3 :(得分:1)
我不小心让它以简单的方式工作。
基本上,您设置了width:0;flex-grow:1
,当然还要添加transition:all 2s;
,就是这样。这是一个好奇的黑客。
答案 4 :(得分:0)
我已经完成了一个Codepen,当您删除元素时,它会为这些元素设置动画,看看: https://codepen.io/MauriciAbad/pen/eQoQbK
可以优化,但是可以。 ; D
<div class="container">
<div id="0"></div>
<div id="1"></div>
... more divs ...
</div>
.container{
display: flex;
flex-wrap: wrap;
}
.container > div{
flex-grow: 1;
transform-origin: left top;
}
var cards = document.querySelectorAll('.container > div');
cards.forEach((card) => {
card.addEventListener('click', () => {removeCard(card);});
});
var cardsOldInfo = //example content
{"cardId": {
"x": 100,
"y": 200,
"width": 100
}
};
var cardsNewInfo = cardsOldInfo;
function removeCard(card){
cardsOldInfo = getCardsInfo();
card.parentNode.removeChild(card);
cardsNewInfo = getCardsInfo();
moveCards();
}
function getCardsInfo(){
updateCards();
let cardsInfo = {};
cards.forEach((card) => {
var rect = card.getBoundingClientRect();
cardsInfo[card.id] = {
"x": rect.left,
"y": rect.top,
"width": (rect.right - rect.left)
};
});
return cardsInfo;
}
function moveCards(){
updateCards();
cards.forEach((card) => {
card.animate([
{
transform: `translate(${cardsOldInfo[card.id].x - cardsNewInfo[card.id].x}px, ${cardsOldInfo[card.id].y -cardsNewInfo[card.id].y}px) scaleX(${cardsOldInfo[card.id].width/cardsNewInfo[card.id].width})`
},
{
transform: 'none'
}
], {
duration: 250,
easing: 'ease-out'
});
});
}
function updateCards(){
cards = document.querySelectorAll('.container > div');
}
答案 5 :(得分:0)
我一直试图为flexbox中的行设置动画。仅通过CSS不可能做到这一点。因此,我使用了一些JavaScript并为我的flexbox行添加了一个额外的父级。
HTML:
<div class="outer-container">
<div class="inner-container">
<div class="row">Row number 1</div>
</div>
</div>
<button id="add">Add one more item</button>
CSS:
.row{
height : 40px;
width : 200px;
border: 1px solid #cecece;
text-align : center;
padding-top : 20px;
}
.outer-container {
height : 500px;
border : 1px solid blue;
width : 250px;
display: flex;
justify-content : center;
align-items: center;
}
.inner-container {
height : 42px;
transition : height 0.3s;
}
button {
width : 200px;
height: 30px;
margin-left : 80px;
margin-top : 10px;
}
JavaScript:
(() => {
let count = 1;
document.querySelector("#add").addEventListener('click', () => {
const template = document.createElement('div');
count += 1;
template.textContent = `Row number ${count}`;
template.className = 'row';
const innerContainer = document.querySelector('.inner-container');
innerContainer.appendChild(template);
innerContainer.style.height = `${innerContainer.clientHeight + 42}px`;
})
})();