【本文會持續(xù)更新!】
1、color 影響 border-color
當(dāng)只設(shè)置元素的邊框?qū)挾群蜆邮綍r,邊框的顏色會取當(dāng)前元素 color 屬性的計算值。
<div style="color: blue;border: 1px solid;">這里設(shè)置了 border,但不指定 border-color</div>

瞧瞧該實例元素的 border-color 屬性的計算值:

可以看到,border-color 屬性未設(shè)置值時為 initial 關(guān)鍵字,代表取該屬性的默認(rèn)值。那么,為什么這里取的是 color 屬性的值而非瀏覽器對 border-color 的默認(rèn)值(如果有的話)呢?
因為 border-color 屬性的默認(rèn)值就是 currentColor 關(guān)鍵字(CSS 3),也就是當(dāng)前元素的 color 屬性的計算值,詳見 border-color | MDN。
color 前景色
MDN 中對 color 屬性是這樣介紹的:
The
colorproperty sets the foreground color of an element's text content, and its decorations. It doesn't affect any other characteristic of the element
翻譯過來就是,color 屬性設(shè)置元素文本內(nèi)容的 前景色 和 修飾。
HTML 元素的前景色包括:
- 字體顏色,也就是狹義上的
color; -
border-color,邊框的顏色; -
outline-color,輪廓的顏色; -
box-shadow,陰影的顏色; -
text-shadow,文本陰影的顏色;
以及文本修飾中的 text-decoration-color,下劃線的顏色。
<head>
<style>
p {
color: blue;
max-width: 500px;
}
</style>
</head>
<body>
<p>這里沒有做任何處理</p>
<p style="border: 1px solid;">這里設(shè)置了 border,但不指定 border-color</p>
<p style="outline: 1px solid;">這里設(shè)置了 outline,但不指定 outline-color</p>
<p style="text-decoration: underline;">這里設(shè)置了 text-decoration,但不指定 text-decoration-color</p>
<p style="box-shadow: 0 1px 2px 0;">這里設(shè)置了 box-shadow,但不指定顏色</p>
<p style="text-shadow: 10px 10px 2px;">這里設(shè)置了 text-shadow,但不指定顏色</p>
</body>

2、移動端 H5 禁止顯示系統(tǒng)菜單
當(dāng)在移動端 H5 上長按一個目標(biāo)元素時,瀏覽器會彈出一個關(guān)于目標(biāo)元素的菜單信息。請看下面針對文本元素的實例:
<span>這是一段文字,請在移動端長按</span>

在某些場景下,我們并不希望瀏覽器彈出這樣的菜單,應(yīng)該怎么做呢?我在網(wǎng)上搜羅了幾個常見方案:
-
通過 -webkit-touch-callout 屬性禁用 callout【無效】
-webkit-touch-callout: none;-webkit-touch-callout屬性的兼容性非常差,之前只有在 Safari 瀏覽器上可用。而 現(xiàn)在應(yīng)該是被廢棄了,親測在 ios Safari 瀏覽器上不起效,Can I use 上也已經(jīng)搜索不到了。 -
JS 屏蔽 contextmenu 事件的默認(rèn)行為【無效】
$elm.addEventListener('contextmenu', (e) => { e.preventDefault(); });當(dāng)用戶嘗試打開上下文菜單(通常是鼠標(biāo)右鍵單擊)時,
contextmenu事件會被觸發(fā),我們可以通過preventDefault()方法來屏蔽菜單的顯示。那么這種方法是否適用于移動端 h5 呢?答案是否定的。不妨來看看
contextmenu事件的兼容性:so,網(wǎng)上的部分教程就不要再誤人子弟了。
-
通過 user-select 屬性讓元素不可選中【有效】
-webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; -o-user-select: none; user-select: none;在移動端,若用戶不可選中元素,自然也就不能通過長按調(diào)起默認(rèn)菜單了。但需要注意的是,
user-select: none在部分瀏覽器(如 Safari)中會使<input>、<textarea>等表單元素失效。 -
JS 屏蔽
touchstart事件的默認(rèn)行為【有效】$elm.addEventListener('touchend', (e) => { e.preventDefault(); });此方案和使用
user-select是一樣的原理,但同樣 需要注意禁止默認(rèn)行為所帶來的負(fù)面影響,譬如作用于可滾動元素時。
所有方案的測試情況見:https://codepen.io/JunreyCen/pen/rEBYPV
總結(jié)一下,移動端的兼容性一直是非常棘手的問題,各種手機操作系統(tǒng)、各種瀏覽器應(yīng)用沒有一套統(tǒng)一的 web 標(biāo)準(zhǔn),都喜歡 “各抒己見”。也因此,上面提及的方案在某些型號手機的瀏覽器中(譬如 Oppo 自帶的瀏覽器)依然是不起作用的,這種情況下開發(fā)者只能 “見招拆招”,無招可使時也只能擇 “較優(yōu)解” 了。
3、文本溢出顯示省略號
我們經(jīng)常遇到單行文本溢出時顯示省略號的場景,那多行文本的類似處理該如何實現(xiàn)?
單行文本
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap; /* 文本不換行 */

多行文本
多行文本溢出時,最后一行截斷并顯示省略號。這里提供兩種實現(xiàn)方式:
-
使用 line-clamp 屬性
line-clamp是一個不規(guī)范的屬性,沒有出現(xiàn)在 CSS 規(guī)范草案中。而且,它必須結(jié)合舊版的flexbox(伸縮盒)模型才起作用。overflow: hidden; display: -webkit-box; /* 舊版伸縮盒模型 */ display: -moz-box; -webkit-box-orient: vertical; /* 子元素垂直排列 */ -moz-box-orient: vertical; -webkit-line-clamp: 2; /* 塊元素顯示的文本行數(shù) */ -moz-line-clamp: 2;如下圖所示,
line-clamp在兼容性方面還是有點缺陷的。除此之外還需要注意的是,autoprefixer 等預(yù)處理插件會自動刪除一些舊的樣式屬性(包括
-webkit-box-orient屬性),所以使用這種方式時要對 autoprefixer 插件進行配置,詳見這個 issue 。 -
JS + CSS 手動加省略號
處理流程:
- 元素的
height值設(shè)置為line-height值的整數(shù)倍;
- JS 獲取元素的文本節(jié)點高度(
scrollHeight),若高度倍
line-height值則視為文本溢出; - 文本溢出時,于元素右下方顯示省略號,否則不顯示;
<style> #ellipsis { position: relative; display: block; overflow: hidden; line-height: 20px; height: 40px; /* height 為整數(shù)倍 line-height */ word-break: break-all; /* 使文本填充滿容器,利于省略號和文本的銜接 */ } .show-ellipsis { padding-right: 12px; /* 給省略號騰出空間 */ } .show-ellipsis:after { content: '...'; position: absolute; right: 0; bottom: 0; } </style> <p id="ellipsis">JS 和 CSS 設(shè)置多行文本字?jǐn)?shù)超出時最后一行顯示省略號,JS 和 CSS 設(shè)置多行文本字?jǐn)?shù)超出時最后一行顯示省略號</p> <script> const $elm = document.getElementById('js-ellipsis'); const style = window.getComputedStyle($elm); const limitHeight = +style.height.replace('px', '') + +style.lineHeight.replace('px', ''); if ($elm.scrollHeight >= limitHeight) { // 文本溢出則顯示省略號 $elm.className = 'show-ellipsis'; } </script>這種實現(xiàn)方式基本不存在兼容性問題(除了低版本 IE 瀏覽器),但效果肯定比不上
line-clamp的方式,只能靜待 W3C 制訂一套規(guī)范的處理方案了。 - 元素的
4、圖像自適應(yīng)
我們寫頁面的時候經(jīng)常會遇到,獲取的圖片尺寸與我們所期待的渲染尺寸不符。譬如在渲染用戶頭像的場景下,我們往往希望用戶上傳的圖片都是統(tǒng)一的正方形尺寸,然而用戶給的可能是這樣的:

常見的處理方式是 適當(dāng)?shù)募舨檬箞D片填滿容器而不被拉伸,我們可以利用背景圖(background-size / background-position)來實現(xiàn):
<style>
.avatar {
width: 200px;
height: 200px;
border: 2px solid #07C160;
background: url('./images/captain.jpeg') no-repeat;
background-size: cover;
background-position: center;
}
</style>
<div class="avatar"></div>

CSS 3 中提供了新的屬性:object-fit,可以對 <img> 標(biāo)簽作寬高自適應(yīng)處理,效果類似于 background-size 屬性。
object-fit 提供了5個取值:
- none:內(nèi)容保持原有尺寸;
- contain:內(nèi)容保持寬高比地縮放,內(nèi)容和容器的寬高比不匹配時會 留下白邊;
- cover:內(nèi)容保持寬高比地填滿容器,內(nèi)容和容器的寬高比不匹配時會 被裁剪;
- fill:內(nèi)容剛好填滿容器,內(nèi)容和容器的寬高比不匹配時會 被拉伸;
- scale-down:內(nèi)容尺寸和 none 或 contain 中的一個相同,最終會顯示尺寸較小的那個;
background-size 和 object-fit 的效果對比

同樣的,background-position 和 object-position 的作用類似,比較明顯的區(qū)別在于:
background-position的默認(rèn)值是0% 0%,而object-position的默認(rèn)值是50% 50%。
object-fit 的意義
- 解放了
background-image的能力;
譬如可以同時利用background-image和<img>標(biāo)簽完成圖片的堆疊等。 -
object-fit對所有 可替換元素 都有效;
常見的可替換元素包括:<iframe>、<video>、<embed>、<img>、<input type="image">。
兼容性

額,如果要兼容 IE 瀏覽器的話,還是乖乖用背景圖的方式把。
5、塊元素等比縮放
現(xiàn)在的網(wǎng)頁開發(fā)都講究響應(yīng)式設(shè)計,以使在各種尺寸的設(shè)備上也能保持良好的 UI 呈現(xiàn)。在響應(yīng)式布局中,我們經(jīng)常需要實現(xiàn)隨網(wǎng)頁視窗寬度動態(tài)變化的元素,尤其是支持等比縮放的元素。
比較傳統(tǒng)的做法,是通過 JS 監(jiān)聽 resize 事件,動態(tài)獲取容器的寬度然后調(diào)整元素的寬高。這里提供一種純 CSS 實現(xiàn)的方式,主要利用的是 padding 屬性的百分比取值:
padding屬性的百分比取值是相對于其包含塊的寬度。
所以,當(dāng)包含塊的寬度發(fā)生變化時,子元素的 padding 屬性的計算值會隨之發(fā)生變化,也就是說子元素的總寬高都會被改變,且與包含塊寬度成正比。
<style>
.wrapper {
width: 200px;
height: 300px;
border: 2px solid #07C160;
}
.content {
padding: 50%;
width: 0;
height: 0;
background-color: #FA5151;
}
</style>
<div class="wrapper">
<div class="content"></div>
</div>

接下來的工作,只需要讓目標(biāo)元素的寬高參考于 padding 子元素的寬高,就完成了元素的等比縮放。我們可以利用 絕對定位 來實現(xiàn)。
這里實現(xiàn)一個寬高比為 1:2、寬度保持為容器的等比縮放元素:
<style>
.wrapper {
width: 20%;
height: 40%;
border: 2px solid #07C160;
}
.container {
position: relative;
padding: 50%;
width: 0;
height: 0;
}
.content {
position: absolute;
top: 0;
left: 0;
width: 50%;
height: 100%;
background-color: #FA5151;
}
</style>
<div class="wrapper">
<div class="container">
<div class="content"></div>
</div>
</div>
為了突出演示效果,稍微 “修飾” 了一下:

需要體驗 Demo 的請?zhí)D(zhuǎn):https://codepen.io/JunreyCen/pen/agzoyG
6、垂直外邊距合并
當(dāng)兩個垂直外邊距鄰接時,會合并成一個外邊距。只有普通文檔流中塊元素的垂直外邊距才會發(fā)生合并,不在同一個 BFC 內(nèi)(譬如行內(nèi)元素、浮動元素、絕對定位等)的垂直外邊距不會合并,水平方向的外邊距也不會合并。
通常發(fā)生外邊距合并的場景有:
-
相鄰的兩個塊元素,鄰接的上/下外邊距發(fā)生合并
圖片摘自 http://www.w3school.com.cn/css/css_margin_collapsing.asp發(fā)生合并時外邊距的計算規(guī)則:
- 兩個外邊距都是正數(shù)時,取兩者中的較大值;
- 兩個外邊距一正一負(fù)時,取兩者之和;
- 兩個外邊距都是負(fù)數(shù)時,比較兩者的絕對值大小,誰大取誰;
-
無內(nèi)邊距(
padding)和邊框(border)的父元素的垂直外邊距會與子元素的垂直外邊距合并圖片摘自 http://www.w3school.com.cn/css/css_margin_collapsing.asp -
無內(nèi)邊距(
padding)、邊框(border)和內(nèi)容(content)的空元素的上/下外邊距會合并圖片摘自 http://www.w3school.com.cn/css/css_margin_collapsing.asp
這里提供一個完整 Demo:https://codepen.io/JunreyCen/pen/zVxPWX

7、行內(nèi)(塊)元素空隙
試試執(zhí)行這段代碼:
<img src="./images/captain.jpeg" width="200">
<img src="./images/captain.jpeg" width="200">

奇怪,兩張圖片之間出現(xiàn)了一道縫隙……
這是因為 img 元素默認(rèn)會被渲染成行內(nèi)元素(display: inline;),而上述代碼中兩個 <img> 之間其實是存在一個 換行符 (以及若干個 制表符)的,這些都會被渲染成一個空白格,也就導(dǎo)致了縫隙的產(chǎn)生。
解決辦法有倆:
- 寫 HTML 代碼的時候避免行內(nèi)元素間的空格、換行符等特殊字符;
<img src="./images/captain.jpeg" width="200"><img src="./images/captain.jpeg" width="200"> - 把行內(nèi)元素所在行的字體大小設(shè)為
font-size: 0;<style> body { font-size: 0; } </style> <img src="./images/captain.jpeg" width="200"> <img src="./images/captain.jpeg" width="200">
PS:行內(nèi)塊元素(
display: inline-block)也會存在同樣的問題。
8、pointer-events: none;
pointer-events 屬性可以指定元素是否可以成為鼠標(biāo)事件的 target ,通俗點講就是該元素是否可以接收鼠標(biāo)事件。
pointer-events 屬性有多種取值,詳見 MDN。這里著重介紹取值 none:
pointer-events: none;指定元素及其后代元素不會成為鼠標(biāo)事件的 target,父元素不受影響。
實驗 Demo
實驗內(nèi)容:三層 DOM 元素都監(jiān)聽了鼠標(biāo)點擊事件,其中 target 節(jié)點設(shè)置了 pointer-events: none,點擊 child 元素,看看有哪層元素可以響應(yīng)點擊事件。
<div class="parent" onclick="alert('parent')">
<div class="target" onclick="alert('target')">
<div class="child" onclick="alert('child')"></div>
</div>
</div>

左邊不作處理的實例會 alert 三次;而右邊的實例只會 alert 一次,內(nèi)容為 parent。
應(yīng)用場景
-
同層元素點擊穿透
我們在寫 UI 基礎(chǔ)組件時,多多少少會接觸到 Field 輸入框組件。比如下面的實例,需求是滿足 0.5px 邊框 + input 輸入框。
<style> .field { position: relative; width: 250px; height: 50px; text-align: center; } .field:after { position: absolute; top: -50%; left: -50%; right: -50%; bottom: -50%; content: ''; border: 1px solid #ccc; transform: scale(0.5); } </style> <div class="field"> <input type="text" placeholder="請輸入"> </div>你會發(fā)現(xiàn),左邊的輸入框無法聚焦。這其實跟 0.5px 邊框的實現(xiàn)方式有關(guān),實例中利用偽元素
:after制造了一個2倍尺寸的子元素,然后通過transform: scale(0.5)縮放,從而實現(xiàn) 0.5px 邊框。然而,**這個偽元素和input輸入框?qū)儆谕瑢釉兀鶕?jù)渲染的先后順序偽元素是層疊于輸入框之上的,所以鼠標(biāo)點擊事件是無法被輸入框捕獲的。我們只需要給偽元素設(shè)置
pointer-events: none;,使其無法成為鼠標(biāo)事件的 target,input輸入框就可以成功被聚焦。 -
阻止 :hover、:active 等鼠標(biāo)行為狀態(tài)的觸發(fā)
設(shè)置了
pointer-events: none;的元素?zé)o法響應(yīng)鼠標(biāo)事件,自然也就無法觸發(fā)相關(guān)的狀態(tài)了。
想體驗實例的請訪問:https://codepen.io/JunreyCen/pen/NZqKOx。
9、:first-child 和 :first-of-type 的區(qū)別
:first-child
匹配其父元素的符合特定類型的首個子元素。條件更為苛刻,需要滿足 首個子元素 + 符合特定類型。:first-of-type
匹配其父元素的符合特定類型的第一個元素。條件較為寬松,在滿足 符合特定類型 的范疇下尋找第一個元素即可。
<style>
.group-1 h2:first-child,
.group-1 h3:first-child,
.group-2 h2:first-of-type,
.group-2 h3:first-of-type {
color: #FA5151;
}
</style>
<div class="group-1">
<h2>父元素的第一個元素,第一個 h2 元素</h2>
<h3>父元素的第二個元素,第一個 h3 元素</h3>
</div>
<div class="group-2">
<h2>父元素的第一個元素,第一個 h2 元素</h2>
<h3>父元素的第二個元素,第一個 h3 元素</h3>
</div>

10、當(dāng)心分號 ;
我們都知道,在樣式表的聲明塊({...})內(nèi),樣式聲明之間會用分號隔開,這是因為引擎在解析時,每條聲明之間的空格(包括換行符等)會被忽略:
<style>
div {
color: red;
font-size: 20px;
}
</style>
<div>content</div>
那如果,分號寫在聲明塊之外呢?
這相當(dāng)于告訴引擎,樣式表解析到這里就結(jié)束了,后面的東西就不用管了。來看看這個 demo:
<style>
div {color: red};
.ctn-1 {color: blue}
.ctn-2 {font-weight: 600}
</style>
<div id="ctn-1">藍色字體</div>
<div id="ctn-2">加粗字體</div>

遇到類似的面試題時,就要注意仔細(xì)看別被 “坑” 了~








