標籤:

[多行文本] 樣式怎麼沒了?

背景

- 「線上樣式有個小問題,有時間幫忙改下」

- 「誒,什麼情況,訂單信息的商品名稱不是做了多行文本截取了嗎,怎麼沒效果啦 ...」

是的,線上的多行文字截取沒了

技術概況

多行文本... 通常情況下會採用如下方案:

.multi-ellipsis { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;}

百試不爽 ...

然後,webpack bundle 配置 :

{ test: /.(sass|scss)$/, use: ExtractTextPlugin.extract({ fallback: style-loader, use: [ { loader: css-loader, options: { minimize: true, }, }, { loader: postcss-loader, options: { sourceMap: true, plugins: () => [autoprefixer], }, }, { loader: sass-loader, }, ], }),}

其中,postcss-loader 使用了 autoprefixer 插件。

求解過程

1. 查看線上頁面元素樣式,發現元素下的樣式只有:

{ display: -webkit-box; -webkit-line-clamp: 2;}

2. 拉取最新代碼,本地構建,查看本地環境

「誒,我這是好的啊,是不是你電腦有問題啊,要不清個緩存吧,重啟也行(:」

@leohxj 登場,用一句話指明了正確的解題思路:

雲構建的包依賴是會更新到最新的,你把本地 node_modules 刪了重新裝一下試試

3. rm -rf node_modules & npm i,然後再看本地環境

「果然如此啊,那就是哪個包升級所導致的了」

4. 首先,懷疑的肯定是 autoprefixer,只有它會做類似的事情,先移除看看 ...

{ loader: postcss-loader, options: { sourceMap: true, plugins: () => [], },}

編譯,wtf ... 怎麼還是沒有?難道還有包也幹這種事情啊 ...

5. 中間過程甚是艱辛,暫且不表,反正最後發現了 css loader 的 options 的配置裡面其實是可以傳 cssnano 的配置參數的

是的,去翻代碼的看到了這樣的玩意:

如果 css-loader 開啟了 minimize, cssnano 的配置參數就可以通過 options 傳進來了,比如:

{ loader: css-loader, options: { minimize: true, zindex: true, },}

就可以開啟構建中使用 cssnano 做 zindex 的優化了 ...

但是,有沒有發現有個貨不在裡面?是的,autoprefixer 啊!autoprefixer 是默認開啟的啊!fuck...

於是,options 中設置 autoprefixer: false構建試試,在了!這次沒消失!

敲黑板:css-loader 中使用了 cssnano,v0.26.0 之前的版本中默認開啟 autoprefixer. 在 0.26.0 關掉了此配置。因此,如果你代碼中有使用到 css-loader 並且無 cssnano 配置參數,建議升級,減少代碼執行不確定性。

6. autoprefixer

autoprefixer issue 中,已經有相關的問題了,ai 給了回復:

一直在找構建工具的問題,忽略 CSS 本身是否有問題 ...

7. CSS

我們的 CSS 寫法屬於 Flexbox 的 old 2009 version, 目前我們常用的 display: flex 屬於現代的版本。

問題在於,因為有一定的瀏覽器支持度,2009 version 的寫法似乎已經被大家下意識的「標準」化了,大家都在使用這種方式處理多行文字截取的問題,但是始終都是要被拋棄的...

我們上面遇到的問題就是一種體現,也是一種警醒 ...

如果你不想去改代碼,可以指定構建時的瀏覽器支持度:

autoprefixer({ browsers: [> 0.5%, last 2 versions]})

多行文本的正確姿勢

使用 weird webkit flexbox 去解決 ... 的問題其實很奇怪,為什麼要用 flexbox 去解決這個問題,沒想過 ... 而且給元素設置 padding 是會影響的:

without padding

with padding: 10px

那該用什麼方法解決呢?

最穩妥的方法應該是 JS 庫的介入了,比如:Clamp.js, 體積小且通用;

如果不想用 JS 庫的話,我還看到了一種「歪」方法:

.text { position: relative; height: 3.6em; /* exactly three lines */}.text:after { content: ""; text-align: right; position: absolute; bottom: 0; right: 0; width: 20%; height: 1.2em; background: linear-gradient( to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1) 80% );}

定高 n 倍,結尾處放置一個漸變塊 ...

當然,也可以:

.text:after { content: "..."; text-align: right; position: absolute; bottom: 0; right: 0; height: 1.2em; background: #fff;}

但是這種容易把字截斷,不可控 ...

結語

如果你正在尋找方法,實現多行文字截取,可以考慮使用正確的姿勢;

如果你已經遇到了上述同樣的問題,建議:

  1. 把 css-loader 升級到 0.28 以上版本 ( autoprefixer 默認不開啟 );
  2. 把 autoprefixer 升級到 8.0 以上版本,並指定 browsers,通常為: [> 1%, last 2 versions]

重要的備註

1. css-loader 在 0.27 後,cssnano 的參數移到了 option.minimize 中,即:

{ minimize: { zindex: true }}

2. autoprefixer 8.0 依賴的 browserslist@3.0.0, 在 browserslist 3.0 版本中,對默認值做了變更:

你也可以使用默認值,但是要去掉 not dead ... 顧名思義,old version supporter 無人權 ...


推薦閱讀:

用 cooking 搭建一個多頁面易配置的 Vue 2 項目(進階篇)
webpack 4.0.0-alpha.3 新功能:JSON Tree Shaking
你不知道的webpack和webpack-dev-server高級玩法
用 webpack 構建 node 後端代碼,使其支持 js 新特性並實現熱重載
React學習資源匯總

TAG:CSS | Webpack |