Appearance
前言
实现一个UI库都具备的栅格系统,用于快速实现一个响应式的布局,栅格系统有如下特性
- 具备一个row容器和一系列的col单元格,当然,col单独存在时也需要能正常展示
- 24个单元格,更加精细化的展示,同时还需要能够在单元格之间有空隙
- 单元格除了正常的排列外还需要具备偏移和排序功能
- 响应式布局也是必不可少的
- 新的框架也要是一个能够利用新特性的来实现栅格的,拥抱新特性
具体实现
基于float
首先实现一个简单的row,row根据不同设备大小定义,宽度100%
less
.clearfix {
&:after {
content: '';
display: block;
clear: both;
}
}
.row {
.clearfix();
width: 100%;
box-sizing: border-box;
@unit-count: 24;
@unit-width: (100% / @unit-count)
.col {
float: left;
box-sizing: border-box;
}
each(range(@unit-count), {
.col-@{value} {
width: (@unit-width * @value)
}
})
}添加上间隔,假设间隔添加为12px,而且间隔还需要是首尾无间隔,中间的间隔相同
less
.col {
margin-right: 12px;
&:last-child {
margin-right: 0;
}
}
// 也可以按照下面写
.col {
padding-left: 6px;
padding-right: 6px;
&:first-child {
padding-left: 0;
}
&:last-child {
padding-right: 0;
}
}栅格系统的偏移指的是在原有位置上平移,如果有重复会直接覆盖。排序会使最终的效果按照css不是html实现,我们定义通过col-offset-4 表示在原有的位置上向右偏移4个单元格。定义col-push-4表示从第四个单元格开始布局
less
.col {
position: relative;
}
each(range(@unit-count), {
.col-offset-@{value} {
// 偏移的关键通过相对定位 不会影响到其他
left: @value * @unit-width;
}
.col-push-@{value} {
// 排序的关键是marigin,通过margin会影响到后面所有的
margin-left: @value * @unit-width;
}
})bootstrap实现栅格系统
主要是参考bootstrap的栅格系统,bootstrap栅格系统由container、row和col组成。规定col必须包含在row中,row可以包含在container或者另一个col中。
less
@media-sizes: {
sm: 768px
md: 992px;
lg: 1200px;
xs: 1920px;
}
@media (min-width: @media-sizes[sm]) {
// 总是在两边空出一定间隔,避免撑满
.container {
width: @media-sizes[sm] - 18px; // 750px;
}
}
@media (min-width: @media-sizes[md]) {
.container {
width: @media-size[md] - 22px;
}
}
@media (min-width: @media-sizes[lg]) {
.container {
width: @media-size[md] - 30px;
}
}
.container {
// 额外增加了15px的间隔
padding-left: 15px;
padding-right: 15px;
margin-left: auto;
margin-right: auto;
.row {
// 抵消到container额外增加的padding的
margin-left: -15px;
margin-right: -15px;
}
.col {
// 因为这个地方总是增加了15的padding,为了方便col本身也作为container 容器使用, 也能实现间隔
padding-left: 15px;
padding-right: 15px;
}
}基于flex实现栅格系统
bootstrap栅格系统的神,目前bootstrap4 和 bootstrap5采用的方式就是flex的方式实现栅格,整理借鉴一下。
less
.row {
display: flex;
flex-wrap: wrap;
}
.col {
flex: 0 0 auto
}
each(range(@unit-count), {
.col-@{value} {
width: @unit-width * @value
}
})迁移到ui框架
前面我们的设计都是在style上面作文章,实际栅格系统这种东西也就是style,没有交互,迁移到UI框架需要开放一些定制能力,比如栅格的间隔大小,栅格的个数,这个是单纯的样式系统不能实现的
总结
踩坑总结
- 在less中使用计算时,有时会碰到变量不计算的问题(被处理成了宏,直接替换了),使用括号包括强制计算
less
@unit-count: 10;
@unit-width: 100% / 10
.col {
width: @unit-width * 5 // 理想应该输出 50 实际会输出 100% / 10 * 5
width: (@unit-width * 5) // 强制计算
}- less中没有slot功能,比如想在@media将内容整个嵌入,还没找到办法实现
- 嵌套选择器没法跳过,这个还没找到功能
less
.a {
&-b {
color: red;
}
}
// 这里我只想最终的输出如下
.a-b {
color: red;
}
// 实际上会输出如下
.a .a-b {
color: red;
}- 如果选择更上一级的父选择器, 这个目前已经解决,通过将&赋值实现
