在做这种实现之前我钻研过其它的实现形式,比方 CSS 3 的 column,这种形式出现的多列有许多的问题,像是列宽度如果不够凑满容器时会均匀距离于其它列,就有些像字符间距一样;尽管当初的浏览器都曾经基本上兼容了这种实现,然而在某些组合其它成果应用的场景中会存在一些意料之外的问题,比方在 Internet Explorer 中动静向列中增加元素时,如果提前利用了这个新增加元素的 CSS 3 动画会导致闪动和隐没的问题;本来列内容的最终排序形式始终凑满一列而后自左向右的靠,也就是首先自上而下排列,而后再是自左向右,比方最右边的列是 1、2、3,向右一列是 4、5、6,这在动静增加新内容时看上去并不谐和。所以我本人换了一种形式实现,上面是动静效果图:
我的实现逻辑并不算简单,依据上一列的最小高度内容确定下一列的新内容搁置的地位,自左向右选一个最合适的地位;也就是每一个内容在增加到容器之前都会依据上一排的内容大小抉择适合的地位,计算过地位后再搁置到容器中。下面的效果图来自我写的一个例子:
<!doctype html><style> table { display: inline-block; vertical-align: top; border-collapse: collapse; float: left; } td { padding: 5px; } #container { border: 1px solid gray; position: absolute; padding: 5px; padding-bottom: 25px; width: 80%; } #load { position: absolute; bottom: 0; width: 100%; height: 20px; left: 0; }</style><body> <div id="container"> <table id="column1" class="columns"></table> <button id="load" type="button" onclick="GetRandomBlocks(8)">load</button> </div> <script> var borderSize = 1; var paddingSize = 5; var width = 150; //计算容器的总宽度以确定可能包容的列数 var containerWidth = parseInt(document.getElementById("container").clientWidth); var columns = parseInt(containerWidth / (width + paddingSize * 2 + borderSize * 2)) - 1; var surplus = containerWidth % (width + paddingSize * 2 + borderSize * 2); var container = document.getElementById("container"); var loadButton = document.getElementById("load"); for (var i = 0; i < columns; i++) { //确定好列数过后向容器内补充新的列 var e_column = document.createElement("table"); e_column.id = "column" + (i + 2); e_column.className = "columns"; container.insertBefore(e_column, loadButton); } container.style.width = containerWidth - surplus + "px"; //补充新的内容 function GetRandomBlocks(size) { for (var i = 0; i < size; i++) { var e_content = document.createElement("div"); e_content.style.border = borderSize + "px solid green"; e_content.style.width = width + "px"; e_content.style.height = GetRandomInt(100, 300) + "px"; e_content.style.fontSize = "30px"; e_content.className = "contents"; e_content.innerText = document.getElementsByClassName("contents").length; var e_td = document.createElement("td"); e_td.appendChild(e_content); var e_tr = document.createElement("tr"); e_tr.appendChild(e_td); //补充之前计算应该在的地位(外围) var columns = document.getElementsByClassName("columns"); var minHeight = parseInt(document.getElementById("column1").clientHeight); var minHeightId = ""; for (var j = columns.length - 1; j >= 0; j--) { var height = parseInt(columns[j].clientHeight); if (height == 0 || height < minHeight) { minHeight = height; minHeightId = columns[j].id; } } //------------------------------------------------------------------------ if (minHeightId) { document.getElementById(minHeightId).appendChild(e_tr); } else { document.getElementById("column1").appendChild(e_tr); } } } //给内容确定随机高度的办法 function GetRandomInt(_start, _end) { var x = _end - _start; var num = Math.random() * x + _start; return parseInt(num, 10); } //开始 GetRandomBlocks(8); </script></body>
用 Javascript 计算内容的相对地位,这甚至须要准确到边框的宽度,所以这外面的边框宽度、边距大小和内容大小一样也不能少,列数是依据容器的宽度确定的,当然至多须要有一列,全副的代码也就这些了,增加内容的办法模仿了动静获取内容,其中要留神 HTML 标记格局不要轻易改,我顺便选了用表格来承载。