如何按顺序应用CSS更改



我有时会遇到这样的情况:我想要立即连续地对CSS应用几个更改,确保每个更改都被渲染器注册。

下面是一个简化的例子

元素的高度是auto,所以它不能从。因此,我希望将元素高度设置为当前计算的高度,然后立即更改类以开始过渡。如果在下一行代码中发生这种情况,则css-renderer没有时间对第一次更改做出反应,并且好像只有类被更改了->没有转换。

var foo = $(".foo");
foo[0].addEventListener("click", function(ev){
  foo.css({"height":foo.height()+"px"});
  foo.addClass("active");
});  //this doesn't work, foo.css…' is ignored.

我们可以用window.requestAnimationFrame()延迟到最小的可动画时间步,然而,由于浏览器的差异,这些已经需要两个嵌套调用来支持Firefox。

var dan = $(".dan");
dan[0].addEventListener("click", function(ev){
  window.requestAnimationFrame(function(){
    dan.css({"height":dan.height()+"px"});
    window.requestAnimationFrame(function(){
      dan.addClass("active");
    });
  });
});  //this does work (afai can tell), but feels overdone with all that nesting.

从技术上讲,这段代码是有效的。我只是想知道这是否真的是最好的方式来链接css更改像这样或者是否有其他方法。

您可以在这里使用setTimeout以确保在计算divheight之后总是发生类更改。

例子:

var foo = document.getElementsByClassName('foo')[0];
var bar = document.getElementsByClassName('bar')[0];
var dan = document.getElementsByClassName('dan')[0];
function fooFunction(element) {
    element.style.height = element.clientHeight + 'px';
    setTimeout(function(){
        element.classList.add('active');
        element.removeAttribute('style');
    },10);
}
foo.addEventListener('click',function(){fooFunction(foo);},false);
bar.addEventListener('click',function(){fooFunction(bar);},false);
dan.addEventListener('click',function(){fooFunction(dan);},false);
.foo, .bar, .dan{
width:20%;
display: inline-block;
overflow: hidden;
vertical-align:top;
transition: height 1s ease-out;
}
.active {
height:50px;
}
.foo {
background:rgb(150, 100, 100);
}
.bar {
background:rgb(150, 150, 100);
}
.dan {
background:rgb(100, 150, 100);
}
<div class="foo">
<p>Works.</p>
<p>Another paragraph.</p>
<p>Third paragraph. This one is even longer. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quibusdam, fugiat facere? Animi, odit et tempore debitis modi quae eaque, libero, dolores magni, voluptas tenetur tempora quidem alias ut praesentium sed.</p>
</div>
<div class="bar">
<p>Works.</p>
<p>Another paragraph.</p>
<p>Third paragraph. This one is even longer. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quibusdam, fugiat facere? Animi, odit et tempore debitis modi quae eaque, libero, dolores magni, voluptas tenetur tempora quidem alias ut praesentium sed.</p>
<p>Fourth paragraph. This one is even longer. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quibusdam, fugiat facere? Animi, odit et tempore debitis modi quae eaque, libero, dolores magni, voluptas tenetur tempora quidem alias ut praesentium sed.</p>
</div>
<div class="dan">
<p>Works.</p>
<p>Another paragraph.</p>
<p>Third paragraph. This one is even longer. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quibusdam, fugiat facere? Animi, odit et tempore debitis modi quae eaque, libero, dolores magni, voluptas tenetur tempora quidem alias ut praesentium sed.</p>
<p>Fourth paragraph. This one is even longer. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quibusdam, fugiat facere? Animi, odit et tempore debitis modi quae eaque, libero, dolores magni, voluptas tenetur tempora quidem alias ut praesentium sed.</p>
<p>Fifth paragraph. This one is even longer. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quibusdam, fugiat facere? Animi, odit et tempore debitis modi quae eaque, libero, dolores magni, voluptas tenetur tempora quidem alias ut praesentium sed.</p>
</div>

如果在click事件之前不知道目标元素的高度,只需在DOM准备好后检查它,并将每个目标元素设置为它自己的高度。这样,当你点击一个目标元素时:动画将工作,因为元素的高度已经设置。*点击事件将会少执行一个命令。

如果你已经在使用jQuery,你可以一直使用它:

$(document).ready(function(){ // use document ready so we can get the target elements height after they finished to load. 
    var $tran = $('.transition'); // get "transition" class. instead of using different class name for each element, i use unique class for the animation part, the change needs to be on the HTML and CSS too of course, you will see it in the example. 
    $tran.each(function(){ // run each loop so we can get each of the elements that have the class "transition", this is important when the elements height different from each other.
        var height = $(this).height(); // get the height of the current element in the loop. 
        $(this).height(height); // set the height of the current element in the loop. 
    });
    $tran.click(function(){ // set jQuery click event
        $(this).addClass('active'); // add the "active" class
    });
});

香草:

document.addEventListener('DOMContentLoaded', function(){ // use DOMContentLoaded so we can get the target elements height after they finished to load.
  var tran = document.getElementsByClassName('transition'); // get "transition" class.
  for ( let i = 0; i <= tran.length-1; i++ ){ // run for loop so we can get each of the elements that have the class "transition", this is important when the elements height different from each other.
    let height = tran[i].clientHeight; // get the height of the current element in the loop. 
    tran[i].style.height = height + 'px'; // set the height of the current element in the loop. 
    tran[i].addEventListener("click", function(ev){ // set click event
      this.className = this.className + " active"; // add the "active" class 
    });
  }
});

每个目标元素都有一个过渡类:

<div class="foo transition">
...
<div class="bar transition">
...  
<div class="dan transition">
... 

过渡部分移动到它自己的类中,所以如果你决定删除它或将它用于其他元素,你可以稍后从HTML中删除该类。它不再在"活动"类上了所以它影响的元素没有连接到点击事件,这样你可以用toggleClass()代替addClass(),当你再次点击元素时,你会得到一个"打开"动画:

.foo, .bar, .dan {
  width: 20%;
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
}
.transition {
  -webkit-transition: height 1000ms;
  transition: height 1000ms;
}
.active {
  height: 50px !important;
}

生活的例子:https://jsfiddle.net/84joouov/*在这个例子中,我让你通过设置"use_jquery"变量为真或假来选择使用纯JS还是jQuery。

相关内容

  • 没有找到相关文章

最新更新