如何实现同等间隙的卡片布局
在列表展示中,经常会使用卡片的内容展示形式,为了美观,常常要求各卡片间的间隙是一致的。
卡片内容不一样可能高度不等,但一般来说为了整体的一致性,会限制每个卡片的宽高都相等。
本文就基于宽高一致的多个卡片,在不同屏幕大小下,每行卡片数量可能有调整,考量如何实现等间隙的布局。
放置一张张卡片项,为了设置间距,最常见的就是直接使用一个特定的margin值了,这种方式虽然可以(通过精确计算后确实也可以)
直接设置一个间距,比如统一 margin-left 和 margin-bottom都为 20px ,并不能保证每行最后一个卡片之后的间距是20px
关于如何定这个 margin的值,需要通过一个规则来计算,这个后文再说明
设置同等间距,常用的还有 flex布局中的 justify-content: space-between,可以定义各子项目以相同间距布局,但不好处理左右子项目与边框的间距。 space-around这个就更用不得了,会使得左右子项目右margin == 左margin * 2
所以最终还是回到使用margin值来设置,通过一个可用的规则,来保证间距是一致的。
先把基本结构搭上
<div class="container"> <h2>项目列表</h2> <ul class="proj-items"></ul> </div> <!-- 模板结构 --> <script type="text/template" id="proj-item-tpl"> <li class="proj-item"> <a href="#/p/{{projectid}}"> <h3 class="proj-item__title">{{projectname}}</h3> <p class="proj-item__author">{{author}}</p> </a> </li> </script>
js生成n个项目
function addevent(elem, type, handler) { elem.addeventlistener(type, handler, false); } function qs(selector) { return document.queryselector(selector); } function qsa(selectors) { return document.queryselectorall(selectors); } var mockdata = (function(num) { var data = []; for (var i = 1; i <= num; ++i) { data.push({ projectid: i, projectname: '项目' + i, author: '张大大' }); } return data; })(8); var itemtpl = qs('#proj-item-tpl').innerhtml; var itemsdom = qs('.proj-items'); /** * 渲染数据 * @param {[type]} data [description] * @return {[type]} [description] */ function renderlist(data) { var html = ''; var fragment = document.createdocumentfragment(); data.foreach(function(item) { var divtemp = document.createelement('div'); // 模板替换 divtemp.innerhtml = itemtpl.replace(/{{(\w+)}}/g, function(input, match) { return match ? item[match] || '' : ''; }); fragment.appendchild(divtemp.firstelementchild); }); // 渲染 itemsdom.appendchild(fragment); } renderlist(mockdata);
把基础样式放上,这里我们先指定一个特定的itemmargin值为20px
$itemmargin: 20px; $itemwidth: 130px; $itemheight: 150px; .container { margin: 20px auto; width: 450px; background-color: #f2f2f2; color: #666; h2 { margin: 20px; padding-top: 20px; font-size: 20px; } } .proj-items { display: flex; flex-wrap: wrap; /* justify-content: space-between; */ padding: 0; list-style: none; &:after { content: ""; display: block; flex-grow: 99999; } } .proj-item { margin-left: $itemmargin; margin-bottom: $itemmargin; width: $itemwidth; height: $itemheight; background-color: #fff; border-radius: 3px; text-align: center; &:hover { box-shadow: 0 0 20px #ddd; } a { display: block; padding: 15px; height: 100%; color: #666; text-decoration: none; } &__title { margin-top: 0; font-size: 16px; } &__author { font-size: 12px; } }
可以看到,每行最后一个间距不一致了,所以不能简单的写个margin值
再来看看设置 space-between的时候
.proj-items { justify-content: space-between; ... } .proj-item { /* margin-left: $itemmargin; */ margin-bottom: $itemmargin; ... }
看来并不够强大
如果看得仔细,应该能看到项目7和8是挨在一起的,为何没有间距呢
其一是因为没有margin-left值,其二是在项目列表后放了一个坑来占位,防止最后一行项目过少时 space-between的值太大了
把这个撤掉看看这个影响
&:after { content: ""; display: block; flex-grow: 99999; }
还是把目光投向margin值的设定规则吧
在设计一个页面布局时,至少已经确定了xx页面大小的情况下,容器宽度应该设置为多少(比如为1200px),每行放n个项目,项目的宽高是多少
有了这些指标(也必须有这些指标),我们就可以用来计算margin值了
containerwidth == n * itemwidth + (n + 1) * itemmargin
得出
itemmargin = (containerwidth - n * itemwidth) / (n + 1)
代入这里的情况,containerwidth 450px,itemwidth 130px,每行 3个,即可得出 itemmargin 正好为 15px
有了某种特定情况下的布局规则之后,接下来还要考虑不同屏幕大小的情况下,怎么调整这个margin值
这个需要结合媒体查询来设定,同时相应的计算规则也可以通过scss来处理
第一种情况是每行3个,n只可能为整数,即可推算出需要处理的临界值为1 2 3 4 5 6 ... 这些整数值
加入n为4,如果要保证 itemmargin值15px在各种情况下都相等,计算可得 容器宽度containerwidth值 为 595px
同理求得 n是5时为 740px ,n是2时为 305px
当然,如果觉得这个containerwidth值不太好看,也可以自己定义,比如 n是4的时候设置为 600px,代入公式那么 itemmargin值为16px。
为了保证各种请下间距都相等,我个人就不推荐这么干了
通过上述的规则计算,我们可以得出每行项目数量递增时的容器宽度临界值。把这些临界值放在媒体查询里面配置,即可方便地实现这种布局的自适应。
/* 这两个为初始就确定的基准值 */ $containerwidth: 305px; $itemmargin: 15px; $itemwidth: 130px; $itemheight: 150px; /* 每行项目数量为itemnum时的容器宽度 */ @function getcontainerwidth($itemnum) { @return $itemnum * $itemwidth + ($itemnum + 1) * $itemmargin; } /* 配置各个页面宽度下的容器宽度(应用) */ @mixin adjustcontainerwidth( $from: 2, $to: 5 ) { @for $i from $from through $to { $minwidth: getcontainerwidth($i); $maxwidth: getcontainerwidth($i + 1); @media only screen and (min-width: $minwidth) and (max-width: $maxwidth) { .container { width: $minwidth; } } } } .container { margin: 20px auto; width: $containerwidth; background-color: #f2f2f2; color: #666; h2 { margin: 20px; padding-top: 20px; font-size: 20px; } } @include adjustcontainerwidth( $from: 1, $to: 7 );
即可实现各个页面大小下的自适应效果
完整的css部分
1 /* 这两个为初始就确定的基准值 */ 2 $containerwidth: 305px; 3 $itemmargin: 15px; 4 5 $itemwidth: 130px; 6 $itemheight: 150px; 7 8 /* 每行项目数量为itemnum时的容器宽度 */ 9 @function getcontainerwidth($itemnum) { 10 @return $itemnum * $itemwidth + ($itemnum + 1) * $itemmargin; 11 } 12 13 /* 配置各个页面宽度下的容器宽度(应用) */ 14 @mixin adjustcontainerwidth( 15 $from: 2, 16 $to: 5 17 ) { 18 @for $i from $from through $to { 19 $minwidth: getcontainerwidth($i); 20 $maxwidth: getcontainerwidth($i + 1); 21 22 @media only screen and (min-width: $minwidth) and (max-width: $maxwidth) { 23 .container { 24 width: $minwidth; 25 } 26 } 27 } 28 } 29 30 .container { 31 margin: 20px auto; 32 width: $containerwidth; 33 background-color: #f2f2f2; 34 color: #666; 35 36 h2 { 37 margin: 20px; 38 padding-top: 20px; 39 font-size: 20px; 40 } 41 } 42 43 @include adjustcontainerwidth( 44 $from: 1, 45 $to: 7 46 ); 47 48 .proj-items { 49 display: flex; 50 flex-wrap: wrap; 51 padding: 0; 52 list-style: none; 53 } 54 55 .proj-item { 56 margin-left: $itemmargin; 57 margin-bottom: $itemmargin; 58 width: $itemwidth; 59 height: $itemheight; 60 background-color: #fff; 61 border-radius: 3px; 62 text-align: center; 63 64 &:hover { 65 box-shadow: 0 0 20px #ddd; 66 } 67 68 a { 69 display: block; 70 padding: 15px; 71 height: 100%; 72 color: #666; 73 text-decoration: none; 74 } 75 76 &__title { 77 margin-top: 0; 78 font-size: 16px; 79 } 80 81 &__author { 82 font-size: 12px; 83 } 84 }
上一篇: 使用mpvue搭建一个初始小程序
下一篇: 昨晚睡梦中被画画一脚踢下床
推荐阅读
-
css3 column实现卡片瀑布流布局的示例代码
-
css3 column实现卡片瀑布流布局的示例代码
-
android的布局 (如何实现空心圆效果的布局)
-
如何实现同等间隙的卡片布局
-
页面中有间隔的方格布局如何完美实现方法
-
如何在移动端实现纯css的自定义布局?
-
【请教】如何实现横向布局时图片A居中宽度固定,左右两侧由不同的图片B、C填充为背景_html/css_WEB-ITnose
-
如何在移动端实现纯css的自定义布局?
-
CSS 布局实例系列(四)如何实现容器中每一行的子容器数量随着浏览器宽度的变化而变化?_html/css_WEB-ITnose
-
CSS 布局实例系列(四)如何实现容器中每一行的子容器数量随着浏览器宽度的变化而变化?_html/css_WEB-ITnose