如果你還不知道 Flickr 是什麼玩意,那麼我這麼說吧:Flickr 是一個線上相簿網站... 這種講法好像有點太小看它了,總之是個非常強的相簿網站,提供你每月 20MB 上傳流量、最多顯示兩百張照片的免費空間。除此之外,它還提供方便的功能,讓你在自己的網誌上貼照片!相關訊息請參考以下網頁:
不過,今天的主角不是它 -- 只是要借用它的服務來做點變化,真正的主角還是 CSS 啦!
藉由 Flickr 的 badge 服務,我們可以在自己網誌上的邊欄放隨機相簿、讓訪客每次來都可看到不同的相片。在樂多 blog 邊欄放上 badge 一代的 HTML 版後,顯示的效果大概如圖一:

嗯,這樣是不難看,不過用點 CSS 還可以讓它更有趣點。要是當訪客將滑鼠游標移上某張照片時,可以產生不同效果的話,豈不美哉?所以,我們規劃了三階段的變身目標:
- 平常有黑色邊框,滑鼠移上時轉為橙色。
- 平常照片會稍微淡些,滑鼠移上時則恢復原狀。
- 平常的寬度為目前的 80%,滑鼠移上時則放大為 110%。
接下來我們就各個擊破,分別討論這三個目標的 CSS 寫作方法。
事前準備
我們在此採用 Flickr badge 一代的 HTML 版,為什麼不用二代呢?因為二代的程式碼以表格為基礎,對我們接下來要做的事情來說反而累贅;至於 Flash 版... 那就不用我說為什麼不採用了吧? :P 總之,我們採用 Flickr Badge 給的 No style 版程式碼,也就是只有 JavaScript 的版本,如下:
<script type="text/javascript" src="http://www.flickr.com/badge_code.gne?nsid=64165297@N00&count=4&display=random&name=0&size=thumb&raw=1"> </script>
每個人的程式碼多少會有點差異(帳號和所選參數不一樣),此處以四張照片的情況來說明。這段程式碼執行後,會在你的網頁上插入這樣的 HTML 碼:
<a href="http://www.flickr.com/photos/bobchao/16079419/"> <img src="http://photos12.flickr.com/16079419_573a86b504_t.jpg" class="flickrimg" id="flickrimg1"> </a> <a href="http://www.flickr.com/photos/bobchao/16104205/"> <img src="http://photos13.flickr.com/16104205_d34371af34_t.jpg" class="flickrimg" id="flickrimg2"> </a> <a href="http://www.flickr.com/photos/bobchao/16104174/"> <img src="http://photos13.flickr.com/16104174_f1b0590d40_t.jpg" class="flickrimg" id="flickrimg3"></a> <a href="http://www.flickr.com/photos/bobchao/16079415/"> <img src="http://photos13.flickr.com/16079415_b41e19cc4b_t.jpg" class="flickrimg" id="flickrimg4"> </a>
如果你使用 Firefox 瀏覽器,可以一次選取那幾張照片以後按下滑鼠右鍵,選擇 檢視選取範圍原始碼,即可看到程式碼真正執行後的結果。這段 HTML 非常簡單:四個 a 元素中各包著一個設為 flickrimg 類別的 img 元素,每張圖片也有專用的 id 屬性。瞭解架構後,我們便可以開始設計其樣式。
邊框變化
談到滑鼠移上效果,除了使用 JavaScript 的 onmouseover 等事件之外,也可以利用 CSS 的 :hover 擬似類別。所以邊框變化效果非常簡單,只要更動 .flickrimg:hover 的邊框色彩就好了。
<style type="text/css">
.flickrimg:hover {
border-color: #f80;
}
</style>
目前大部分的瀏覽器都能支援這種效果 -- IE 例外,因為它僅支援在 a 元素上套用 :hover 擬似類別。說到 a 元素,這些圖片的外圍不都正好有一個嗎?那麼只要轉個彎改以 a:hover img 當選取符,IE 就能支援這種效果了:
<style type="text/css">
a:hover img{
border-color: #f80;
}
</style>
不過這樣會換來另一個問題:這個隨機相簿位於網誌的邊欄區,換句話說只是網頁的一部份罷了;以 a:hover img 當選取符的影響層面太大(會影響整個網頁中的圖片連結),所以我們首先在這個 script 元素的外圍包上一個 div 元素,並將其 id 屬性設為 flickrimgs:
<div id="flickrimgs"> <script></script> </div>
接著再修改選取符為 #flickrimgs a:hover img,將影響範圍限制在相簿當中。
<style type="text/css">
#flickrimgs a:hover img{
border-color: #f80;
}
</style>
如果懶惰點,那這樣可以交差了,不過我們決定多做點變動:Flickr 送出的縮圖寬高都不會超過 100 像素,而本例的邊欄寬度為 190 像素,因此目前圖片在換行後是向右靠齊的。要使圖片置中,可以直接為 flickrimgs 設定 text-align: center;;不過,為了確保每張圖片各佔一列,我們首先讓 a 元素以 block 模式顯現,再為其設定 text-align: center;。完成的效果如圖二所示。
<style type="text/css">
#flickrimgs a {
display: block;
text-align: center;
}
#flickrimgs a:hover img{
border-color: #f80;
}
</style>

將連結設定以 block 方式顯示後,整個可按範圍寬度就變成母元素內容寬度的 100%。只要滑鼠移到範圍之中,圖片的邊框就會變色。
深淺變化
解決邊框後,接下來要處理圖片色彩的深淺變化。我們無法直接以 CSS 調整圖片明暗深淺的特性(至少目前沒有),不過可以利用支援程度尚可的 opacity 透明特性來製造類似效果。此特性可指定 0(完全透明)到 1(完全不透明)之間的數值,我們希望圖片平時不透明程度為 60%,當滑鼠移上時則變化為完全不透明。
#flickrimgs a img { opacity: .6; } #flickrimgs a:hover img{ border-color: #f80; opacity: 1; }
不過... 嘿嘿,不好意思,IE 目前還是不支援這個特性。為了照顧這位目前市佔率仍然領先的老兄,我們只好加上一個非標準的 IE 專用特性: filter。修改後的效果如圖三,IE 也能正常運作。(注意 filter 後面傳入的參數為百分比。)
#flickrimgs a img {
opacity: .6;
filter: Alpha(Opacity=60);
}
#flickrimgs a:hover img{
border-color: #f80;
opacity: 1;
filter: Alpha(Opacity=100);
}

當然,這麼一來的話你的 CSS 就無法通過標準驗證。在此我們的透明效果只是好看而已,放棄 IE 其實不打緊;不過如果你覺得很重要的話,就加上去吧。
放大效果
接著輪到本文件中比較有意思的部分了,我們希望圖片一開始僅顯示小圖,但在滑鼠移上時要有放大效果。同樣必須藉助 :hover 的力量,而且還要一點點國中數學... 別擔心,一點也不難的啊。
在動手之前,我們得先瞭解 Flickr 給的圖片長什麼樣子,觀察後發現範例中的橫式圖片(寬大於高)的寬度皆為 100 像素、高則是 67 像素。話說我們的目標是普通狀態的圖片寬度縮小為 80%,那麼這樣設定行不行呢:
#flickrimgs img {
width: 80%
}
如果你的瀏覽器標準支援的程度較為完善,應該可以發現這個區塊上頭已經跟你說是錯誤示範了(你看不到?還不快換瀏覽器...)。為什麼這樣做不行?因為這表示圖片寬度應為母元素寬度的 80%;目前母元素寬度為 190 像素,所以圖片會狂增至 152 像素寬,那當然是錯的。有些瀏覽器能在 CSS 裡用程式設計的手法動態運算特性值,不過為了相容性,就讓我們直接計算正確數字吧!經過計算,圖片寬度在普通狀況應該是 80 像素、滑鼠移上時則放大至 110 像素,如圖四所示。此時並不需要一併指定高度,瀏覽器會依據長寬比自動放大。
#flickrimgs a img {
opacity: .6;
filter: Alpha(Opacity=60);
width: 80px;
}
#flickrimgs a:hover img{
border-color: #f80;
opacity: 1;
filter: Alpha(Opacity=100);
width: 110px;
}

做到這裡的時候筆者發現一個怪現象:如果你在前一個步驟(半透明效果)中決定放棄 IE,那麼 IE 在這個步驟也會放棄你。如果不加上 filter 特性,IE 怎麼也不願意放大圖片,但是一加上去又好了... 目前沒精神去細究原因,總之如果要讓 IE 有放大效果,請加上 filter 特性。如果你有線索,請至留言版發言。
可以交差了嗎?仔細看就會發現還是不完美:滑鼠移上時圖片是放大了,但也因而把下方的內容又給擠下去啦!如果你覺得這樣很好玩,那其實就此停手也無妨,不過如果希望滑鼠的動作不會影響版面,此時就得來突發奇想一下。
我說這圖為什麼會向下推?到底是為了長高:寬度從 80px 增至 110px 的同時,高度也從 54px(67*0.8,小數點以下四捨五入)長到 74px(67*1.1),這就難怪下方的內容會被往下推 20 像素了。為了解決這個問題,我們將採用負的 margin 值:
#flickrimgs a:hover img{
border-color: #f80;
opacity: 1;
filter: Alpha(Opacity=100);
width: 110px;
margin: -10px auto;
}
設定負的上下 margin 值後,當滑鼠移上圖片(其實是連結)時,圖片的上緣會往上縮回 10px、與上方圖片重疊;同時,底部佔的空間也往上拉 10px、與下方圖片重疊。這樣就解決了多出來的 20px。
做到這裡的時候筆者又發現一個怪現象:不曉得是 Opera 的 bug 還是我做錯了什麼,到此 Opera 8 會開始不聽話。如果將滑鼠由下往上移,則顯示出的圖片會有缺角現象,怪的是從上往下或是左右兩側就沒這個問題。一樣不細究,如果你有線索請至留言版發言。
這才做了一半。由於現在圖片開始會相互重疊,那麼有個非常明顯的問題便隨之而生:誰在上面?就目前的狀況看來,圖片四號會蓋在三號上面、三號會蓋在二號上面,以此類推。所以,要是我們將滑鼠移到三號圖片上,那麼底部就有 10px 距離會被四號蓋住。為了解決這個問題,我們要敦請 z-index 出馬;這個特性值要是設定得越大,那麼元素就會在越上面 -- 或說是越前面?總之,只要把這個值設定得夠大,那麼便可確保元素不會被其他東西蓋住。z-index 得在 position 設定為 absolute(絕對定位)或 relative(相對定位)時才有用,我們便設定為 relative、不指定其他位置特性。成果如圖五所示。
#flickrimgs a:hover img{
border-color: #f80;
opacity: 1;
filter: Alpha(Opacity=100);
width: 110px;
margin: -10px auto;
z-index: 100;
position: relative;
}

至此左看看右看看、IE 看看 Firefox 看看都蠻好的,應該沒問題了吧?那可不...
借用 JavaScript 之力
如果你的照片都是橫式圖片,那到此可以收工去吃飯了;不過如果是直橫交雜,你應該已經發現問題:直式圖片的寬度原本只有 67px(高 100px),這會被我們硬設定為 80px、高度也因而變成 119px,遠高過橫式圖片;此外,滑鼠移上直式圖片時,寬度增為 110px、高度又長到 164px 了。高度差 45px,我們設定 -10px 的邊界根本不夠補,該怎麼辦呢?
來想辦法吧!摳摳摳摳(一休和尚的木魚聲)摳摳摳摳、噹~ 有啦!大概的點子是這樣:
- 為了統一,剛剛設定的寬度一律要換算成高度。本來這種直排的東西就該從高度著手,吃一次虧學一次乖。所以,普通橫式圖片高為 54px、滑鼠移上時變成 74px。
- 接著為直式圖片另外設定一個 pt 樣式類別、個別指定高度。普通直式圖片的高度為 80px,滑鼠移上時增至 110px、並設定 -15px 的上下邊界(瓜分 30px 落差)。
- 接著要 Flickr 告訴我他傳的哪張是橫的、哪張又是直的,並且把直式圖片標上 pt 類別。
前面兩點的樣式表如下,這些樣式接下來也不會改了:
#flickrimgs a {
display: block;
text-align: center;
}
#flickrimgs a img {
opacity: .6;
filter: Alpha(Opacity=60);
height: 54px;
}
#flickrimgs a:hover img{
border-color: #f80;
opacity: 1;
filter: Alpha(Opacity=100);
height: 74px;
margin: -10px auto;
z-index: 100;
position: relative;
}
#flickrimgs a img.pt{
height: 80px;
}
#flickrimgs a:hover img.pt{
height: 110px;
margin: -15px;
}
輕鬆愉快!不過第三點,Flickr 只冷冷地丟了句話給我:「你想太多了,辦不到!」難道這就注定了我們無法破關... 啊不對,無法破解這個難題嗎?還好 JavaScript 適時對我們揮了揮手,於是只要加上這段 script 程式碼就行了。
<script type="text/javascript">
function flickrimgPT(){
var i, imgObj = document.getElementById('flickrimgs').getElementsByTagName('img');
for (i=0; i<imgObj.length; i++)
if (imgObj[i].width < imgObj[i].height) imgObj[i].className += ' pt';
}
window.onload = flickrimgPT;
</script>
這段程式超出本文題旨,我只大概解釋一下:首先程式找出 flickrimgs 下所有的 img 元素,然後一個個察看其寬度;如果寬度小於高度,就把這張圖當作直式圖片、為其添加 pt 樣式類別。由於這段程式符合標準,所以支援 DOM 的瀏覽器都應該能正確執行(簡單說,命中率應該高達九成八)。加上 JavaScript 程式碼以後的效果如圖六。

所以你還等什麼?快為你的網誌加上隨機相簿吧 ;)
後記
事實上這樣的作法還是小有缺陷,因為 Flickr 並不是真的把每張圖片都變得大小相同,所以有時看起來還是有點出入。此外,moztw 論壇上的李大哥提醒:最後一個藉助 JavaScript 的作法要是碰上關閉 JavaScript 卻支援 CSS 的瀏覽器,那麼直橫交錯的圖片還是會亂掉... 經實驗結果,還好我們已經改設定 height 了,所以除了圖片比例不一有點醜之外是不怕亂的。
筆者找了幾種方法,試圖不藉助 JavaScript、以純 CSS 完成目標,可惜功敗垂成。辦法不是沒有(例如把 a 元素設為等寬高、那麼不管直式橫式都一樣),不過看起來總覺得差強人意,想想寫這篇文章已經夠累人,還是別虐待自己好了 :P 如果您有任何想法,歡迎至留言版發言,或寄信與我討論。
相關文章


