昨天我們做了一個不能點的 neuomorphic-button
今天我們把他可以點擊 & 加上 shadow-dom 讓元件內外的 styling 區隔開來吧 !
昨天我們做了一個不能點的 neuomorphic-button
元件
// neuomorphic-button.js
class NeuomorphicButton extends HTMLElement {
// as Component mounted to page
constructor() {
// Always call super first in constructor
super();
// Element functionality written in here
const div = document.createElement('div')
div.classList.add('icon-box')
div.innerHTML = `<i class="fas fa-wifi"></i>`
this.append(div)
}
}
window.customElements.define('neuomorphic-button', NeuomorphicButton);
首先我們先補上 checkbox
讓其可以被點擊 ,
因為我們要客製化 checkbox
的樣式 , 因此會需要設定 checkbox
的樣式為 display:none
把它隱藏起來
這時我們可以請出 label
這個 Html tag , 用 label
將 input
元素包住 , 將 onclick 事件轉送到 input[type="checkbox"]
上
// neuomorphic-button.js
class NeuomorphicButton extends HTMLElement {
constructor() {
super();
// 利用 div 顯示按鈕的樣式
const div = document.createElement('div')
div.classList.add('icon-box')
div.innerHTML = `<i class="fas fa-wifi"></i>`
// label & 其內部的 checkbox
const label = document.createElement('label')
label.innerHTML = `<input type="checkbox">`
label.append(div)
this.append(label)
}
}
window.customElements.define('neuomorphic-button', NeuomorphicButton);
當然在 html 中我們需要補上一些樣式設定
<style>
/* neuomorphic-button 的樣式 */
label input[type='checkbox'] {
display: none;
}
label .icon-box {
width: 60px;
height: 60px;
position: relative;
background-color: #ebf5fc;
box-shadow: 8px 8px 16px #bcbcbc,
-8px -8px 16px #ffffff;
display: flex;
justify-content: center;
align-items: center;
border-radius: 10px;
cursor: pointer;
transition:all 0.3s;
}
label .icon-box:hover {
transform:translateY(3px)
}
label .icon-box i {
font-size: 2em;
color: #6a9bd8;
}
// 被點選後的樣式
label input[type='checkbox']:checked ~ .icon-box {
box-shadow: inset -2px -2px 5px rgba(255, 255, 255, 1),
inset 3px 3px 5px rgba(0, 0, 0, 0.1);
}
label input[type='checkbox']:checked ~ .icon-box i {
transform: scale(0.95);
filter: hue-rotate(90deg);
}
</style>
之後我們得到了一個可點擊的 neuomorphic-button
目前我們的 style
是定義在 html 的 header 中 , 如果有其他的 css 設定可能會造成互相影響
這時我們就可以請出 shadow dom
來 ~~~
const shadowRoot = this.attachShadow({mode: 'open'})
既然我們都改用 shadow dom
那當然需要將掛在 this 上的那些 HTML 元素 , 改掛在 shadowRoot
的上面
// neuomorphic-button.js
class NeuomorphicButton extends HTMLElement {
// as Component mounted to page
constructor() {
...跟之前相同的設定
// 將 label 改 append 到 shadowRoot 上面
const shadowRoot = this.attachShadow({mode: 'open'})
shadowRoot.append(label)
}
}
window.customElements.define('neuomorphic-button', NeuomorphicButton);
改後我們會獲得以下截圖
奇怪 , 外部有定義樣式阿 ~ , 那 neuomorphic-button
元件內的樣式為何會沒有吃到呢 ?
原來 shadow dom
也就是 this.attachShadow({mode: 'open'})
會將 shadowRoot 中的樣式跟外部 Html 的樣式做一個區隔
所以 , 我們需要在 shadowRoot
的內部再定義一次樣式
// neuomorphic-button.js
class NeuomorphicButton extends HTMLElement {
// as Component mounted to page
constructor() {
...跟之前相同的設定
// 將樣式相關的部分 , 定義在此
+ const fontAwesomeStyle = `<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css">`
+ const styleStr = 'neuomorphic-button 的樣式'
// 將 label 改 append 到 shadowRoot 上面
const shadowRoot = this.attachShadow({mode: 'open'})
+ shadowRoot.innerHTML = fontAwesomeStyle + styleStr // 將定義出來的樣式 , 掛載到 shadowRoot 內部
shadowRoot.append(label)
}
}
window.customElements.define('neuomorphic-button', NeuomorphicButton);
太棒了 ! 按鈕吃到我們設定的樣式了 (^∀^●)ノシ
如果想查看實際頁面 , 請到 shadow-dom.html 查看
下方情況 label 會將 onclick 事件做一個轉送 , 事件將傳給對應的元素並觸發其 onclick
A. for 對應的那個 name HTML 元素
<div class="preference">
<label for="cheese">Do you like cheese?</label>
<input type="checkbox" name="cheese" id="cheese">
</div>
B. 包在 label 內的 input 元素
<label>
<input type="checkbox">
I agree to the Terms and Conditions
</label>
因此我們需要利用 隱藏原生 checkbox
+ 設定 div 樣式
來製作自身想要的 checkbox
<label>
<!-- 隱藏原生 checkbox -->
<input type="checkbox" style="display:none">
<!-- 將想要的 checkbox 樣式設定在 myCheckbox 中 -->
<div class="myCheckbox">
</label>
詳細的 Styling checkbox 步驟請參考 這篇