英文連接:Shadow DOM: Styles (cont.), 29 AUGUST 2013 on Web Components, Shadow DOMcss
在昨天的博文裏咱們總體討論了設置 Shadow DOM 樣式的一些基本事項,但咱們僅僅觸及了一些皮毛。今天咱們緊接着上文繼續討論怎樣使用分佈節點(distributed nodes)以及怎樣將咱們的組件打通使外部可使用並自定義。html
在今天開始以前,我想要感謝 Eric Bidelman 的這篇介紹 Shadow DOM 樣式添加的宏文(能夠戳中文譯版)。本文的大部分都是我對他這篇博文內容的實踐。若是有機會的話你必定要去讀一下HTLM5 Rocks 關於 Web Components 的所有文章。html5
我建議你使用 Chrome v33+ 來實驗本文的例子,由於 33+ 的 Chrome 對我所描述的這些新特性都有瀏覽器的原生支持。node
經過閱讀各類博客,我認識到了一點:在使用 shadow DOM 的時候應該確保內容和表現的分離。換句話說,若是你的一個按鈕上想展現一些文本,那麼這些文本應該來自頁面而不是埋在 shadow DOM 的模板裏。來自頁面並經過 <content>
標籤添加到 shadow DOM 的內容被稱爲分佈節點。web
在最開始我困惑於如何給分佈節點添加樣式的時候,我這樣寫 CSS 的:瀏覽器
<div class="some-shadow-host"> <button>Hello World!</button> </div> <template> <style> :host { ... } button { font-size: 18px; } </style> <content></content> </template>
試想若是 button
是來自影子宿主的話,一旦它被 <content>
標籤選中,就應該能被個人樣式渲染。然而事實卻並不是如此,實際上,分佈節點的樣式渲染須要用到 :content
僞類選擇器。這樣作是十分有意義的,由於咱們可能會想讓影子模板中的按鈕與出如今 <content>
標籤中的按鈕擁有不一樣的樣式。app
讓咱們看一個實例:dom
<body> <div class="widget"> <button>分佈節點碉堡啦!</button> </div> <template class="widget-template"> <style> ::content > button { font-size: 18px; color: white; background: tomato; border-radius: 10px; border: none; padding: 10px; } </style> <content select=""></content> </template> <script> var host = document.querySelector('.widget'); var root = host.createShadowRoot(); var template = document.querySelector('.widget-template'); root.appendChild(document.importNode(template.content, true)); </script> </body>
在這裏咱們將按鈕從 .widget
影子宿主中取出並放置到 <content>
標籤中。使用 ::content
僞類選擇器,咱們使用 >
將 button
定位到子元素並設置了華麗麗的樣式。ide
迄今爲止咱們已經列舉了各類基於 shadow DOM 封裝的優勢,但有時你可能會想讓使用者打破影子邊界的壁壘,讓他們可以給你的組件添加一些樣式。網站
咱們假設你在表單裏建立了一個標誌。在你的模板裏你給輸入框定義了文字的大小,可是你但願用戶能夠改變文字大小以更好的適應本身的網站。使用 ::shadow
僞類選擇器咱們能夠賦予用戶重寫咱們默認定義的自由,若是用戶這樣作的話,他就能夠打破影子邊界的壁壘。
<body> <style> .sign-up::shadow #username, .sign-up::shadow #password { font-size: 18px; border: 1px solid red; } .sign-up::shadow #btn { font-size: 18px; } </style> <div class="sign-up"></div> <template class="sign-up-template"> <style> #username, #password { font-size: 10px; } </style> <div> <input type="text" id="username" placeholder="用戶名"> </div> <div> <input type="password" id="password" placeholder="密碼"> </div> <button id="btn">註冊</button> </template> <script> var host = document.querySelector('.sign-up'); var root = host.createShadowRoot(); var template = document.querySelector('.sign-up-template'); root.appendChild(document.importNode(template.content, true)); </script> </body>
使用 ::shadow
選擇器的一個缺陷是他只能穿透一層影子邊界。若是你在一個影子樹中嵌套了多個影子樹,那麼使用 /deep/
組合符【注】更爲簡便。
<head> <style> #foo /deep/ button { color: red; } </style> </head> <body> <div id="foo"></div> <template> <div id="bar"></div> </template> <script> var host1 = document.querySelector('#foo'); var root1 = host1.createShadowRoot(); var template = document.querySelector('template'); root1.appendChild(document.importNode(template.content, true)); var host2 = root1.querySelector('#bar'); var root2 = host2.createShadowRoot(); root2.innerHTML = '<button>點我點我</button>'; </script> </body>
若是你已經讀了本文和最近的一篇博文那麼在給 shadow DOM 添加樣式方面你已經懂得和我同樣多啦。可是咱們尚未說 JavaScript 呢!咱們把 JavaScript 的部分留到明天再說:)
和以往同樣有問題的話去個人 twitter 或者給我留言,感謝閱讀~
注:組合符(Combinator)是 CSS 裏的一個概念,用於表示兩個選擇器之間的關係。現有的組合符號有後代選擇器(space)、子選擇器(>
)、相鄰兄弟選擇器(+
)和兄弟選擇器(~
)。