Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

响应式元素列表的程序实现

  之前有一篇使用flex与max/min-width来解决响应式列表页的 ,但是flex这东西太新了,目前浏览器对其的兼容依然很糟糕。于是我们考虑通过程序来解决这个问题。其实用程序实现的话,在一些细节的用户体验上要比flex好得多,但可能性能方面不及flex。
  我们要做的主要是这两件事。一,对元素设置max-widthmin-width,将元素的尺寸限制在这个范围内。二,对每行元素的尺寸做调整,使其尽可能的填满一行。这是使用flex比较容易实现的,但是flex的实现有个问题,对于最后一行的元素,即使是最大尺寸也无法填满行,所以元素总是会保持最大尺寸。下面这个截图是使用flex的实现,后两个元素的尺寸就没和前面的行一致,感觉很突兀。

  其实我们可能更希望元素与之前的行对其。使用程序计算就可以解决这个问题。下面是使用程序实现,这里我写成了一个jQuery插件:

<!DOCTYPE html>
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<style>
ul {
  border:1px solid red;
  padding:0px;
  list-style:none;
  overflow:hidden;
}
ul li {
  float:left;
  min-width:30px;
  max-width:60px;
  height:30px;
  background:#CCC;
  margin:4px;
}
</style>
<ul>
  <li></li><li></li><li></li><li></li><li></li><li></li><li></li>
  <li></li><li></li><li></li><li></li><li></li><li></li><li></li>
</ul>
<script>
$.fn.extend({
  fillLines:function(){
    var $this=$(this);
    var containerWidth=parseInt($this.css("width")); //容器宽度
    var lineWidth=containerWidth; //当前行的可用行宽度
    var lineElements=[]; //当前行的元素
    var lastArgs; //保存上一行的参数
    var node,max,min,margin;
    $this.children().each(function(){
      //强制元素使用border-box以防止border和padding对尺寸的干扰
      node=$(this).css("box-sizing","border-box");
      //取出元素允许的最大和最小宽度
      max=parseInt(node.css("max-width"))||9999;
      min=parseInt(node.css("min-width"));
      //取出元素的水平margin
      margin=parseInt(node.css("marginLeft"))+
             parseInt(node.css("marginRight"));
      //如果当前行不足以容纳这个元素则换行
      if(lineWidth<min+margin)return makeLine();
      //从当前行剩余的空间中扣除当前元素的宽度
      lineWidth-=min+margin;
      //将当前元素的相关参数以数组的形式储存下来
      lineElements.push([min,max,max-min,node]);
    });
    //最后一行用上一行的参数来调整尺寸
    if(lastArgs)
      lineWidth=lastArgs[0]*lineElements.length/lastArgs[1].length;
    makeLine();
    //换行
    function makeLine(){
      //统计可用于调整的空间
      var total=0;
      for(var i=0;i<lineElements.length;i++)
        total+=lineElements[i][2];
      //调整元素尺寸
      for(var i=0;i<lineElements.length;i++){
        var e=lineElements[i];
        var w=lineWidth*e[2]/total;
        e[3].css({width:e[0]+w});
      };
      //记录当前行的参数
      lastArgs=[lineWidth,lineElements];
      //将元素作为下一行的初始值
      lineWidth=containerWidth-min-margin;
      lineElements=[[min,max,max-min,node]];
    };
  }
});
//绑定到ready和resize上
$(window).on("resize ready",function(){
  $("ul").fillLines();
});
</script>
网名:
34.203.213.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^