CSS 樣式防禦

_Kieran發表於2018-08-26

概念 / 起因

什麼是樣式防禦?
顧名思義,就是保護你寫的樣式最後是你想展現的樣子。一般樣式被破壞多發生於第三方應用程式設計中,當編寫的元件被應用於第三方網站中,元件的樣式經常會被網站本身的樣式影響而破壞了它本來想展現的樣子。

為什麼會研究這個東西呢?因為有一天,我引用的第三方程式碼的 CSS 被我網站上的 CSS 影響了。於是,我噼裡啪啦趕緊把第三方的樣式又給“強調“了一遍。搞完一想,不對啊,這特麼應該是第三方自己沒做好對自己 CSS 程式碼的防禦啊,我瞎操什麼心呢。不過這也引出了這次的話題,假如是你來寫這個第三方應用,你怎麼去做這個樣式防禦?

對比研究

為此,我特地先研究了幾家比較知名的網站是怎麼做的。
首先,我們先看一下暢言 changyan.kuaizhan.com/static/help…,這是一個第三方評論元件,開啟 console 仔細看了一下,發現其實它沒怎麼做樣式防禦,大部分樣式寫在 id 選擇器裡,防止了大部分的誤傷。但還是很容易誤傷,比如加個 span { color: red; } 評論就都變紅色了。不過它在 logo 上倒是加了 !important 來防止隱藏,還有廣告也加了一堆 !important,效果嘛,你懂得。

接著我們來看一下 Disqus blog.disqus.com/why-readers… 是怎麼做的。沒錯,iframe,直接趕盡殺絕。不讓任何人修改我的樣式,你只能用我提供的樣式。用 iframe 固然可以完美的做到樣式防禦,不過開發的複雜度一點也沒有減少,動態的計算元件的高度來改變 iframe 的高度就夠讓人頭疼了,畢竟裡面評論一條套著一條,一條行數都是不定的。不過簡單的固定長寬的倒是很適合用 iframe 來開發,相容性也好。

還有 Twitter,需要FQ才能看到

用了 Shadow DOM,也算是時代先鋒了。
我們先來看看 Shadow DOM 是什麼,developer.mozilla.org/zh-CN/docs/…

Shadow DOM 修復了 CSS 和 DOM。它在網路平臺中引入作用域樣式。 無需工具或命名約定,您即可使用原生 JavaScript 捆綁 CSS 和標記、隱藏實現詳情以及編寫獨立的元件。

看描述,感覺非常適合用來編寫第三方元件,內心一喜,但是別激動,查一下相容性先。

Shadow DOM 相容
果不其然,天妒英才啊,不過,這不妨礙我們瞭解一下它。
從文件中我們知道 Shadow DOM 必須附加在一個元素上,可以是HTML檔案中的一個元素,也可以是指令碼中建立的元素;可以是原生的元素,如<div>、<p>;也可以是自定義元素如 <my-element>。 如下例所示,使用 Element.attachShadow() 來附加影子DOM:

<my-element id="hostElement"></my-element>
<script>
  // create shadow DOM on the <p> element above
  var shadow = document.querySelector('#hostElement').attachShadow({mode: 'open'});
  shadow.innerHTML = '<p>我是 Shadow DOM~</p>';
  // 新增CSS,將文字變紅
  shadow.innerHTML += '<style>p { color: red; }</style>';
</script>
複製程式碼

這裡的 p 就不會受到外部 CSS 的影響了,由此可見,Shadow DOM 很好的隔絕了外部的世界,天然的實現了樣式防禦。

對比到這裡,大家對樣式防禦也有了一定的瞭解了。那麼除了上述的三種方案,還有什麼方案嗎?
我們來想想為什麼要做樣式防禦,不就是怕第三方網站的樣式汙染了我們元件的樣式嗎,如果我們能把第三方網站的樣式在我們元件這裡重置掉不也可以嗎。 網上有很多重置 CSS 的程式碼,雖然寫那麼多略顯繁瑣,但有用。那有什麼一句程式碼就能重置的呢?有嗎?當然是有的了,不然我也不會寫出來了。就是 CSS all 屬性了。下面的一句程式碼,就能把標籤的樣式恢復到瀏覽器預設狀態了。

element {
  all: initial;
}
複製程式碼

不過很不幸,依然不相容全系列 IE

CSS all 相容
不過比 Shadow DOM 好多了,如果你的應用不需要相容 IE 的話,可以一試。

總結

作為一個第三方元件,比如評論元件,光隔絕外部樣式是不夠的,準確的說,是不夠智慧,假如外部設定的字型,顏色跟我的元件差別很大,那我的元件不就顯得格格不入了嗎。所以我們隔絕了外部樣式後還得獲取外部的核心樣式來讓我們的元件顯得更和諧。具體要獲取哪些樣式,就仁者見仁智者見智了,根據你的元件來定製,沒有一成不變的規則。

相關文章