H2rmone / blog

🤔Independent thinking.
9 stars 0 forks source link

Responsive Grid with Borders(响应式栅格布局的边框实现) #4

Open H2rmone opened 4 years ago

H2rmone commented 4 years ago

Requirement

最近一直在忙重构业务的事情,很久没有发新文,这次借着期间碰到的一个问题展开来说下。需求比较简单:在一个栅格布局中以每行3个为例,要求最后一列出现的元素不能有底边框,每一列的最后一个不能有右边框。

用一个简单的图表示那么就是 requirement

Solution

解决方案其实有很多种,js,css都可以解决,这里我们讨论的方案尽量以不是奇技淫巧的方式去解决,而是单纯css的方案

首先我们来找出所有的情况,我画了3个图代表三个不同的case,绿色的代表每一个子元素的border,红色三角表示这个元素不需要底边框,黄色圈圈表示这个元素不需要右边框:

Case 1

九个子元素对应最后一列出现3个元素的情况 case-1

八个子元素对应最后一列出现2个元素的情况 case-2

七个子元素对应最后一列出现1个元素的情况 image

针对这些情况很快就能得出下面的思路: 给每列不是最后一个元素的元素加上border-right

.item {
  &:not(:nth-child(3n)) {
    border-right: 1px solid lightgray;
  }
}

给不是最后一列的元素加上boder-bottom,从上面3个case中我们可以发现一共有6种情况:

这里我们使两种选择器且逻辑去关联,再归纳一下可以形成3条规则:

转化成css得到:

.item {
  &:not(:last-child, :nth-last-child(2):nth-child(3n + 2), :nth-last-child(-n + 3):nth-child(3n + 1)) {
    border-bottom: 1px solid lightgray;
  }
}

❗Reminder

值得一提的是,有多个参数列表的:not()选择器是Selectors Level 4的标准,目前大部分都不支持,而Selectors Level 3中定义里面的参数只能是简单的一个选择器。上述这种写法如果需要兼容处理的话可以拆成多个:not()

.item {
  &:not(:last-child),
  &:not(:nth-last-child(2):nth-child(3n + 2)),
  &:not(:nth-last-child(-n + 3):nth-child(3n + 1)) {
    border-bottom: 1px solid lightgray;
  }
}

Thanks

最后如果实现方式有问题欢迎指正,有更好的css实现方式也欢迎留言。