相信大多数人都有过关于CSS的痛苦经历,从我加入公司到如今,不到两年的时间里,听到最多CSS相关的讨论就是‘很难调’。因此我也一直在探究这其中有怎样的问题,为何不少人以为CSS很难写,如何才能让其余人更优雅的写CSS。在Code Review的时候,我渐渐的发现了问题所在,其实不少人已经掌握了丰富的CSS知识,但殊不知道如何分组属性写成class。最后只好在须要改变样式的元素上随意起个名字作class而后把全部要写的属性丢进这个class里,若是优先级不够,再把前面的选择器都加上。结果就是CSS代码不断堆积,重复和冗余不断增多,维护也变得举步维艰。
css
问题找到了,但如何解决呢,虽然我在项目组内作了几回分享,还常常在Code Review的时候提出一些问题,却仍是收效甚微。有时候知道什么是正确的很容易,但知道如何才能作到正确却很难。直到最近,看了几本书以后,发现了一个很适合指导设计CSS的方法,那就是五个为何或者叫五问法。五问法来自丰田的精益生产,后来天然衍生到了精益创业中,在DDD以及UX相关书籍中都会见到这个方法,其主旨是深刻发觉大量现象的背后所隐藏的真正缘由。乍一看它是一个管理方法,其实我以为它是一种思惟方式,即刨根问底的找到问题的根本缘由并解决。因此被应用于各个领域,天然对于CSS所面临的问题也正恰如其分。html
先来举个例子吧,某天Code Review发现了一条CSS代码是这样写的:框架
.max-width { max-width: 300px; }
由此产生了如下对话(纯属虚构):.net
UI Dev:“不该该这样写,这和直接写内联样式有什么区别呢?”设计
Dev:“若是我不加最大宽度,页面上那个元素左边就会多出一部分,否则加个margin外边距能够吗?”code
UI Dev:“这个...我也不肯定,我从没遇到过这样的问题,必定是哪里有问题。”htm
Dev:“确实这样写也挺很差的,过一段时间就不知道这行代码什么意思了,也不敢修改它。但究竟应该如何写呢?”开发
UI Dev:“呃,这样吧,咱们来试试五个为何,找找问题的根本缘由。”get
Dev:“好啊,CSS的问题也困扰我很久了,能解决就最好了。”io
UI Dev:“首先问问,为何要给元素加最大宽度呢?”
Dev:“由于不加就就会多出一部分呀。”
UI Dev:“那为何这个元素会多一部分呢?”
Dev:“由于没加最大宽度,开个玩笑,别生气,其实我也不肯定,不过用DevTools看了一下,好像它的父元素的宽度也不对。”
UI Dev:“已经接近了,为何父元素的宽度不对?”
Dev:“由于父元素的内边距两边不同。”
UI Dev:“为何父元素的内边距不一致?”
Dev:“啊,我知道了,原来为父元素的父元素写了一个last的伪选择器,它是用来把padding-right设为0的,由于父元素如今正好是最后一个,因此被影响了。”
UI Dev:“别急,为何要把最后一个元素的padding-right设为0?”
Dev:“由于原先最后面的那个元素里面是一个没法修改样式的控件,须要把padding-right设为0才能放得下。”
UI Dev:“因此这才是问题所在,咱们的意图是给空间的容器加上padding-right为0的属性对吗?而不是给最后一个元素加,因此应该写一个class,也许叫作‘widget-container’之类的,放在那个容器上,而后把last伪选择器删掉,如此一切就正常了。原先出问题的地方实际上是没问题的。”
Dev:“原来是这样,太好了,我学到了,样式出问题的地方不必定是代码有问题的地方,五个为何太有用了。”
这样反复问屡次“为何”可让咱们找到问题的根本所在,若是仅仅从表面现象去解决问题极可能致使南辕北辙的后果。并且在例子中的last伪选择器就是由于没有找到根本缘由而简单粗暴的写了这样一行代码而致使的。这个例子还很好的展示了五个为何对于CSS的益处,不只是找到问题的根本缘由,还使得咱们在写CSS的时候意图更加明确。如此一来,class命名难的问题也迎刃而解,padding-right应该为的0的元素是那个控件的容器,因此很容易想出“widget-container”这样的名字,由于经过五个为何的方法找到了真正的意图,此时,class叫什么和应该放在哪都是水到渠成了。
但有时候咱们所面对的项目不会这么善良,“为何”的层级越多,说明CSS的关系也越复杂,因此如今咱们来谈谈五个为何中的一个重要原则,按比例投入。其主旨是小问题小投入,大问题大投入,问题等级越高,投入也应该越大。在CSS中来说,就是当发现样式异常时,使用五个为何深刻找到的根本缘由所在之处的重复次数越多,说明问题越严重,对问题的解决方案也应投入的更多。
再回到上面的例子中,经过一个元素位置异常的问题,找到根本缘由来自一个控件须要内边距为0的容器元素,因为第一次发现,因此选择投入较小的解决方案,针对该控件加一个class用来去掉内边距。目前看来是很正确的,但若是连续不断的从不一样的问题上深刻找到这个控件上,那就说明问题等级提高了,不该该仅仅是在每一个调用控件的容器上添加该class。此时咱们能够考虑其余方式,好比把全部容器内边距都设为0,而有针对性的对内部元素添加外边距,若是问题等级继续提高,还能够修改甚至替换控件,或者重构其余部分来适应该控件。总之就是要按问题等级选择解决问题的手段,这样的好处不只仅是原先在精益中那样能够自动调节效率,还能够等样式需求更明确的时候做出相应的重构。
因为CSS的描述性,使得它很自由,因此同一个需求,每每一百个开发者有一百种实现。在第一次碰到一个需求时,更是很难写出最佳实现,只能有针对性的写一个专属class把须要的属性扔进去。其实问题不在于此,而在于以后是否能在相同问题出现时重构原先的代码,根据全部相关问题写出更具普适性的class。有经验的UI Dev有时会经过经验来判断,直接写出这种class,Bootstrap这类框架就是这样的,但没有或较少经验的开发者就会产生疑惑。五个为何的按比例投入原则能够很好的驱动CSS的开发,用深刻的根本缘由链接不一样元素甚至不一样页面上出现的问题,这样使咱们可以安心的以目前的问题等级来组织代码,等到再次碰到问题并找到这里,才再次重构以解决问题。