编写友好的Html和CSS代码

2014-06-27 · 25 min read

Html 和 CSS 写过不少(虽然我很不喜欢写),也使用过别的同事写的和第三方库的,在使用的过程中也渐渐对 Html 和 CSS 代码的“友好度”有了点认识。UI 设计出的图片,放在不同开发手里,即使最终效果差不多,但是结构、思想、质量可能会天差地别(可以从结构的合理性,可复用程度等方面看出)。从好的代码中可以看出开发人员天马行空的想象力,扎实的代码功底,丰富的经验和奇妙的想象力,更重要的是:用着舒心。下面从代码的“可用性”上,讲讲我实际开发过程中积累的认识,很多是一些基础和细节的东西,有疑义欢迎讨论。

一、合理的 Html 的结构#

先看一个很常规的导航栏:

后面一些栏目(例如后台管理),可能会根据情况显示隐藏,那么这个“竖线”就不是那么随意了,对比下面两种代码:

代码 1:

<ul>
  <li>首页<span>|</span></li>
  <li>栏目1<span>|</span></li>
  <li>栏目2<span>|</span></li>
  <li>栏目3<span>|</span></li>
  <li>栏目4<span>|</span></li>
  <li>栏目5</li>
</ul>

代码 2:

<ul>
  <li>首页</li>
  <li>
    <span>|</span>栏目1
  </li>
  <li>
    <span>|</span>栏目2
  </li>
  <li>
    <span>|</span>栏目3
  </li>
  <li>
    <span>|</span>栏目4
  </li>
  <li>
    <span>|</span>栏目5
  </li>
</ul>

两段代码差别很容易看出,那么哪个更合理呢?显然在当前的需求下,代码 2 更加合理,因为首页是固定不变的,直接写就好,后面的的栏目可能要读取后台内容循环输出,此时只要循环<li><span>|</span>{{name}}</li> 即可,无需做额外的判断(代码 1 要把最后一项的 span 去掉……添堵……)。

二、“内部消化掉”一些不和谐的样式#

继续说上面的导航栏,这次情况更加复杂,所有栏目都是可配置的。也行有的新手会想,那这下没辙了,只能循环<li> {{name}} <span>|</span></li> 然后找到最后一个<li> ,去掉里面的竖线。其实不然,完全可以使用border 代替竖线,在外层使用负的margin 抵消“多余”的竖线。

再看一个九宫格:

代码如下:

.wrapper {
  width: 300px;
  height: 300px;
  margin: 30px;
  border-right: 1px solid #ccc;
  border-bottom: 1px solid #ccc;
  overflow: hidden;
}
.wrapper div {
  width: 99px;
  height: 99px;
  border: 1px solid #ccc;
  float: left;
  margin: 0 -1px -1px 0;
}
<div class="wrapper">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

利用负的margin 将不和谐消化掉。查看在线 Demo

三、一些元素要“有所依托”#

就像<li> 必须写在<ul> 里一样,一些元素要“有所依托”,最常见的就是使用<div> 模拟复杂列表,对比下面的两种代码:

代码 1:

<!-- 顶部信息 -->
<div>...</div>
<!-- 列表 -->
<div>1</div>
<div>2</div>
...
<div>n</div>
<!-- 分页 -->
<ul></ul>

代码 2:

<!-- 顶部信息 -->
<div>...</div>
<!-- 列表 -->
<div class="list">
  <div>1</div>
  <div>2</div>
  ...
  <div>n</div>
</div>
<!-- 分页 -->
<ul></ul>

当然这是见仁见智的选择,但是我还是认为,从组件化等角度分析。多一层<div class="list"></div> 总是好的。另外一点就是方便 js 操作(也许这点更重要),下面是 weibo 的截图,他的 timeline 明显是<div> 模拟的复杂列表:

可以看到 feed list 的外层 div 上自定义了pagenum 属性方便 js 操作。

- – - – - – - – - – -

另外一个常见的例子就是内容由 js 输出的时候:

<p>一共300条记录...</p>

上例的记录数由 ajax 异步请求时输出,此时使用<span> 包裹一下,加上 id,就会方便很多(就算用 AngularJS 等 MVC 框架,也要有个元素标记ng-controller)。也许你会觉得:“这些在写 Html+CSS 的时候可能考虑不到,实际开发的时候,自己加个<span> 写个 id 就好了,不用这么矫情”,好吧,这只是简单的例子,如果<p> 标签里用<i> 显示了个图标,<span> 显示不同颜色的文字……你改怎么办?

Html 和 CSS 没有太多高深的技术,复杂的架构,高手和菜鸟比的就是经验,细节和想象力(感觉这是事实,高手高就再于习惯把每件事情做好一点,积小成大)

四、操作尽量集中在一个元素上#

直接上例子:

这是个很简单的表头,点击触发排序,修改小三角的颜色。在看看代码是如何实现的:

它是这么实现的,通过btn-upbtn-up1 这两个类来控制小三角的颜色。这样好吗?显然是不好的,首先用户的操作范围一定要大,点击事件肯定是绑定在<th> 上,这点毋庸置疑,那么合理的做法应该是这样的:

<tr>
  <th class="hand active">语文<i class="btn-up"></i></th>
  <th class="hand">数学<i class="btn-up"></i></th>
  <th class="hand">英语<i class="btn-up"></i></th>
</tr>

<th> 上用active 控制状态,这就是“操作尽量集中在一个元素上”。

五、表格使用百分比,不要“自适应”#

表格应该使用colgroupcol ,直接在 thead>th 上设置宽度 等方式,使用百分比控制每一列的显示比例,否则内容长度变化的时候,表格会“抖动”,有分页时更加明显。

六、细节考虑周全#

未雨绸缪,提前考虑好一些细节和边界条件,例如“暂无数据的提示”,“内容超长的处理方案”,“最小高度”等,细节才是影响用户体验的关键。

– 暂时写这么多,想到再补充,欢迎一起讨论