2009/03/19

CSS 小精靈

在網頁中,每一個 IMG 元素都會產生一個 HTTP 服務要求。如果你的網頁有十張圖,就會產生 10 個 HTTP 服務要求。依據 Yahoo! 的研究,減少 HTTP 服務要求可以加快網頁的回應速度。CSS 小精靈(CSS Sprites),這個技術源自早年 2D 電玩所使用的小精靈圖片。這個方法就是將十張圖合成一個大圖,然後再用 background-image, background-position 選取要用的圖。如此只要一個 HTTP 服務要求就可以將圖讀下來,

CSS 小精靈在一般流量小的網站可能看不出效益,反而增加網頁設計師的工作量。可是對大流量的網站來說,速度的微小改善,一天下來都可能累積成可觀的量。事實上, Yahoo! 與 Google 都有用到此方法。如果你要到大公司工作,千萬不要說你不會 CSS sprites 喔!

實際使用發現,大圖的檔案大小通常會比小圖各自存檔的總合還小,這主要是因為每一個小圖都要一個顏色表;而在大圖中,則是共用一個顏色表。

下面範例中大圖包含了四個小圖。小圖因為位置放的不好,所以 background-position 調的很辛苦,所以大圖設計良好很重要:

  1. 小圖要水平放置,以減小大圖的高度,通常這樣可得到較小的圖檔。小圖之間距要小;大圖的長寬減小,則可以減少展圖時所需記憶體。
  2. PNG 檔用作背景圖,其透明與漸層效果,在 IE6 會看不到。如果大圖只用到 256 色,可以存成 PNG8 檔案格式,就不會有前述問題。用 PNG8 檔優於 GIF 檔。
  • 風格用法:

    <style type='text/css'>
    .spr {display:inline-block;
          vertical-align:middle;
          margin:4px;
          width:31px;
          height:31px;
          background:no-repeat url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEia62ajhtQD4_RY3vWB_NzOJbsSiJa1LTR8B3MtOueww7Egw7Mt7W4IMFkDjLRqtEXfFhCS1M675B-idVYjGT1Uot2IrAqCnNa9vEdH0e2fjI2GKoCQMjQyKz8vKHspRy8AdaZQ4vBXi9fy/s200/sprite.PNG);
         }
    .spr#lnk1 {background-position:-28px -42px}
    .spr#lnk1:hover
         {background:no-repeat url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEia62ajhtQD4_RY3vWB_NzOJbsSiJa1LTR8B3MtOueww7Egw7Mt7W4IMFkDjLRqtEXfFhCS1M675B-idVYjGT1Uot2IrAqCnNa9vEdH0e2fjI2GKoCQMjQyKz8vKHspRy8AdaZQ4vBXi9fy/s200/sprite.PNG);
          background-position:-29px -128px;
         }
    .spr#lnk2 {background-position:-121px -42px}
    .spr#lnk2:hover
         {background-position:-117px -130px;}
    </style>

    <img src='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEia62ajhtQD4_RY3vWB_NzOJbsSiJa1LTR8B3MtOueww7Egw7Mt7W4IMFkDjLRqtEXfFhCS1M675B-idVYjGT1Uot2IrAqCnNa9vEdH0e2fjI2GKoCQMjQyKz8vKHspRy8AdaZQ4vBXi9fy/s200/sprite.PNG' />

    <ol>
    <li><a class='spr' id='lnk1' href='http://gamelily.blogspot.com/2008/11/blog-post_7559.html#ra'></a>好玩遊戲。
    <li><a class='spr' id='lnk2' href='http://gamelily.blogspot.com/2008/11/blog-post_7559.html#sh'></a>射擊遊戲。
    </ol>

  • 執行結果:

    1. 好玩遊戲。
    2. 射擊遊戲。
  • 調出來的小圖,在不同瀏覽器有小差異。
  • :hover 效果在個人電腦測試正常,移到部落格就沒了,這是受到部落格設定的 A:hover 影響。解決方法是在 .spr#lnk1:hover 加上 background:url()。原本 background:url() 只要在 .spr 宣告一次就可以通用了。在 .spr#lnk2:hover 沒有加 background:url(),這是要示範成功與失敗的情形。

使用 IMG 元素與 clip 特徵來作小精靈。此法近年由 Jennifer Semter 提出。此法中 clip 特徵必須配合 position:absolute 使用;所以元素外要加一層 DIVA 元素,並且宣告 position:relative。下面練習發現此法調座標位置比前面的方法辛苦。下例中的 .jen:hover 拿掉的話,IE6 沒法作 :hover 效果。

  • 風格用法:

    <style type='text/css'>
    .jen {display:inline-block;
          vertical-align:middle;
          margin:4px;
          width:31px;
          height:31px;
          position:relative;
         }
    .jen:hover {border:none}
    .jen#lnk3 IMG
         {position:absolute;
          border:none;
          padding:0;
          top:-42px;
          left:-28px;
          clip:rect(42px 59px 73px 28px)
         }
    .jen#lnk3:hover IMG
         {top:-128px;
          left:-30px;
          clip:rect(128px 61px 159px 30px )
         }
    .jen#lnk4 IMG
         {position:absolute;
          border:none;
          padding:0;
          top:-42px;
          left:-121px;
          clip:rect(42px 152px 73px 121px)
         }
    .jen#lnk4:hover IMG
         {top:-131px;
          left:-118px;
          clip:rect(130px 148px 161px 117px)
         }
    </style>
    <ol>
    <li><a href='http://gamelily.blogspot.com/2008/11/blog-post_7559.html#ra' class='jen' id='lnk3'>
      <img src='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEia62ajhtQD4_RY3vWB_NzOJbsSiJa1LTR8B3MtOueww7Egw7Mt7W4IMFkDjLRqtEXfFhCS1M675B-idVYjGT1Uot2IrAqCnNa9vEdH0e2fjI2GKoCQMjQyKz8vKHspRy8AdaZQ4vBXi9fy/s200/sprite.PNG' /></a>好玩遊戲。
    <li><a href='http://gamelily.blogspot.com/2008/11/blog-post_7559.html#sh' class='jen' id='lnk4'>
      <img src='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEia62ajhtQD4_RY3vWB_NzOJbsSiJa1LTR8B3MtOueww7Egw7Mt7W4IMFkDjLRqtEXfFhCS1M675B-idVYjGT1Uot2IrAqCnNa9vEdH0e2fjI2GKoCQMjQyKz8vKHspRy8AdaZQ4vBXi9fy/s200/sprite.PNG' /></a>射擊遊戲。
    </ol>

  • 執行結果:

    1. 好玩遊戲。
    2. 射擊遊戲。
  • 上面調出來的小圖,在不同瀏覽器有小差異。
  • 上例雖然用了兩次 IMG,但是一張圖只會下載一次,然後存入本機的接收磁碟區(Cache)中,第二張圖會由接收區讀取。