英文连接: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)、子选择器(>
)、相邻兄弟选择器(+
)和兄弟选择器(~
)。