前陣子使用 Tailwind CSS 開發的正舒服時,遇到一個常見的需求。
為了營運方便,網頁常常會留一個區域給客戶使用,客戶可以編輯 HTML 來達到想要的效果
這樣的好處是,客戶可以馬上應對業務需要,IT也不用重新佈署程式
壞處是要考量資安,不過都是內部來源,出、入口增加檢核,好好把關就能把風險降到最低
Tailwind CSS 預設是會把 HTML 元素原生樣式移除,使所有元素都在相同基礎上設計,避免在各瀏覽器有不一樣的顯示。
以上面情境來看,客戶編輯的 HTML 內容就會不如預期,例如: <ul>、<li>、<h1>
如圖
native vs tailwind
官方稱此為 Preflight ( 很不容易想到的關鍵字… ),而 @tailwind base; 就是使 Preflight 作用的地方
這段Code有使用 Tailwind 應該都不陌生~
@tailwind base; /* Preflight will be injected here */
@tailwind components;
@tailwind utilities;
Shadow DOM 簡單介紹,可以想像 HTML 是一張紙,而 Shadow DOM 則是在藏於其後的另一張紙,而畫面渲染時會像是兩張紙疊起來顯示
這次則是利用DOM、Shadow DOM之間互不干擾的特性!
先看結果
透過 vue directive 方便使用
Setup
import { DirectiveBinding, ref } from 'vue'
const htmlStr = ref(`
<h4>Top 3 Frontend Framewors</h6>
<ul>
<li>Vue</li>
<li>React</li>
<li>Angular</li>
</ul>`)
const vShadowHtml = {
mounted: (el: HTMLElement, binding: DirectiveBinding) => {
let shadow: ShadowRoot | null = el.shadowRoot
if (shadow == null) {
shadow = el.attachShadow({ mode: "open" });
}
shadow.innerHTML = binding.value
},
updated: (el: HTMLElement, binding: DirectiveBinding) => {
let shadow: ShadowRoot | null = el.shadowRoot
if (shadow == null) {
shadow = el.attachShadow({ mode: "open" });
}
shadow.innerHTML = binding.value
}
}
Template
<div class="p-5">
<div class=" text-red-300">Without Shadow DOM</div>
<div v-html="htmlStr"></div>
<br />
<div class=" text-red-300">Using Shadow DOM</div>
<div v-shadow-html="htmlStr"></div>
</div>
使用 Tailwind CSS 可以方便管理樣式與提高開發效率,但遇到不同的業務情境時,還是要額外處理。
幾年前研究過 Shadow DOM,沒想倒在此時派上用場,救了我一把,因為這個問題發生是在專案 UAT 階段
另外,對於要不要使用框架,我自己的想法是八二法則~ 若框架能解決8成以上的問題,我就會考慮使用,而剩下的特殊狀況額外處理即可