溢出文本顯示省略號,關於text-overflow:ellipsis的那些事

溢出文本顯示省略號,關於text-overflow:ellipsis的那些事
這個標題其實已經是一個老生常談的問題了。很多時候,比如網站最基本的文章列表,標題會很長,而顯示列表的區域寬度卻沒有這麼寬,這時候最正常的做法就是讓超出寬度的部分文字用省略號(…)來表示。通常做法是網站後台程序截取一定的字元然後輸出到前台顯示或者前台用javascript截取一定的字元,但是通過控制字數來截取的話還是存在一個大問題的,因為中文和英文的字元寬度問題,這個字數不好控制,而且通用性較差。那麼有沒有更好的方法呢,比如直接用CSS來解決的,當然是有的。

text-overflow是一個比較特殊的屬性,W3C早前的文檔中目前的文檔中沒有包含text-overflow屬性,FML!)對其的定義是:

Name: text-overflow-mode
Value: clip | ellipsis | ellipsis-word

clip :  不顯示省略標記(…),而是簡單的裁切
ellipsis :  當對象內文本溢出時顯示省略標記(…),省略標記插入的位置是最後一個字元。
ellipsis-word :  當對象內文本溢出時顯示省略標記(…),省略標記插入的位置是最後一個詞(word)。

至於為什麼一開始我說text-overflow是一個比較特殊的樣式呢?因為我們可以用它代替我們通常所用的標題截取函數,而且這樣做對搜索引擎更加友好,如:標題文件有50個漢字,而我們的列表可能只有300px的寬度。如果用標題截取函數,則標題不是完整的,如果我們用CSS樣式text-overflow:ellipsis,輸出的標題是完整的,只是受容器大小的局限不顯示出來罷了(表現上是超出部分顯示省略標記…)。

text-overflow: ellipsis屬性僅是註解,當文本溢出時是否顯示省略標記。並不具備其它的樣式屬性定義。我們想要實現溢出時產生省略號的效果。還必須定義:強制文本在一行內顯示(white-space:nowrap)及溢出內容為隱藏(overflow:hidden)。只有這樣才能實現溢出文本顯示省略號的效果。Via.

那麼,如果我們要給p標籤定義text-overflow:ellipsis就可以這麼寫:

p {
      white-space: nowrap;
      width: 100%;                  /* IE6 需要定義寬度 */
      overflow: hidden;             
 
      -o-text-overflow: ellipsis;    /* Opera */
      text-overflow:    ellipsis;    /* IE, Safari (WebKit) */
   }

使用樣式前:

我是一段測試文字,請分別用IE,Safari,chrome,opera瀏覽器查看我哦!

使用樣式後:

我是一段加長過的測試文字,請分別用IE,Safari,chrome,opera瀏覽器查看我哦!哈哈哈,看到省略號了么?

瀏覽器兼容狀況

Browser Lowest Version Support of
Internet Explorer 6.0 text-overflow
Firefox (Gecko)
Opera 9.0 -o-text-overflow
Safari (WebKit) 1.3 (312.3) text-overflow

OH,FML!Firefox不支持這個屬性!這回,Firefox你也太另類了吧!還有別的辦法么,當然有,方法還挺多的。
比如Mozilla developer center推薦的-moz-binding CSS屬性。Mozilla developer center給出的理由是text-overflow沒有W3C的規範…但是因為Firefox支持XUL,一種XML的用戶界面語言。並且Firefox還支持XBL,一種XML綁定語言,這樣我們就可以使用Mozilla developer center推薦的-moz-binding CSS屬性來綁定XUL里的ellipsis屬性了。

1.XUL方式

首先,我們創建XUL,它應該被保存為ellipsis.xml:

<?xml version="1.0"?>  
<bindings   
  xmlns="http://www.mozilla.org/xbl"  
  xmlns:xbl="http://www.mozilla.org/xbl"  
  xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"  
>  
    <binding id="ellipsis">  
        <content>  
            <xul:window>  
                <xul:description crop="end" xbl:inherits="value=xbl:text"><children/></xul:description>  
            </xul:window>  
        </content>  
    </binding>  
</bindings>

然後我們需要把這個xml文件放到一個目錄,原來的css需要加一條,變成這樣

p {
      white-space: nowrap;
      width: 100%;                  /* IE6 需要定義寬度 */
      overflow: hidden;             
 
      -o-text-overflow: ellipsis;    /* Opera */
      text-overflow:    ellipsis;    /* IE, Safari (WebKit) */
      -moz-binding: url('ellipsis.xml#ellipsis');    /* Firefox */
   }

雖然Firefox通過XUL的方式實現了ellipsis,但是還是需要注意以下這些問題:
1.經過XUL處理過的文本你將不能被選中,按理說-moz-user-select: text; 屬性將允許文本被選中,但是我沒有試驗成功。
2.如果你給父元素綁定了XUL,那麼子元素的內容將變得不可見。例如:

It is a longhaha long long long long text!

如果你只是給p節點綁定了XUL,那麼在Firefox下你將看不到haha這個內容。
它的源代碼實際上是:

<p>It is a long<em> haha</em> long long long long text!</p>

參考資料:

http://www.w3.org/TR/2003/CR-css3-text-20030514/
http://www.quirksmode.org/css/contents.html
https://bugzilla.mozilla.org/show_bug.cgi?id=312156
https://developer.mozilla.org/En/XUL
https://developer.mozilla.org/En/XUL/Description
http://www.rikkertkoppes.com/thoughts/2008/6/
http://www.w3.org/TR/xbl/
http://www.w3.org/TR/css3-text/

2.Javascript方式

既然XUL無法完美解決Firefox下文字溢出顯示…,那麼我們就求助javascript吧,當然,並不是古老的截取一定數目的字元來實現。
這裡以jQuery為例,代碼如下:

(function($) {
	$.fn.ellipsis = function(enableUpdating){
		var s = document.documentElement.style;
		if (!('textOverflow' in s || 'OTextOverflow' in s)) {
			return this.each(function(){
				var el = $(this);
				if(el.css("overflow") == "hidden"){
					var originalText = el.html();
					var w = el.width();
 
					var t = $(this.cloneNode(true)).hide().css({
                        'position': 'absolute',
                        'width': 'auto',
                        'overflow': 'visible',
                        'max-width': 'inherit'
                    });
					el.after(t);
 
					var text = originalText;
					while(text.length > 0 && t.width() > el.width()){
						text = text.substr(0, text.length - 1);
						t.html(text + "...");
					}
					el.html(t.html());
 
					t.remove();
 
					if(enableUpdating == true){
						var oldW = el.width();
						setInterval(function(){
							if(el.width() != oldW){
								oldW = el.width();
								el.html(originalText);
								el.ellipsis();
							}
						}, 200);
					}
				}
			});
		} else return this;
	};
})(jQuery);

這段js的原理很簡單,就是通過不斷的比較寬度值,然後逐個縮短字元寬度,當最後寬度合適的時候,停止循環,就實現了文字溢出顯示…的效果。
這段js還需要一段css來配合。

.overflow {
	text-overflow: ellipsis;
	-o-text-overflow: ellipsis;
	white-space: nowrap;
	overflow: hidden;
}

js里有個判斷就是當樣式里出現text-overflow或者-o-text-overflow的時候,便不會執行這段js。因為支持這兩個屬性的瀏覽器可以自己實現ellipsis效果。

這兩種方法都可以實現Firefox下ellipsis的效果,如何取捨使用,具體還得根據你要運用到的項目的具體情況來具體分析,XUL實現的方法的不足之處在以上已經很詳盡地列舉了,如果你可以避免或者說這些無關你項目的大問題,那麼XUL不失一個好方法。

至於其他的一些方法你可能在網上也有看到,比如用:after偽類來實現等,個人不推薦,所以我這裡也不細說了,如果你有更好的方法,也希望能與我分享,謝謝觀看!

2011.09.28更新:Firefox7已經支持text-overflow:ellipsis了,enjoy it!

68 Responses to 溢出文本顯示省略號,關於text-overflow:ellipsis的那些事

  1. bolo says:

    在一個列表裡,有時候沒必要把過長的文本進行隱藏。
    正常時可以固定 li 的高度並且 overflow: hidden ,mouse over 時則 height: auto;z-index: 99;overflow: visible;
    也就是當滑鼠在元素上時則顯示全部內容。

  2. 游神 says:

    收了,等會去試試我的那些個標題去

  3. 游神 says:

    我目前的做法:

  4. 游神 says:

    php echo mb_strimwidth(get_the_title(), 0, 34, ‘…’);

  5. 游神 says:

    複製PHP代碼竟然無聲無息就給我屏蔽了,邪惡的淫

  6. 任平生 says:

    原來 WebKit 也支持text-overflow 啊。

  7. Pingback: Tweets that mention 溢出文本顯示省略號,關於text-overflow:ellipsis的那些事 - Leeiio Chaos Made. -- Topsy.com

  8. winy says:

    firefox居然不支持 ❓ 還是overflow: hidden吧

  9. Mars says:

    路過,學習啦。

  10. LOO2K says:

    leeiio,你博客上的 JavaScript 有點問題,外部鏈接點擊之後會打開兩個。
    $("a[rel*='external']").click(function() {
    window.open(this.href);
    return false;
    });

    應該是少了一句return false;

  11. 阿邙 says:

    之前也研究過這個問題 不過最後放棄了。

  12. Chris says:

    while() 那段還可以再優化, 現在這個例子根據截斷的不同, 循環次數也不一樣

  13. 行者 says:

    學的不是很好使,應該放個demo出來,有個參照。

  14. 小邪 says:

    呵呵,我一般喜歡讓他們到下面去 ~
    word-break: break-all;
    word-wrap: break-word;
    😳 😳

  15. 行者 says:

    javascript 中調用的寫法怎麼寫,恕我愚笨。 🙂

  16. disinfeqt says:

    曾經糾結了一整晚的問題終於到你頭上了。
    你寫的辦法我當時都自己摸索出來了,除了那個噁心的XUL…
    最後還是PHP後台截斷最省事…
    不過,最近一個項目里正巧用到了 text-overflow: ellipsis;
    真巧…

    • Leeiio says:

      @disinfeqt 呃,因為我們的doit後台不會處理這種問題的,都是前端問題的,所以當時糾結這個了好久,其實無非就是糾結在firefox下的問題,面對ellipsis問題它就是個異類。然後一直拖著沒時間寫博客分享…

  17. disinfeqt says:

    嗯那個JQ小插件留著備忘了,不錯不錯~ 😳

  18. QiQiBoY says:

    那個,火狐下我看到haha了。。 😮

  19. Chris says:

    今天處理等高問題, 發現離線 el 無法讀取 offsetHeight, 想起你這裡有用到 cloneNode 和 t.width(), 以為你有解決方案
    看了半天發現也是和我一樣… visibility: hidden 後附加到 DOM 里… ❓

  20. comfill says:

    希望以後全人類都來用chrome吧。

  21. mm says:

    我用了那個xml文件,在火狐里居然顯示是粗體字,其它正常,這是怎麼回事呢?

  22. mm says:

    我的代碼是這樣的:
    #box #piaofu #piaofu-xia #piaofu-xia-xia #piaofu-xia-xiaduan li a {
    font-size: 12px;
    font-weight: normal;
    color: #FFF;
    display: block;
    overflow: hidden;
    white-space: nowrap;
    -o-text-overflow: ellipsis;
    text-overflow: ellipsis;
    -moz-binding: url(‘ellipsis.xml#ellipsis’);
    }
    字體的大小和粗細都定義了的,在IE和OPREA下顯示正常,但是在FF下字體大小正常,但是就是顯示粗體。

    • Leeiio says:

      @mm 先試試給font-weight: normal;加上!important變成font-weight: normal !important;,這個xml文件不會造成字體變粗的,有演示頁面么

  23. mm says:

    :mrgreen: 問題已經解決,的確是我的CSS出現了問題,非常感謝!!!!

  24. mm says:

    是字體的繼承問題,居然是繼承最根部的字體定義。呵呵 :mrgreen:

  25. mm says:

    就是用了這個XML文件,FF的字體會自動繼承最根部的定義,而IE和OPERA不字體的根部定義是什麼,都必須在該子層中重新定義 :mrgreen:

  26. mm says:

    就是用了這個XML文件,FF的字體會自動繼承最根部的定義,而IE和OPERA不管字體的根部定義是什麼,都必須在該子層中重新定義

  27. mm says:

    再次感謝,感謝,再感謝 :mrgreen:

  28. 左旋肉鹼 says:

    此文寫的不錯,學習了。。。

  29. 曾少 says:

    已拜讀,已收藏,已RSS

  30. 雞巴牛比 says:

    XML無法載入完成時,整行文字無法顯示。該方法解決的那行文字,無法複製!不推薦使用。

  31. Ygs says:

    喲,學習了我

  32. 黑幕困獸 says:

    國內火狐用戶感覺還是蠻少的,大部分都是開發人員在用,項目中我覺得不必要針對火狐來做這麼多代碼處理。
    不過方法很不錯,贊! 😛

  33. Jill says:

    學習了 😳

  34. 這麼多方法,學習了

  35. 宇蠢 says:

    逐個縮短字元寬度……汗死……
    這明顯該用二分法的。

  36. Yuest says:

    另外,ff4.0上已經可以看到那個haha了
    還有,你的博客是不是有頭像緩存啊,怎麼我的頭像沒更新,我早在 gravatar 更新過了……

  37. 依雲 says:

    火狐 7+ 支持 ellipssis 啦~

  38. Cherry says:

    我一般都設置好固定的width,超過部分就overflow:hidden了

  39. Jiuaisee says:

    9aisee: OOPS  學習!!

  40. Yaopeiling22 says:

    文本多行的時候,是不是只能用js來實現?

  41. Pingback: 顯示12個位元組 | 咖啡不苦

Leave a Reply

Your email address will not be published. Required fields are marked *