本文是我在众成翻译平台上认领并翻译的:设计师/后端工程师也能马上实践!前端设计(CSS设计)的技巧 ,正文内容如下:
大家好,我是2015年的应届毕业生小原,职位是前端工程师。不久前我加入了新业务的开发,负责前端的设计和实现。我想在回顾当时做法的同时,总结出一套能够轻松实现的前端编程设计方法。
什么是高灵活性的前端开发设计
不论开发什么样的业务,都可能面临界面样式没有完全确定,或者今后还需要增加或改变功能点的情况。因此代码开发与业务构思一样,都需要具备高度的灵活性,对变化频繁的前端来说更是如此。
前端开发的灵活性是指,前端代码能在多大程度上高效的、持续地应对界面更新。
我们需要应对哪些变化
界面的变化需求是各种各样的,比如“把这个按钮的颜色和大小改一下”或者“把这块内容往上移一些,让它更醒目一点”之类的。这些修改需求虽然看起来五花八门,但其实都可以分为【功能点的布局】的变化和【功能点的外观】的变化这两类。
分离【功能点的布局】与【功能点的外观】
将这两者分离能够形成高效的敏捷性开发周期:从精益开发、设计构思到针对业务不断地进行测试、逐步改善功能。在这种开发模式下,将用户场景(接触功能点的流程 → 功能点的布局)和印象唤起(外观引起的情绪性操作 → 功能点的外观)分离并独立修改的情况也会很多。如果把【功能点的布局】与【功能点的外观】这两个要素分离开来进行独立开发,那么其中一个要素改变的时候另一个要素就不会产生bug(比如改变外观的时候布局被打乱)。这样一来就能够实现快速响应更新的高效率开发了。另外,由于能够将功能的各个组成部分像堆积木一样组装起来构建网站,开发人员还可以轻松地尝试各种各样的布局。
也就是说,在前端开发中,采用将【功能点的布局】与【功能点的外观】有意识地分离开来的设计,能够使代码具备足够的灵活性来应对业务改进的需求。而且这种设计实施起来非常简单。
明白这一点之后,即使你不懂前端,也能大致了解什么是具有灵活性的良好编程设计了吧。
分离开发【功能点的布局】与【功能点的外观】的方法
引言说的有点多了,还是来看看具体应该如何进行上文所述的前端开发吧。 总体思路是,在有关DOM构造和CSS的部分,遵循分离【功能点的布局】与【功能点的外观】这一规则进行代码编写。 ※ 详细的规范:文件结构与布局的命名遵循SMACSS风格,模块的命名则遵循BEM风格。
【功能点的外观】代码编写方法
首先介绍【功能点的外观】,这部分代码我采用了流动设计。这里的流动设计是指,元素的宽高尺寸依赖于外层元素,随外层元素宽高尺寸的变化而变化。代码实现如下所示:
// 例1 左边栏设计
<div class="item">
//与item的外观相关的所有css类名全部包含“item”
<div class="item__movie">...</div>
<div class="item__body">
<div class="item__body__title">...</div>
<div class="item__body__prof">
//在item中添加了prof组件
//同样与prof的外观相关的所有css类名全部包含"prof"
<div class="prof">
<div class="prof__user">
<div class="prof__user__img"></div>
<div class="prof__user__inf"></div>
</div>
</div>
</div>
<div class="item__body__tag">...</div>
</div>
<div class="underline"></div>
</div>
/** 外层的.item的设计要注意 **/
.item{
width: 100%; /** 为了将宽度的设置交给【item的布局】css文件,在这里将宽度设为100% **/
/** float: left; 反例 设置【item的布局】的css不要写 **/
/** margin: 10px; 反例 设置【item的布局】的css不要写 **/
/** 以下是设置外观的css **/
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-box-shadow: 0px 1px 3px rgba(51, 51, 51, 0.3);
-moz-box-shadow: 0px 1px 3px rgba(51, 51, 51, 0.3);
box-shadow: 0px 1px 3px rgba(51, 51, 51, 0.3);
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
}
/** 为避免在item外发生css干扰进行嵌套**/
/** 另外,使用__明确表示这是item的子元素**/
.item .item__body{
/** 自由设置css **/
...
}
.item .item__body .item__body__title{
/** 自由设置css **/
..
}
// 例2 右边栏设计
<div class="nav">
<div class="nav__title--l">...</div>
<div class="nav__select">
<div class="nav__select__child">...</div>
<div class="nav__select__child">...</div>
<div class="nav__select__child">...</div>
</div>
<div class="nav__title--s">...</div>
<div class="nav__title--s">...</div>
<div class="nav__title--s">...</div>
</div>
/** 外层的.nav的设计要注意 **/
.nav{
/**为了将宽度的设置交给【nav的布局】css,在这里将宽度设为100% **/
width: 100%;
height: 100%;
/** float, margin之类与布局有关的css不要写 **/
/** 以下是设置外观的css */
-webkit-box-shadow: 1px 0px 3px rgba(153, 153, 153, 0.5);
-moz-box-shadow: 1px 0px 3px rgba(153, 153, 153, 0.5);
box-shadow: 1px 0px 3px rgba(153, 153, 153, 0.5);
position: relative;
color: #e9e8e8;
background-color: #253038;
}
/** 避免在nav外发生css干扰**/
.nav .nav__title{
/** 自由设置css **/
...
}
.nav .nav__title.nav__title--l{
/** 自由设置css **/
...
}
.nav .nav__select{
/** 自由设置css **/
..
}
为什么这样写?
这段代码的目的是将class="item"
和class="nav"
这两个元素内部包含的所有子元素的【功能点的外观】整合起来。class="item"
所包含的class="item__body"
等内部元素的css设计也可以进一步细化,但首先要注意的是,class="item"
和class="nav"
这两个父元素的与【功能点的布局】相关的css设计没有写在这个css文件中。
这样一来,对class="item"
和class="nav"
这两个元素来说,【功能点的外观】就被独立出来了。
※像class="nav__title--l"
这样包含“__"或“-”的命名方法是基于BEM记法的。在这里的作用只是一种命名规范,比如为了明确地防止在元素class="item"
外发生css干扰。
【功能点的布局】代码编写方法
接下来介绍【功能点的布局】,为了设定各个组成部分的位置,我准备了一个盒模型。代码实现如下所示:
<html>
<head>...</head>
<body>
<div class="l-wrap">
<div class="l-main">
<div class="l-header"></div>
<div class="l-height-offset"></div>
<div class="l-side"></div>
<div class="l-cont">
<div class="l-cont__body"></div>
</div>
</div>
</div>
</body>
</html>
/** 在设定布局的代码中加上前缀“l-” **/
/** background, color, border等与外观有关的css不要写 **/
/** 感觉就像在编写只定义了大小和位置的透明盒子 **/
.l-wrap {
width: 100%;
height: 100%;
/** 像这样与外观有关的css不要写 **/
}
.l-main {
width: 100%;
min-height: 100%;
vertical-align: top;
}
/** 如果要写设定外观的代码,要通过不同的类名来写 **/
.main {
background-color: #fbfbfc;
}
.l-header {
position: fixed;
z-index: 100;
top: 0;
left: 0;
width: 100%;
height: 48px;
}
.l-height-offset {
height: 48px;
}
.l-side{
position: fixed;
z-index: 99;
top: 48px;
width: 230px;
height: 100%;
max-height: 100%;
}
.l-cont{
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
width: 100%;
padding-left: 230px;
margin: 0 auto;
}
.l-cont__body {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
width: 100%;
max-width: 1064px;
min-height: 80%;
padding: 48px 28px;
margin: 0 auto;
}
为什么这样写?
这段代码的目的是完成【功能点的布局】。此时与【功能点的外观】有关的css不能出现。感觉就像在编写只定义了大小和位置的透明盒子。
※像class="l-cont"
这样有前缀“l-”的类名,目的是表明这是用于布局的css。这种命名方式是对SMACSS记法的模仿。与模仿BEM记法时一样,它的作用只是一种命名规范,是为了明确地将【功能点的布局】独立出来所作的标记。
将【功能点的外观】嵌入【功能点的布局】上的结果
将上述【功能点的外观】嵌入【功能点的布局】上的结果如下所示:
简单的工作!
只需要将【功能点的外观】像积木一样嵌入到【功能点的布局】上就大功告成了。 将两者分离后,一方面修改外观的时候不会再出现打乱布局的情况,另一方面在添加/删减功能时也只需要增减积木块就行了。
再次总结
只要掌握了分离【功能点的布局】与【功能点的外观】这一技巧,就能编写出具有灵活性的代码
如果你是设计师、后端工程师等非前端工作者,因为被老板说“我想做个网站但人手不足,你来想办法写写代码吧!!”而开始写前端代码的时候,请一定要尝试这种方法。如果能因此减少你对前端代码的畏惧,让你能够自信地编写代码,那就再好不过了。