魔法CSS(1)——消失的list-style

2次阅读

共计 2916 个字符,预计需要花费 8 分钟才能阅读完成。

有时候一个简单 Bug 的出现,往往是由于一点知识小细节;但往往这点小细节看似简单,其背后却颇有韵味。
(需求)这部分 UI 给换成这样的

看起来相对比较简单,分析下结构:

整体为无序列表,需要保留前置图标;
每个列表后跟随对号,且始终垂直居中;

嗯?首先需要个对号,Css 好像可以实现(那就用不用麻烦用 icon 了):
对好实现

// <span className=”check” />
.check{
position: relative;
display: inline-block;
width: 16px;
height: 15px;
margin: 0 10px;
&::after{
content: “”;
position: absolute;
left:0;
width: 100%;
height: 50%;
border: 2px solid #000;
border-radius: 1px;
border-top: none;
border-right: none;
background: transparent;
transform: rotate(-45deg);
}
}

实现原理很简单,就定个伪元素设置宽高形成矩形,然后背景色透明,边框只保留左和下(其他相邻也可),最后旋转个角度就 OK;
接下来,图标跟随列表始终垂直居中(垂直居中方法比较多,高度不定 flex 方便点,就他了),li 标签内元素需要水平两列布局,文字靠右,对好靠左垂直居中,话不多说提上 flex 就是撸。

// 部分代码,作用就是循环生成列表
<ul className=”detail” >
{
storeTypeInfoMap[type].map(item => (
<li>
{item}
<span className=”check” />
</li>))
}
</ul>
// css
.detail {
font-size: 12px;
color: $c-gray;
li {
display: flex;
justify-content: space-between;
align-items: center;
text-align: left;
line-height: 3em;
padding-right: 10px;
.check{
position: relative;
display: inline-block;
width: 16px;
height: 15px;
margin: 0 10px;
&::after{
content: “”;
position: absolute;
left:0;
width: 100%;
height: 50%;
border: 2px solid #000;
border-radius: 1px;
border-top: none;
border-right: none;
background: transparent;
transform: rotate(-45deg);
}
}
}
}
出现的界面:

??? 我的 li 标签的 list-style 属性怎么没有啦?强制给 liul 都设置个 list-style-type: disc;, 还是没用?
这点小细节 1——list-style 消失真相

首先想想是不是更 flex 布局有关;因为 Flex 布局,会导致一下属性失效;但是也只有其子元素的 float、clear 和 vertical-align 属性失效,没说 list-style 属性会失效啊?

问题在于 display?:

首先 display 好像有个 list-item 属性可以对非列表元素进行列表布局,但这里是直接使用 li, 不需要 display:list-item 啊;
划细节重点:

li 默认有 list-style 属性是因为,浏览器对 li 的默认 display:list-item, 就像内敛元素 display 默认为 inline;
display:flex 设为这个,所以就覆盖了 display:list-item, 以至于我们的 list-style 失效了。

那么如何解决?
内嵌一个其他标签元素进行 flex 布局?
<ul className=”detail” >
{
storeTypeInfoMap[type].map(item => (
<li>
<p className=”detail-item”>
{item}
<span className=”check” />
</p>
</li>))
}
</ul>

纳尼?列表图标跑到外边去了?

两个解决方案:

对 ul 进行 margin 把图标挤进容器

li 有个 list-style-position 属性, 设置为 inside 将图标放进 li 中就好(用这个把):

吐血,列表图标咋的又给独占一行啦?
这点小细节 2—list-style 内嵌 li 内部就是其中一员

但 li 图标设置内嵌到 li 内部时,其就相当与是 li 内部的一个内敛元素;
然后套的 P 标签又是块级元素,设置的 flex 布局也为块,得独占一行就被挤下来了;
既然块布局不行,那么试着将包裹元素 P 设置为 display: inline-flex 看看:

只有一行时这里又引出了有意思的 display:inline-XXX

后知后觉——inline-xxx

inline-flex 和 inline-block 都是一个 inline-xxx 序列,都会产生 BFC,并且外部表现为 inline 特性,内部表现为 block 特性;

联想到我们平时使用 inline-block 布局的场景:比如布局导航栏,经常会出现宽度明明计算好,但是却会出现最后一个或几个被挤到下一行的现象;我们知道这时由于 inline-block 是包含空格、换行符的,所以种种原因会导致 inline-block 产生间距,即会出现换行;

这里列表图标相当于空格之类的,而我们没有对内嵌的 <p>inline-block 标签设置宽度(根据内容自动,当然可以设置宽度 % 给图标腾出位置,但这样处理后期更改宽度相对麻烦),以至于当内容不足以一行容下时,p 宽度就别撑到父容器的宽度,便换行;

那么有什么办法解决呢(联系下处理 inline—block 布局问题的方式)?

不设置 display 为 inline-block, 而使用 float 浮动(这里显然不行,我们需要 inline-flex 布局 )
设置父元素,white-space: nowrap 强制不换行
父元素设置 font-size: 0;

试试父元素 font-size: 0

发现列表下项的图标没有了?

发现:看来列表的图标相当与列表中的一文字,font-size 可以控制其大小;

试试父元素 li 强制不换行?white-space: nowrap

哇!可以了好像,但是文字不换行被挤出去了,这个怎么回事?
再设置子元素 p 强制换行 white-space: pre-wrap 试试

赞;一个新的常用需求诞生了(对好紧随列表垂直居中)
不对好像最初的需求还没有坐呢?(没办法那就用第一种处理图标的方法:list-style-position: outside; 然后容器 ul 设置 margin 啰)

总结—简单并不简单
虽然这只是一个简单的需求,实现的方法肯定很多,但是每一种方法的背后可以衍生出的知识点却是无尽的;衍生出的每一个知识点也许看似简单,但其背后的原理细节却是值得研究的。
学无止境,积累点滴;把小简单变成大简单。

如果这篇文章对你有所收获,请留在你的小心心!
其他推荐:

React 你知多少
Git 常用操作

正文完
 0