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 id=”reg”>
    <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>
        <class=”va”>看不清?换一张。</a>
    </div>
</div>

相应的CSS代码如下:(CSS 2.0)

 

.line{height:40px;margin-top:10px;}
.lbl{width:140px;text-align:right;}
.txt{height:20px;border:#ff0000 1px solid;}
.em{color:#FF0000}
.lbl,.txt,.em,.va{float:left;}


第二种方式(HTML5):

 

<div id=”reg”>
    <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{height:40px;margin-top:10px;}/*以reg为起点,进行各子元素的查找*/
#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代码中我有一个快捷登录框

<input id=”tbxUserName” />



出于方便我有了如下CSS定义:

 

#tbxUserName{width:50px;border:red 1px solid;height:20px;}


之前看是完美的,但却留下了一个隐患,当其它的页面中再次出现ID为tbxUserName的input时候,效果就会受其影响,例如本文第一段代码。这时,我们就得要想办法规定好这个#tbxUserName的作用域,一般来说这样写:

 

#reg div #tbxUserName{width:100px;border:green 1px solid;}


这种写法被称为CSS的覆写。

 

采用结构清晰的方式去写CSS代码,会留下整洁的HTML页面,便于移植与重新布局,在修改的时候,我们只需要找到入口,就能轻易改写整个样式块;
而采用第一种混沌的方式去写CSS代码,结果会留下难以维护的HTML页面,一旦重新修改布局,所有的以class这种方式的样式全部都要改写,工作量甚至大于重新写。

另外,谈一下CSS的复用。
我们写每一行CSS代码,总指望它能被多次重复使用,简称“复用”,很多人明白这个道理,但实际过程中可能一不小心就写得很糟糕,当然很多美工会理直气壮地说“时间紧,钱又给的少,你叫我怎么办?”。我要说的是,只有你的品质上去了,才有资格和别人谈钱,至少我会给高品质的作品更高的报酬。我经常会以打工者的身份接到“改版”的任务,而我又经常外包给别人;我经常和雇主谈比较高的报酬,而我又对美工如此苛刻,我感觉自己是个奇怪的家伙。
谈到“复用”,这在各行各业都有表现,不仅仅在计算机领域。复用的重要性不言而喻,但为保证不跑题,这里不作赘述。
当然也有许多的情况下我们不能复用。
总的说来,以.xxx{}形式命名的style,都是期望复用的,以#xxx{}方式命名的style,不期望复用,而以tagName{}方式命名的style,则是期望有作用域的,如果它没有外层嵌套,那么它是全局作用域的。

还是以上面的注册表单为例,例如我们要给每一行后面的SPAN加上一些变化,当什么也不做的时候,就显示当前信息,并带有“!”号的前置图标,当输入错误的时候,显示出错内容,并显示“X”图标,当输入正确时,显示“√”图标。这时候,我必须复用一些代码来保证效果的完整,且不产生多余代码:
此示例中借助了一些简单的javascript脚本帮我们实现。

 

 

<div id=”reg”>
    <div>
        <label>用户名:</label>
        <input id=”tbxUserName” />
        <em>*</em>
        <span id=”chkUNameResult” class=”formMsgBox formMsg”>用于登录。</span>
    </div>
</div>

 

 

.formMsgBox{float:left;border:solid 1px #EB9C7D;margin-left:5px;padding-right:5px;}
.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;}

 

 

 

<script language=javascript>
    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.此示例仅供参考,不代表其能用作商业代码.

发表评论

电子邮件地址不会被公开。 必填项已用*标注