WEB UI篇——以结构化的方式写CSS
我的职业是码农,以前有人称这职业叫程序员或软件工程师,不过这些不重要,重要的是我这次写的东西和码农几乎不相干,我接触CSS的时间不长,2年多一点,并且只有在极端的情况下我才会自己动手写CSS,例如:需要挣些钱来养活自己,或者需要将外包出去的难看的前台重写。下面我将要向大家描述如何以层次-结构化的方式来写CSS。
众所周知,一个好的WEB UI工程师注重结构化的HTML+CSS代码,而不仅仅是还原之前的图片设计,这其中区别很大,前者能为代码美观及维护带来非常大的帮助,而后者,除了完成“任务”,几乎就是一团糟。
html代码经常以嵌套的方式出现,例如<body>中可能嵌套了<div>,<div>中又嵌套了<ul>,之后又嵌套了<li>,而li中可能再嵌套label,em,p,i,input,dl,dt,dd,....等等.总之我们将尽可能的组合这些html元素,以便思维更加清晰地展现页面各部分。
假设我们要设计一个注册用户的表单,效果如下:
我可能会有如下的HTML(HTML5):
第一种方式:
<div class="line">
<label class="lbl">用户名:</label>
<input class="txt" id="tbxUserName" />
<em class="em">*</em>
<span class="sp">用于登录。</span>
</div>
<div class="line">
<label class="lbl">邮箱:</label>
<input class="txt" id="tbxEmail" />
<em class="em">*</em>
<span class="sp">用于找回密码。</span>
</div>
<div class="line">
<label class="lbl">验证码:</label>
<input class="txt" id="tbxVerify" />
<em class="em">*</em>
<a class="va">看不清?换一张。</a>
</div>
</div>
相应的CSS代码如下:(CSS 2.0)
.lbl{width:140px;text-align:right;}
.txt{height:20px;border:#ff0000 1px solid;}
.em{color:#FF0000}
.lbl,.txt,.em,.va{float:left;}
第二种方式(HTML5):
<div>
<label>用户名:</label>
<input id="tbxUserName" />
<em>*</em>
<span>用于登录。</span>
</div>
<div>
<label>邮箱:</label>
<input id="tbxEmail" />
<em>*</em>
<span>用于找回密码。</span>
</div>
<div>
<label>验证码:</label>
<input id="tbxVerify" />
<em>*</em>
<a>看不清?换一张。</a>
</div>
</div>
CSS的代码如下(CSS 2.0)
#reg div label{width:140px;text-align:right;}
#reg div *{float:left;}/*让每一行的子元素乖乖向左上方挤,避免因各浏览器原因各元素水平不对齐*/
#reg div input{height:20px;border:#ff0000 1px solid;}
#reg div em{ color:#FF0000}
这就好比我们要建造一个小型金字塔,以现有技术,一般有两种方式,第一种就是从底部开始用石头开始堆,一直堆到顶部;第二种是直接建造一个模型,从顶部开个洞,然后用泵车从顶部浇注,最终成型。
比较两种方式,不难发现第一种比较原始,必须注意每一个细节,如果发现中间某处出现问题,需要仔细对照HTML文档与CSS文档,找出有问题的HTML元素及其样式表,另外,更重要的是还要对照该元素的上一层及其它相关的样式表。
而第二种,显然要好很多,一旦发现某个HTML元素样式有问题,我们只需找到其“金字塔”的顶部入口,然后找到其具体定义,对于少量的代码而言,这两者的区别还不是那么明显,而当文档达到一定数量后,这个区别就会相当明显了:前者令人痛苦,后者令人舒服。
当然,世上没有最好,只有更好,有些时候,我们可能需要将两者结合起来,例如,在其它页面的HTML代码中我有一个快捷登录框
出于方便我有了如下CSS定义:
之前看是完美的,但却留下了一个隐患,当其它的页面中再次出现ID为tbxUserName的input时候,效果就会受其影响,例如本文第一段代码。这时,我们就得要想办法规定好这个#tbxUserName的作用域,一般来说这样写:
这种写法被称为CSS的覆写。
采用结构清晰的方式去写CSS代码,会留下整洁的HTML页面,便于移植与重新布局,在修改的时候,我们只需要找到入口,就能轻易改写整个样式块;
而采用第一种混沌的方式去写CSS代码,结果会留下难以维护的HTML页面,一旦重新修改布局,所有的以class这种方式的样式全部都要改写,工作量甚至大于重新写。
另外,谈一下CSS的复用。
我们写每一行CSS代码,总指望它能被多次重复使用,简称“复用”,很多人明白这个道理,但实际过程中可能一不小心就写得很糟糕,当然很多美工会理直气壮地说“时间紧,钱又给的少,你叫我怎么办?”。我要说的是,只有你的品质上去了,才有资格和别人谈钱,至少我会给高品质的作品更高的报酬。我经常会以打工者的身份接到“改版”的任务,而我又经常外包给别人;我经常和雇主谈比较高的报酬,而我又对美工如此苛刻,我感觉自己是个奇怪的家伙。
谈到“复用”,这在各行各业都有表现,不仅仅在计算机领域。复用的重要性不言而喻,但为保证不跑题,这里不作赘述。
当然也有许多的情况下我们不能复用。
总的说来,以.xxx{}形式命名的style,都是期望复用的,以#xxx{}方式命名的style,不期望复用,而以tagName{}方式命名的style,则是期望有作用域的,如果它没有外层嵌套,那么它是全局作用域的。
还是以上面的注册表单为例,例如我们要给每一行后面的SPAN加上一些变化,当什么也不做的时候,就显示当前信息,并带有“!”号的前置图标,当输入错误的时候,显示出错内容,并显示“X”图标,当输入正确时,显示“√”图标。这时候,我必须复用一些代码来保证效果的完整,且不产生多余代码:
此示例中借助了一些简单的javascript脚本帮我们实现。
<div>
<label>用户名:</label>
<input id="tbxUserName" />
<em>*</em>
<span id="chkUNameResult" class="formMsgBox formMsg">用于登录。</span>
</div>
</div>
.formMsg{background:url(msg_bg.gif) 5px -102px no-repeat; height:22px;line-height:22px;padding-left:25px;font-size:12px;}
.formMsgErr{background-position:5px -22px;}
.formMsgSuc{background-position:5px -62px;}
var chkUNameResult = document.getElementById("chkUNameResult");
document.getElementById("tbxUserName").onblur = function(){
var json = {result:"",msg:""};
if(this.value == ""){
chkUNameResult.className="formMsgBox formMsg formMsgErr";
json.result = "Fail";
jsong.msg = "用户名不能为空";
}else{
chkUNameResult.className="formMsgBox formMsg formMsgSuc";
json.result = "Success";
}
setMsg(json,chkUNameResult);
}
function setMsg(json,dom){
dom.innerHTML = json.result == "Success" ? "" : json.msg;
}
</script>
最后,附上最后一个示例的文件:Demo.rar.此示例仅供参考,不代表其能用作商业代码.