有没有办法在弹性盒项目的顺序上进行过渡?
换句话说,我可以拥有这个(这个小提琴中的细节)
#container {
display: flex;
}
#container:hover div:last-child {
order: -1;
}
动画(获得新位置的元素会随着时间的推移假设它的位置),请问?
我并没有真正回答这个问题,因为我没有使用 order 属性。
但我想做一些类似于你所期望的事情,最终决定:
- 在 HTML 中,向元素添加
data-order
属性 - 为每个元素位置添加 CSS 属性
- 使用 Javascript 更改
data-order
- 使用 CSS 过渡进行插值
setInterval(changeOrder, 3000);
function changeOrder() {
const allSlides = document.querySelectorAll(".single-slide");
const previous = "1";
const current = "2";
const next = "3";
for (const slide of allSlides) {
const order = slide.getAttribute("data-order");
switch (order) {
case current:
slide.setAttribute("data-order", previous);
break;
case next:
slide.setAttribute("data-order", current);
break;
case previous:
slide.setAttribute("data-order", next);
break;
}
}
}
.all-slides {
display: flex;
width: 80vw;
margin: 0 auto;
perspective: 500px;
height: 500px;
}
.single-slide {
padding: 30px 20px;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
width: 30%;
position: absolute;
background-color: white;
transition: 2s ease;
box-shadow: 0px 5px 10px lightgrey;
}
/* Left slide*/
.single-slide[data-order="1"] {
left: 10vw;
transform: translate(-50%) scale(0.8, 0.8);
z-index: 1;
opacity: 0.7;
}
/* Middle slide */
.single-slide[data-order="2"] {
left: 40vw;
transform: translate(-50%);
z-index: 3;
opacity: 1;
}
/* Right slide*/
.single-slide[data-order="3"] {
left: 90vw;
transform: translate(-120%) scale(0.8, 0.8);
z-index: 2;
opacity: 0.7;
}
.single-slide:nth-child(2) {
order: 3;
}
.single-slide:nth-child(1) {
order: 2;
}
.single-slide:nth-child(3) {
order: 1;
}
<div class="all-slides">
<div class="single-slide" data-order="2">
<h3>First slide </h3>
<p>Some text</p>
</div>
<div class="single-slide" data-order="3">
<h3>Second slide</h3>
<p>Some other text</p>
</div>
<div class="single-slide" data-order="1">
<h3>Third slide</h3>
<p>Yet some other text</p>
</div>
</div>
如果要对滑块(或其他任何内容)进行动画处理,但出于辅助功能目的,希望保留 HTML 中元素的顺序,这可能是 order 属性的有用用法之一,这可能很有用。见 https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Ordering_Flex_Items#The_order_property_and_accessibility
可悲的是没有:order 属性是可动画的,但只能作为整数。这意味着对于动画的每个步骤/帧,它将按地板将值插入到近东整数。因此,项目只会显示在计算的整数值产生的插槽中,永远不会以任何平滑的运动方式介于两者之间。
从技术上讲,它仍然是一个动画:计算出的整数位置仍应遵循动画的计时函数和关键帧规则,只是项目在变化时从一个位置"跳"到另一个位置。
见 https://developer.mozilla.org/en-US/docs/Web/CSS/integer#Interpolation
现在已经很老了,但我最近用这个小提琴(改编自Jason在评论中发布的小提琴)测试了这个问题:http://jsfiddle.net/aqrxcd1u/(下面的代码)。
在Chrome和Firefox中,这都是部分动画,因为顺序一次从当前值过渡到目标值。这意味着它不是从 5->1 开始,而是从 5->4->3->2->1 开始。
在桌面 Safari 中,它仍然直接进入 5->1。
#container {
display: flex;
}
#container div {
width: 100px;
height: 100px;
margin-right: 10px;
background-color: red;
}
#container div:nth-child(even) {
background-color: blue;
}
}
#container div:last-child {
order: 5;
transition: order 1s;
}
#container:hover div:last-child {
order: -1 !important;
}
<div id="container">
<div style="order: 1">Element 1A</div>
<div style="order: 2">Element 2B</div>
<div style="order: 3">Element 3C</div>
<div style="order: 4">Element 4D</div>
<div style="order: 5">Element 5E</div>
</div>
- Jon z 建议可以通过内联样式设置变量;
- 我们知道变形是一个动画效果很好的道具;
- 我们知道我们有
calc()
;
所以这是我基于上述内容创建的内容:
// Some simple logic that will "change the order of elements"
function shuffleThem() {
var items = [...document.getElementsByClassName('item')];
items.sort(() => Math.random() < 0.5 ? -1 : 1);
items.forEach((item, index) => {
item.style.setProperty('--order', index);
})
}
.container {
position: relative;
}
.placeholder {
/*
A .placeholder will push the .container's height
while its .item is absolutely positioned inside.
*/
background: red;
width: 10rem;
height: 3rem;
}
.item {
/*
All items are initially rendered at the top of the .container
and are later transformed/translated to their ordered positions.
*/
position: absolute;
top: 0;
width: 10rem;
height: 3rem;
transition: transform 0.5s ease;
transform: translateY(calc(var(--order) * 100%));
text-align: center;
line-height: 3rem;
}
<button onclick="shuffleThem()">Shufle 🔀</button>
<br /><hr /><br />
<p>Content before the .container</p>
<div class="container">
<div class="placeholder"></div>
<div class="placeholder"></div>
<div class="placeholder"></div>
<div class="placeholder"></div>
<div class="placeholder"></div>
<div class="item" style="--order: 0; background: #FFBE66">A</div>
<div class="item" style="--order: 1; background: #66FF9F">B</div>
<div class="item" style="--order: 2; background: #FFFFFF">C</div>
<div class="item" style="--order: 3; background: #FF8166">D</div>
<div class="item" style="--order: 4; background: #70C1FF">E</div>
</div>
<p>Content after the .container</p>
并不是说它适合所有情况,但它确实适合我的情况。
- 此方法的一个主要要求是知道(或确定)项目的高度,以便可以为它们提供占位符。
- 该方法的一个主要缺陷是您无法使用弹性框的包装功能。您要么垂直(如示例中所示)重新排序,要么水平重新排序。
这与CodePen相同。
正如埃米尔所说,它只动画为整数。但是,我正在考虑一个黑客:
- 将要显示的元素放在具有 1/10
height
的包装器中,设置包装器overflow: visible
- 然后在这些包装器之间放置 9 个间距元素,具有相同的
height
。 - 把
order
和transition
放在所有这些上。 - 更改包装器的
order
并观察其"过渡"。
可悲的是,它很丑陋,只能在Firefox中使用。这是我在 Angular 中测试的内容