2013年2月23日 星期六

說好的不寫寬度呢?那些 inline-block 區塊的處理方式

放了個年假
大家有沒有很開心呢~~
但今天的課題有點嚴肅 ( 哪來的嚴肅 ! )
讓我們一起來看看 CSS 的世界到底發生了甚麼事

傳說中每個 HTML 標籤都有一個詛咒
這詛咒決定他們的樣貌與能力
如果抵抗這個詛咒,那個他就會 .... 
其實是不會怎麼樣啦 = =
今天要談的是屬性 CSS 的標籤 顯示模式 (display)
首先奉上 W3C 說明頁 (不要問英文在寫甚麼~~)

不知道大家有沒有這種疑惑
為什麼 div、p、span、table... 等等的標籤會長的那個樣子?
其實這些都是在規格書當中,官方決定了各個標籤的 display 屬性
並定義各種值的顯示方式

這邊列舉幾個標籤的顯示模式
有興趣的同學可以利用 瀏覽器 的 console panel 來觀察每一個標籤
但是各個標籤的預設 顯示模式 通常不會出現在 css 的觀察面版中
要開啟標籤樣式計算結果中 (那邊也可以看到其他的預設樣式喔)
Chrome 為例 ( Firefox請用 Firebug )














上篇中,我們提到了利用 divprofile 資訊的排版案例
其實就是 display:block 的範例

而今天要說的就是懶人...不對  比較高明 的排版方式 
在 display:inline-block 不指定寬度的情況下,正確顯示的案例

我們先來看看這個需求







有沒有覺得這很面熟
其實這是 Facebook 塗鴉牆的回應區塊
留言部分的區塊架構 HTML 可以這樣寫
<div class='comment clearfix'>
    <img class='photo' src='logo.jpg' />
    <textarea class='reply' placeholder='留言...'></textarea>
</div>

首先 imgtextareadisplay 預設都是 inline-block
這種 display 顯示方式有幾個特點
  1. 可能預設會有寬高 (通常每個流覽器定義不同),且大小不受上層 DOM 元素影響
  2. 可能預設會有 marginpadding
  3. 並排的元素會在單行中顯示
我們先設一些樣式

.comment {
    background:#edeff4;          /* 只是和 fb _背景一樣而已 */
    padding:4px;
    width:398px;                 /* fb 的寬度 */
    outline:0;                   /* 滑鼠 focus 時不要出現框線 (新流覽器才有) */
}

.photo {width:32px; height:32px;}

.reply {
    vertical-align:top;          /* 垂直對齊:上方 */
    border:1px solid #bdc7d8;
    width:355px;
    ...
}


主要這樣就差不多了,詳細請看 http://jsfiddle.net/zQVg8/3/

CSS 的故事就是要沒事找事做 ... 不對
是希望能探討各種寫法的優劣,找出能適應各種情況的 CSS 寫法
因此這寫法到底會出甚麼問題呢?

問題就出現在 .comment.reply 樣式中的 寬度 (width) 屬性
網頁架構中,設寬高是件很麻煩的事 (詳情請參照上篇)

首先現實中的 .comment 應該不會設寬
因為外層應該還會有一個容器 wrapper
包住整個塗鴉牆和其他哩哩摳摳的東西 (就像是 facebook 一樣)

目前 .reply 設了寬度 355px 
只要 wrapper 的寬度要做變更,你就哭哭了 o(>.<)o














你看看你,CSS 改不完了吧 q(=.=)p

Facebook 也提供 API 給其他網站嵌入塗鴉牆
他怎麼會知道那些嵌入的網站寬度留給他多少
寫死寬度真的是自己挖坑給自己跳

OK 言歸正傳
那我們要怎麼做勒?
在這個案例中
.reply 的寬度一定要佔滿去掉 .photo 寬度後的部分
這代表 .reply 的寬度必須寫成多項式
.reply.width = 100% - .photo.width 
(這啥鬼 純 CSS 沒有數學運算這玩意)

咳咳~~
其實這個我們可以以用這兩種方式達成
  1. .comment 設左留白 (padding-left)
  2. .reply 設左邊界 (margin-left)

這兩個方法其實沒甚麼差別
都是要 .comment 將左方的照片空間空出來
因此值設成 .photo 的寬度即可 ( 還要再加上一點空隙 )

因為 .photo 的空間已經留下
.reply 就可以大方的將寬設成 width:100%; 而不會侵占到 .photo 的部分
如此即便 .comment 的寬度改變
.reply 也可以自動適應

但 .photo 該怎麼放到原本位置上呢?
你會說剛特易保留的空間目前已成為死區
誰也沒辦法靠近才對

其實不然
CSS 有一個屬性可以解目前的問題
就是 定位 (position) 啦

把 .comment 的定位方式設成相對後 (relative)
再把 .photo 設絕對定位 (absolute)
並調整位置到當初預留的地方
就完成塗鴉牆的架構
完成的樣式

.comment {
    background:#edeff4;
    padding:4px;
    width:100%;
    outline:0;
    
    padding-left:40px;
    position:relative;
    
    min-height:34px;
}

.photo {
    width:32px; height:32px;   
    
    position:absolute;
    top:4px; left:4px;
}

.reply {
    vertical-align:top;
    resize:none;
    border:1px solid #bdc7d8;
    width:100%;
    height:21px;
    padding:0;
}


這邊成品 http://jsfiddle.net/NqdnL/1/
大家可以試著調整 wrapper 的寬度來看看效果

=============== 我是找不到該說甚麼分隔線 ===============

其實 Facebook 的做法整理後大致上也是這樣
而這種做法其實還是有一點缺陷

因為 .comment 的左留白寬度無法依照 .photo 的大小改變
但現實中照片寬高不會常作調整  
畢竟上傳的圖片要做第 2 次放大或縮小很麻煩
尤其又是縮圖 失真問題會很嚴重
也因此這算是可以接受的做法


感謝收看本期的內容
並敬請期待下期的 CSS 的故事: ABC 狗咬豬,CSS 也有 ABCD


附註
  1. 上面的例子只是簡單做出塗鴉牆架構並無太多細節部分的處理
  2. FacebookCSS 架構很優秀,雖然可能因為還在開發而顯得語法有點亂,但還是有很多值得參考的地方
W3C CSS 速查字典
  顯示模式 ( display ) http://www.w3schools.com/cssref/pr_class_display.asp
  定位 ( position )    http://www.w3schools.com/cssref/pr_class_position.asp





沒有留言:

張貼留言