内容loading加载后高度变化CSS3 transition体验优化

这篇文章发布于 2015年01月22日,星期四,15:45,归类于 JS实例。 阅读 80778 次, 今日 9 次 35 条评论

 

一、小美,你好

小美

此“小美”非东四街的小美,而是“小而美研究”的简称,实用小技巧,分分钟Get, 积累足够多,量变到质变。

本文应该就属于这个范畴,提炼的成果就是十来行代码。

现在web技术不断发展,视图与数据渲染更多由前端呈现,后台更多与数据打交道。于是,我们会经常看到这样的交互场景。页面加载,看到一个框框里面有个菊花在转,然后内容呈现;或者点击个按钮,菊花在转,然后列表动态加载呈现。例如:
loading正在加载

是不是没有任何问题?确实,功能上OK,有菊花,用户也愿意等。但是,大家有没有觉得所有交互,出现菊花→出现内容,都是“砰砰砰”很生硬的感觉,尤其当内容是动态,高度不确定的时候。我们使用一些比较好的手机APP(如微信)的时候一定不会有这样的感觉,整个交互流程都是很流畅的,就像山涧的泉水,涓涓细流到山脚,而不是巨人在峡谷走路的感觉。

所以,如果菊花的呈现到内容的展示能够通过自然的动画过渡呈现,势必会增强用户体验。

而动态内容呈现主要变化的关键因素就是——高度,而过渡效果最佳利器是CSS3 transition, 于是,脑中不禁疑问,是不是可以借助CSS3 transition实现动态内容的高度动画呈现,渐进增强用户体验。

其实,早在12年的时候,我就开始了这方面的尝试,若有兴趣可以查看此文:“更多|收起交互中渐进使用transition动画”。我自己也瞅了瞅,发现当年的我讲废话的本领甩了现在的我两条长安街。大家直接从Part5 看就好了。 其中,受限于当年略显稚嫩的技术,里面获得容器高度的方法,有些傻,大家就假装没看到。

二、CSS3 transition的难点

如果直接一行CSS代码就可以让动态呈现动画化,那就不需要本文了,早就各个站点都是这类优质体验的交互了。究其根本就是CSS3 transition的一个局限性,对"auto"*冷淡!嘛意思?

大家很好理解,所谓“过渡”,就是从一个地方到另外一个地方,比方说,从0100. 但是,你来个从0auto, 傻眼了吧。大学时看过一部美国科幻片《心灵传输者》,其中男主也不是想瞬间位移就瞬间位移的,也是需要知道目的地和路径的。

然而,当我们在一个div呈现动态内容的时候,由于我们并不知道里面的内容(都说了是动态的嘛),所以,我们的height其实都是auto,于是,就算transition: height .35s走起,也不会有动画效果的,我们需要的是固定值。

于是难点和关键点来了,如何赋予固定高度值?

三、固定高度值与transition触发

说白了很简单,当前高度固定值,获得动态内容载入后的高度固定值,再style设置,over~

代码细节我就不讲了,其实没什么人关心的,“我需要的是代码,代码!”估计很多人心里是这么咆哮的。

// 高度无缝动画方法
var funTransitionHeight = function(element, time) { // time, 数值,可缺省
    if (typeof window.getComputedStyle == "undefined") return;
    
    var height = window.getComputedStyle(element).height;

    element.style.transition = "none";    // 本行2015-05-20新增,mac Safari下,貌似auto也会触发transition, 故要none下~
   
    element.style.height = "auto";
    var targetHeight = window.getComputedStyle(element).height;
    element.style.height = height;
    element.offsetWidth = element.offsetWidth;
    element.offsetWidth;
    if (time) element.style.transition = "height "+ time +"ms";
    element.style.height = targetHeight;
};

十行出头点代码。

element就是容器元素;如果transition你是写在CSS中的,time参数可以不要,例如:

element { transition: height 250ms; overflow: hidden; }

funTransitionHeight(element)

funTransitionHeight名字如果你不喜欢,可以自己改掉。IE9+有效,IE10+有动画,IE6~IE8老样子,所谓渐进增强。

百闻不如一见,您可以狠狠地点击这里:不定高度动态元素height CSS3 transition过渡demo

点击页面上“点击我”按钮,里面就有有高度不固定内容呈现,大伙儿就可以看到内容呈现时候不是砰砰砰了,而是歘歘歘~
demo页面的点击我按钮

gif截图

如何调用?很简单,初始化时候funTransitionHeight()一下,赋个固定值;然后每次菊花完毕,内容载入后在funTransitionHeight()一下,动画就来啦。也就是说,相比你们以前的JS代码,就多了一行funTransitionHeight(element)调用而已,是不是实用又低成本!

四、结束语

貌似最近折腾了很多与菊花有关的文章,菊花恒久远,一颗永流传!

菊花

感谢阅读,欢迎交流菊花心得!

(本篇完)

分享到:


发表评论(目前35 条评论)

  1. Lane Sun说道:

    在var targetHeight = window.getComputedStyle(element).height;前设置断点的话,好像会有一个瞬态的高度跳跃,可不可以在母div中嵌入一个子div,检查子div的高度呢,毕竟万一页面复杂的话跳来跳去会影响性能。

    • Jone说道:

      可以,我就是这么做的,父div大小不变,子div设为auto,然后父子同时改变,避免跳动

  2. Bronya说道:

    var oldHeight = element.offsetHeight
    element.style.height = “auto”
    var autoHeight = element.offsetHeight
    element.style.height = oldHeight + “px”
    setTimeout(function(){
    element.style.height = autoHeight + “px”
    },0)
    这样不是更简单吗

  3. 咕咕说道:

    element.offsetWidth = element.offsetWidth;
    这句有什么意义呢

  4. wl22说道:

    通过getComputedStyle获取元素数值高度,才能用于transition触发动画,模糊值不能触发动画。

  5. virgouss说道:

    我居然看见了 e宠 的广告。。

  6. 莹莹yy说道:

    如果是一个隐藏的div,但是这个div的高度不定,怎样实现这个效果呢?研究了好久,没想到更好的办法呢

  7. xxl说道:

    您好。我想问下element.style.height = “auto”;在这段代码里起到什么作用呢?下面不是又element.style.height = height;了吗?
    我试过把element.style.height = “auto”删掉,该元素高度就不会随子元素变化;如果我把它放在element.style.height = height;后面,整个transition的变化很生硬。
    本人初学前端,请大家多多指教(*^__^*)

    • ekoo说道:

      element.style.height = “auto”; // 将高度设置为 auto,这样下面 targetHeight 的值就是将要调整的高度
      element.style.height = height; // 设个设置回原来高度,这样就可以利用 transition 从当前高度过渡到 targetHeight 这个高度

  8. 你结婚了没说道:

    你结婚了没

  9. 李江民说道:

    还要通过JS,不知道有没有只用CSS就可以实现的方法?

    http://codepen.io/Dudy/pen/pvRRzB
    刚看到这个,使用max-width来实现transition,纯JS实现

  10. 少华说道:

    看下

  11. 赖祥燃说道:

    用世界之窗浏览器试了下demo,发现效果只在第一次有效,后面就没有效果了。

  12. en说道:

    我要访问

  13. miao说道:

    请教如何解决使用了transform后导致浏览器滚动条变化和闪动的问题

  14. balbeleet说道:

    别老菊花菊花的 妹子看到会有想法 你考虑过这个问题的严重性吗?

  15. 青铜说道:

    找到一个bug,在360安全浏览器极速模式下貌似无效,楼主可以测试下

    • 小李子说道:

      确实是这样的,只有第一次加载的时候才会自适应高度的!其他的不行

  16. calmcarry说道:

    请教一个问题:
    setTimeout(function() {
    if (time) element.style.transition = “height “+ time +”ms”;
    element.style.height = targetHeight;
    }, 15);
    即使我把15改成1,动画效果依然正常,但是如果我把setTimeout去掉,就直接没有动画效果了,这是为什么

    • 张 鑫旭说道:

      @calmcarry 触发动画效果需要触发重绘,setTimeout就有这个作用。

      • calmcarry说道:

        看了一下关于javascript线程的解释,大致明白是怎么回事了,多谢

      • Roam说道:

        看了一下,这里的 setTimeout 和触发重绘没有关系。
        这里的延时只是为了让 loading 显示一会儿。
        如果没有延时,box.innerHTML 直接被赋值两次,loading 被紧跟着的第二次内容取代了,就看不到 loading(菊花) 了。

  17. 大怪兽说道:

    LZ够幽默,不错!挺喜欢你的作品!

  18. DT说道:

    容器定义一个min-height

    • 一步一脚印2522392195说道:

      min-height??? 没看懂这个例子吧你

      第一次调运的目的是给box设置一个初始高度吧,给个初始固定高度,可以不执行哇

  19. Kenny说道:

    var height = window.getComputedStyle(element).height;
    element.style.height = “auto”;
    var targetHeight = window.getComputedStyle(element).height;
    element.style.height = height;

    element高度设成”auto”时为什么不会闪一下?
    因为css渲染器还没反应过来吗?

  20. 大冒险家说道:

    抱歉,我不是很明白为什么要先初始化一次?我没搞懂

  21. Nobody说道:

    用的话还可以,但是出来第一次就调用一下,是不是对性能不太好!!!