发新话题
打印

[方法技巧] CSS制作网页时的优化与技巧

CSS制作网页时的优化与技巧

使用css缩写 使用缩写可以帮助减少你CSS文件的大小,更加容易阅读。css缩写的主要规则请参看《常用css缩写语法总结》,这里就不展开描述。
0 r# `) N4 n; c& M  i; e' W0 [9 Q0 G/ e
  明确定义单位,除非值为0
2 S3 q4 P  k+ `' g8 e, E: _
# P8 d! y8 S' y& M  忘记定义尺寸的单位是CSS新手普遍的错误。在HTML中你可以只写width=100,但是在CSS中,你必须给一个准确的单位,比如:width:100px width:100em。只有两个例外情况可以不定义单位:行高和0值。除此以外,其他值都必须紧跟单位,注意,不要在数值和单位之间加空格。8 m( L# U; Z3 m$ T: n7 \
' e! I$ K- g& e& X8 B
  区分大小写# g# z4 m% x9 k+ b" ~5 B% ^5 f

+ V# ^" J& E1 N) B  当在XHTML中使用CSS,CSS里定义的元素名称是区分大小写的。为了避免这种错误,我建议所有的定义名称都采用小写。  y( A8 m( {) q( d" }/ h
+ W8 `9 V7 X; [
  class和id的值在HTML和XHTML中也是区分大小写的,如果你一定要大小写混合写,请仔细确认你在CSS的定义和XHTML里的标签是一致的。6 S  H9 p# q7 V+ s  p6 ]7 o

/ {& N& W  D8 y2 G9 F0 [  取消class和id前的元素限定
. m4 K. c4 U( x$ G; \8 d: i- S. ^( N! U* d6 f4 n* s! T) g& Y
  当你写给一个元素定义class或者id,你可以省略前面的元素限定,因为ID在一个页面里是唯一的,class可以在页面中多次使用。你限定某个元素毫无意义。例如:" s, {# X6 v/ i- {2 F0 r/ ]
* e  ~6 F" g, A( r7 R% ^
div#content { /* declarations */ }
% X6 I7 D8 I; T% ^* ^  Vfieldset.details { /* declarations */ }
$ T- j5 {" L: g$ l$ w
4 c$ u( o) L( b& @" i  可以写成! k% N: H4 \" ^$ P# A

1 o5 j3 [  `! E! K+ H#content { /* declarations */ }
5 S; m7 Y4 s) I# K5 H, i. A.details { /* declarations */ }
+ V! Z2 Y3 m% r/ {- f/ Y' F: f* f+ D3 L/ p" L
  这样可以节省一些字节。
. N: A' |% G) [; y! t  l& ~. [
7 G1 P7 h, D" ~1 A1 W) g* m  默认值1 p+ l4 @7 e4 Q' r+ B/ e0 x- x6 Q
9 q% M# r2 r$ _! i0 R" `; T" {0 W
  通常padding的默认值为0,background-color的默认值是transparent。但是在不同的浏览器默认值可能不同。如果怕有冲突,可以在样式表一开始就先定义所有元素的margin和padding值都为0,象这样:/ ?' b1 o3 A3 L. Q
2 h' }7 m/ N" Q7 v
* { : U. d) D& R. m6 _) O% h
margin:0; ; k) F3 U/ X; m1 B! L
padding:0;
3 D, i+ r4 B; u1 x} 0 v/ S+ h, s! m# f
) B- w0 _! T% q- f/ j2 X! V9 `4 D5 _
  不需要重复定义可继承的值$ l+ z# s) e( o6 \, @; h
9 P0 s8 R  }( H" E( j9 @
  CSS中,子元素自动继承父元素的属性值,象颜色、字体等,已经在父元素中定义过的,在子元素中可以直接继承,不需要重复定义。但是要注意,浏览器可能用一些默认值覆盖你的定义。4 E+ ?; p; J$ @+ l3 }; O4 o

! J$ F6 ?! x  Y7 `  最近优先原则
9 z0 z& Z5 k) l; w% P2 j! N, @5 G) T- S. R, V
  如果对同一个元素的定义有多种,以最接近(最小一级)的定义为最优先,例如有这么一段代码
' ]+ X& Y0 }* g2 _+ XUpdate: Lorem ipsum dolor set在CSS文件中,你已经定义了元素p,又定义了一个classupdate5 W4 w6 v. R5 y0 y! c3 ^9 \
! B2 L+ o" r# g. M2 d
p { + v* W. w3 ]& M4 H, W0 b
margin:1em 0; % @- `4 v. r0 ]/ ?* W( S2 C4 j7 G$ _9 s
font-size:1em; $ D" T: q$ ~9 }7 K8 w% n
color:#333; + H- G0 _; I. d2 U. y/ g0 y  u# I
}
- U' V. t4 R8 a2 }+ E5 T/ X.update { ; ~" R1 t) @' P  H$ r2 _- D* j1 n
font-weight:bold; 2 D1 q5 N8 Q' K0 V# _% P! b3 f5 y& Q
color:#600; 3 j. E$ a2 e% z; `9 [% V; M
}  
' W2 c* c5 ~! P' t# Y3 z" A) R( p* {* D7 p4 k, |1 P0 H  i3 V
  这两个定义中,class=update将被使用,因为class比p更近。你可以查阅W3C的《 Calculating a selector’s specificity》 了解更多。5 Y: x9 U/ s3 ]: P! N6 n

) v$ i1 X. B" _# E  多重class定义/ Y  O4 c( q6 \0 f% A  d

4 k' q! l$ s3 z  ]9 b: ?  一个标签可以同时定义多个class。例如:我们先定义两个样式,第一个样式背景为#666;第二个样式有10 px的边框。
+ v+ l+ d5 U) n( o- w. C7 V6 w8 p* r& k1 f$ a9 Y+ P8 ]
.one{width:200px;background:#666;}
5 g% n3 u9 i  o: s9 L8 O4 q0 R& g.two{border:10px solid #F00;}
8 ?% @: H* Z2 h+ ~7 w8 x1 x- V# t" J0 i1 e! i2 ~" b
  在页面代码中,我们可以这样调用8 x6 o. d4 |$ x9 g

2 O$ G8 R# R5 d* K- a8 s. n<div class=one two></div>
5 s4 S# t: z2 D9 S# B! O$ ?; O1 ~' ^4 s
  这样最终的显示效果是这个div既有#666的背景,也有10px的边框。是的,这样做是可以的,你可以尝试一下。
3 q1 {8 U2 x" p: z2 G
4 H8 t+ L' Z: G8 l+ E$ [, [8 Z( q  使用子选择器(descendant selectors)
" {0 Y) d8 P5 n  `4 ?3 m
8 }2 c: R. z7 K8 c& a  CSS初学者不知道使用子选择器是影响他们效率的原因之一。子选择器可以帮助你节约大量的class定义。我们来看下面这段代码:
- E1 y! c' Q- H8 w2 S  V
+ \  i2 Y2 ^1 g( \<div id=subnav>
# \! U6 y. v3 `0 p. ]+ _# H' k<ul>
, u( g. k" P4 M/ L$ w: ]4 H5 c0 t<li class=subnavitem> <a href=# class=subnavitem>Item 1</a></li>>
: w; T/ E" D1 d9 \" g; `<li class=subnavitemselected> <a href=# class=subnavitemselected> Item 1</a> </li>
* O6 v) [) h% t4 B& W, K  @# B" J<li class=subnavitem> <a href=# class=subnavitem> Item 1</a> </li>
. s7 h1 I1 a4 @9 v</ul> 6 n7 V7 B# \; K8 J3 W  o$ o) D8 x% v5 Z1 F
</div>
& k4 }) t  \7 \+ K0 F$ s& ~
$ ]( E8 Y. I# [) a* r% I6 I# u8 v& ~; O  这段代码的CSS定义是:
# e& n- h5 B* T: X" y- B+ j2 B! n% ^$ E3 i% U, w# q$ z; R! n  r
div#subnav ul { /* Some styling */ }
" f' E1 Q) D! Z1 g5 Y% hdiv#subnav ul li.subnavitem { /* Some styling */ } ( v* w8 k4 R4 l4 U/ L# ]6 ?# `
div#subnav ul li.subnavitem a.subnavitem { /* Some styling */ }
& f6 O1 b+ o/ H' [# c% H  B& vdiv#subnav ul li.subnavitemselected { /* Some styling */ } " t& `6 D# F. ?) \
div#subnav ul li.subnavitemselected a.subnavitemselected { /* Some styling */ } ) E6 D& k5 N1 J& O! R
- z, E6 u$ R, @9 v5 H* p! p5 q
  你可以用下面的方法替代上面的代码
3 G" ^' e# }$ ~$ x$ |5 y/ c7 A; v4 T/ b- ?
<ul id=subnav> 8 p" i' w5 f* t3 o
<li> <a href=#> Item 1</a> </li>
' V+ M' z" E$ R& J; t2 `$ t<li class=sel> <a href=#> Item 1</a> </li> 2 H  _3 W* F( f; u+ m8 O* [
<li> <a href=#> Item 1</a> </li> 2 w7 y3 f5 {) l
</ul> 4 `) T2 b- N/ ^3 R
$ K8 e2 {$ W7 O( M$ l8 X2 y7 M
  样式定义是:
! d: S# s  O4 f6 n5 u& x3 m; v/ @1 I5 E5 M  V+ H" ?
#subnav { /* Some styling */ }
+ Y2 r( @9 I. e; k#subnav li { /* Some styling */ } ) Y$ ]! N5 u3 M* i5 v
#subnav a { /* Some styling */ }
# v& w# G. s5 G" D5 B#subnav .sel { /* Some styling */ } ' h) F4 C1 m! \' b; r9 |" b! E4 N% G
#subnav .sel a { /* Some styling */ }
( V7 X% e0 a7 O
9 g) J7 O: O7 X  用子选择器可以使你的代码和CSS更加简洁、更加容易阅读。( j& o& C! q; Z

* J" {: e2 e8 h- l  不需要给背景图片路径加引号0 H/ D% d9 y& e' K) V# T
  P/ f! V" }1 t7 P# h) {
  为了节省字节,我建议不要给背景图片路径加引号,因为引号不是必须的。例如:
4 R! g( r/ R  S
; z- H6 G# i2 R1 Z7 hbackground:url(images/***.gif) #333; 2 e8 i" p" u' D3 B& N

; J- v: ^) \( n1 @4 H9 }  可以写为
0 B, @: p4 N( m0 m4 b& a$ a/ i) @2 R0 h& j9 }8 y$ p! c0 j
background:url(images/***.gif) #333; ; ]2 f& K4 a+ k9 }

3 r8 M% o8 R2 o" b  如果你加了引号,反而会引起一些浏览器的错误。
2 m4 t; p5 ^. |
2 A+ n8 p4 h2 p+ w  k  .组选择器(Group selectors)
  S  w. i* x3 i) O* X$ [& N
# u1 D5 w6 w+ u. n  当一些元素类型、class或者id都有共同的一些属性,你就可以使用组选择器来避免多次的重复定义。这可以节省不少字节。 7 x, X1 a- x8 o. f; F! [
1 }* u7 C& L! |. N( o/ E5 k! Q7 j
例如:定义所有标题的字体、颜色和margin,你可以这样写:
- _* u/ f" ^! U; e5 y; V( z( |- h  ~' Y/ n* P1 N( e+ f, ~& T
h1,h2,h3,h4,h5,h6 { : A& O. ]. ^' P
font-family:Lucida Grande,Lucida,Arial,Helvetica,sans-serif;
8 _- T1 ^' Q3 V6 ~+ Acolor:#333; ; [. ?1 T9 q% \4 y5 A. s
margin:1em 0;
6 ]9 c- A: N; Z' e0 |}
9 b( N. g/ ~+ ?2 W0 W5 s
% d4 b: p! M0 C/ B6 h6 G, Y  E  如果在使用时,有个别元素需要定义独立样式,你可以再加上新的定义,可以覆盖老的定义,例如:, i$ k' h% j( |& ?- N

! N( Z$ }5 R- m  ch1 { font-size:2em; }
* p5 V5 ^: V' m/ Ih2 { font-size:1.6em; }
- C1 z$ Q# u# [7 Q/ Z" e! [
' j0 M& c; a$ V; l0 I  用正确的顺序指定链接的样式8 {9 g) e, c4 [0 m- z: L# P0 E/ R: x

* E. n. n7 I5 u4 N9 s  当你用CSS来定义链接的多个状态样式时,要注意它们书写的顺序,正确的顺序是::link :visited :hover :active。抽取第一个字母是LVHA,你可以记忆成LoVe HAte(喜欢讨厌)。为什么这么定义,可以参考Eric Meyer的《Link Specificity》。& U# u% N$ V' f

$ v9 Y+ O; ^0 c* v3 Y  如果你的用户需要用键盘来控制,需要知道当前链接的焦点,你还可以定义:focus属性。:focus属性的效果也取决与你书写的位置,如果你希望聚焦元素显示:hover效果,你就把:focus写在:hover前面;如果你希望聚焦效果替代:hover效果,你就把:focus放在:hover后面。
, i& B- O% q/ b4 O* B2 {/ C! K& E: c
  清除浮动2 @' V6 \# J6 e! l9 X9 O
( `# v8 O- H5 R9 n9 s/ M
  一个非常常见的CSS问题,定位使用浮动的时候,下面的层被浮动的层所覆盖,或者层里嵌套的子层超出了外层的范围。6 O: l* I. D, U1 f

- Z- F% y8 X" r" q; Z  通常的解决办法是在浮动层后面添加一个额外元素,例如一个div或者一个br,并且定义它的样式为clear: both。这个办法有一点牵强,幸运的是还有一个好办法可以解决,参看这篇文章《How To Clear Floats Without Structural Markup》(注:本站将尽快翻译此文)。
. w- [& q, v0 m( s- }
' n) c7 E' n; ~. j- G  上面2种方法可以很好解决浮动超出的问题,但是如果当你真的需要对层或者层里的对象进行clear的时候怎么办?一种简单的方法就是用overflow属性,这个方法最初的发表在《Simple Clearing of Floats》,又在《Clearance》和《Super simple clearing floats》中被广泛讨论。
# n3 N$ L+ d1 |2 A4 o上面那一种clear方法更适合你,要看具体的情况,这里不再展开论述。另外关于float的应用,一些优秀的文章已经说得很清楚,推荐你阅读:《Floatutorial》、《Containing Floats》和《Float Layouts》
  T6 T3 y  h5 W0 p  W+ L! M, l2 }7 X! ?6 s9 ?4 u% Z1 R+ j
  横向居中(centering)
; L% Z2 G4 v2 v/ w# r/ G
! i7 G9 t$ M& C- W7 {8 h7 I  这是一个简单的技巧,但是值得再说一遍,因为我看见太多的新手问题都是问这个:CSS如何横向居中?你需要定义元素的宽,并且定义横向的margin,如果你的布局包含在一个层(容器)中,就象这样:
! B: P) t3 P9 z( t! S9 H: q2 I- Z: q2 P; U
<!-- 你的布局这里开始 -->5 I9 P) }3 o& L3 K3 F% Q8 D
你可以这样定义使它横向居中:
% c; x2 A. r! x/ l+ _#wrap { 9 a/ a! J" U) Q4 _; U3 t# T) F0 r
width:760px; /* 修改为你的层的宽度 */ ! A1 O$ ?  {8 _  E5 v
margin:0 auto; 6 |/ j6 p& o  x3 F
} 3 |% [/ P/ B! {
# Y- `# Q' Y3 M; S
  但是IE5/Win不能正确显示这个定义,我们采用一个非常有用的技巧来解决:用text-align属性。就象这样:$ ]/ c- |7 u, y2 n7 n7 {
+ ]. y, k) v# f. s
body { 1 }. c) |- H/ M( R0 I/ q
text-align:center;
# \3 s$ N5 F1 b' P0 A} ! F/ s! [# e3 l
#wrap { ; \$ {, v& u/ S! P3 @
width:760px; /* 修改为你的层的宽度 */ $ s& _# p" H4 u  v% g; r5 v
margin:0 auto; : A$ f* w+ H; r! v& j/ x
text-align:left; / E2 D& Z! y1 m
}
) ]) c0 e5 L3 ?6 }# H6 [$ z2 F* \6 q7 a# {& e  X
  第一个body的text-align:center; 规则定义IE5/Win中body的所有元素居中(其他浏览器只是将文字居中) ,第二个text-align:left;是将#warp中的文字居左。
* ?# N# `& e* D/ f: i6 _' d& q5 C1 b& e+ C
  导入(Import)和隐藏CSS6 a3 K  c/ R3 g3 g3 I
- Q; m; ^1 f/ w0 N- v' W/ a
  因为老版本浏览器不支持CSS,一个通常的做法是使用@import技巧来把CSS隐藏起来。例如:
* C; ^' D5 L1 C3 J5 r" p$ z& F! C5 R7 J5 R9 R) T8 @3 n0 {
@import url(main.css);
9 i0 Z/ o7 L, {. P" Z% E; D3 o/ Z) _0 E- }4 g1 }
  然而,这个方法对IE4不起作用,这让我很是头疼了一阵子。后来我用这样的写法:; u; g0 i% L" G/ t7 X- l
% Z$ d* J3 P3 x' m% [
@import main.css;
; M! u1 ?. Q( W
$ O' D# O. o. a6 c" q  这样就可以在IE4中也隐藏CSS了,呵呵,还节省了5个字节呢。想了解@import语法的详细说明,可以看这里《centricle’s css filter chart》4 |# c6 T" j% _$ ?, W+ k+ O

! Z, J% U. u* E. V8 R+ S  针对IE的优化
- ~0 |* |  H+ \) p/ H! v( P: q3 h
+ l% R- z3 Y8 b) U  有些时候,你需要对IE浏览器的bug定义一些特别的规则,这里有太多的CSS技巧(hacks),我只使用其中的两种方法,不管微软在即将发布的IE7 beta版里是否更好的支持CSS,这两种方法都是最安全的。* L# c$ d+ a, _! p
3 Z3 p* x$ G& \: r2 d$ E7 m1 e
  1.注释的方法 0 w3 f  o4 F) H8 K! C

2 P9 ~( L; j/ t2 |  (a)在IE中隐藏一个CSS定义,你可以使用子选择器(child selector):
6 D3 [$ Q, c' A  M3 ^+ ]6 _9 `% q! a. c& @$ b0 [! R
html>body p {
+ _' ^. N1 \$ Z. @$ q4 f/* 定义内容 */
, Y5 g# A4 \( p* U; R: _}
0 e$ B$ S) _) b7 W" \1 g+ z5 T9 H( c
4 [2 I5 l3 i# z1 P; v. w8 _  (b)下面这个写法只有IE浏览器可以理解(对其他浏览器都隐藏) # W; R: q3 w8 x6 \: z9 j4 ]0 e

# k7 z& f2 \$ [* html p {
! ]2 a: j6 }) T! j5 t) t/* declarations */ . U# V) {0 C: _
}
5 `% G* i+ n9 q: I, [8 a0 |2 ?  N7 Q1 A) L2 l: Q6 n1 Y
  (c)还有些时候,你希望IE/Win有效而IE/Mac隐藏,你可以使用反斜线技巧:
! J& M( ^* T- r$ h2 i  V: s  ]9 {: A% {
/* */
+ P, U7 _" s# {- g* html p {
" j) L+ J4 k, j: u" N& e1 w  rdeclarations
# p* b% h2 }3 t$ E}
. g4 o; K+ M& R) N: s% |8 s/* */   W6 h4 Q; u7 o; a$ j* M5 u

9 ^6 a8 W$ {6 n$ m3 K* {6 Q/ Y  2.条件注释(conditional comments)的方法 ( I4 Q0 z, M3 d4 \# o
# W# }7 z3 G: C% p
  另外一种方法,我认为比CSS Hacks更加经得起考验就是采用微软的私有属性条件注释(conditional comments)。用这个方法你可以给IE单独定义一些样式,而不影响主样式表的定义。就象这样:
" r# q5 G1 B2 ^8 }. H& n
7 W* I) g" T  z- t4 J3 K<!--[if IE]>
2 b* D7 N* j+ j. K0 G<link rel=stylesheet type=text/css href=ie.css /> 5 P. |, U% |# |" {5 u( g
<![endif]-->
( q; E! j9 }+ Q$ r, }" K; t2 H, F
; v* v# S/ ~' B9 d. c  调试技巧:层有多大?# [9 c. Q) G6 h

+ \" O) u  r! i2 R  当调试CSS发生错误,你就要象排版工人,逐行分析CSS代码。我通常在出问题的层上定义一个背景颜色,这样就能很明显看到层占据多大空间。有些人建议用border,一般情况也是可以的,但问题是,有时候border 会增加元素的尺寸,border-top和boeder-bottom会破坏纵向margin的值,所以使用background更加安全些。 # \6 c& d! \% Z- T, U

* ^7 N( w9 r4 z% [/ O! s' X" h  另外一个经常出问题的属性是outline。outline看起来象boeder,但不会影响元素的尺寸或者位置。只有少数浏览器支持outline属性,我所知道的只有Safari、OmniWeb、和Opera。
4 o) I- T. |  ~; P2 {: y, L; M. t3 v; m4 m( }1 b. A
  CSS代码书写样式
& Q) F7 X) D/ h7 C0 B% x' o
2 R# T' R% n, {$ S+ ^  在写CSS代码的时候,对于缩进、断行、空格,每个人有每个人的书写习惯。在经过不断实践后,我决定采用下面这样的书写样式:
" J7 D. N/ @$ X2 X
0 ]3 k2 {1 T1 a# R( ^5 T- gselector1,
( x0 {+ d9 A3 o, N$ _% s# Z: Mselector2 {
7 Y! L$ y, [7 J9 p* y3 Pproperty:value;
8 s* y7 r( v. ]6 k5 L" M8 f0 ]} 2 [3 X0 \; f# a& j% |! b

) O( V) q$ [6 ]8 k6 c, u  当使用联合定义时,我通常将每个选择器单独写一行,这样方便在CSS文件中找到它们。在最后一个选择器和大括号{之间加一个空格,每个定义也单独写一行,分号直接在属性值后,不要加空格。
: a3 K' D1 R, p1 k4 t' U+ w  l: u3 i4 z: m
  我习惯在每个属性值后面都加分号,虽然规则上允许最后一个属性值后面可以不写分号,但是如果你要加新样式时容易忘记补上分号而产生错误,所以还是都加比较好。) e3 G5 {9 o; W5 c% e' }! Y& `

7 }5 r5 T6 z4 Z8 z  B& q! w, ]  最后,关闭的大括号}单独写一行。空格和换行有助与阅读
发新话题