textarea 自動調整高度 - 優雅作法!

此篇文章最近更新時間為2012-11-23 20:25:32 目前共有2篇留言

關於作者 - JosephJ

任職於 Faria。喜好戶外運動、2008 年 5 月完成「跑步環島」。對於新技術跟程式碼有著強烈的偏執狂。

依照內容自動調整 textarea 高度算是很常見的功能,像 Facebook 的留言輸入即是:

由於無法透過純 HTML + CSS 就達成,常見的作法透過 scrollHeight 或者是去猜測有幾行。 但是都有一些缺點,例如上面 Facebook 的輸入框就因為中英文字型不同的關係、讓第一行沒辦法出來。

解決方式:鏡像元素

先前同事的作法也是利用 scrollHeight 去偵測,趁這次又要用到這個工具、Survey 後找到這篇文章: Expanding Text Areas Made Elegant, 它所提的作法非常有趣:用 pre 的元素作為 textarea 的鏡像元素。 大部分的 HTML 元素預設都會隨著內容自動展開、而 textarea 是少數的例外。 若我們在輸入時也把 textarea 的內容塞入 pre 內,並讓這兩個標籤的樣式一致, 即可從 pre 得到 textarea 展開時實際所需要的高度、而且一點誤差都沒有!

HTML 結構

HTML 結構

  • 新增 pre 作為隱藏的鏡像元素。
  • 新增 div 將 pre 及 textarea 包起來。
  • 將 pre 及 textarea 的樣式 reset(border, margin, padding, line-height…)。
  • 改用 div 作為 textarea 的外框
  • textarea 設定寬高為 100%,佔滿整個 div 元素。

這些設置一旦設好,當鏡像 pre 因內容增減而改變高度時,也會連帶影響 div 及 textarea 的高度

JavaScript

重點只有 如何同步 pre 裡面的內容,不管 paste、key 都要處理,文章中依是否為 IE 提供了 propertychange 及 input 兩種事件。在 YUI 中不需判斷,有個好用的事件叫做 valuechange 能夠通殺 :D

實作

我用 YUI 實作了一個 Plugin,不需要修改任何 HTML 即可使用:

<link rel="stylesheet" href="assets/node-autogrow.css">
<script src="http://yui.yahooapis.com/3.7.3/build/yui/yui-min.js"></script>
<script src="node-autogrow.js"></script>
<script>
YUI().use("node-autogrow", function () {
    Y.one("textarea").plug(Y.AutoGrow);
});
</script>


看看範例:http://josephj.com/lab/2012/node-autogrow/samples/demo.html

缺點

目前這個作法還是有一些小缺點:

  • 需另外針對 pre, textarea 設定 font 樣式:兩個標籤的字體若不相同,算出來的高度也會有落差。所以我一律 reset 為 Arial 13px,你可能得另外再做設定。
  • 目前高度變更會稍微閃一下,我試 Facebook 的似乎沒有此問題,文章中有提高 Mac 會有這個問題,我再找時間來做修改。

其他應用

文章中還有提到一個有趣的應用:把 textarea 的 color 設為 transparent、下面的 pre 改用 syntax highlighter 並顯示,就可以一邊編輯程式碼、一邊顯示語法高亮了!



Comments

  1. test 2013-12-30 10:41:00
    这个表单简单的验证都没有啊,随便灌水。。。。。。。。。。。
  2. airyland 2012-11-25 20:23:39
    用<pre>这个思路真不错。
暱稱: 必填。
Email: 非必填。若填寫為不公開欄位,僅供站長參考聯繫。
內容: 必填。限 255 個字元以內。
驗證碼:
送出

Facebook Comment