使用:host-context()与相邻的兄弟选择器

时间:2016-08-17 08:53:06

标签: html css css3 css-selectors web-component

我正在尝试使用:host-context()和相邻的兄弟选择器来设置这样的元素:

<x-foo id="1" active></x-foo>
<x-foo id="2"></x-foo> <!-- use :host-context() to target #2 when adjacent sibling, #1 is [active] -->
<x-foo id="3"></x-foo>

我的元素定义类似于:

<dom-module id="x-foo">
    <template>
        <style>
           :host-context(x-foo[active] + x-foo) {
               background-color: yellow;
           }
        </style>
        Hello
    </template>
    <script src="x-foo.js"></script>    
</dom-module>

然而,这并不是很有效。为什么不呢?

2 个答案:

答案 0 :(得分:7)

:host() and :host-context() only accept a compound selector as their argument,而不是复杂的选择器。

x-foo[active] + x-foo是一个复杂的选择器,包含两个复合选择器x-foo[active]x-foo,由相邻的兄弟组合子分隔。 :host():host-context()可以接受复合选择器,但不能接受任何组合器。

不幸的是,由于影子主机的兄弟姐妹在影子上下文中不存在,因此您将无法编写类似x-foo[active] + :host的内容。因此,我认为您无法在阴影环境中完成您想要完成的任务。 (当然,在光照环境中,您可以只编写x-foo[active] + x-foo,但这会使将CSS预先打包成Web组件的目的失败。)

我不清楚为什么:host():host-context()首先不允许使用复杂的选择器,因为如果他们这样做了,那么你所拥有的只会有效。

答案 1 :(得分:0)

解决方法是添加全局<style>规则。

您可以根据需要添加(例如attachedCallback/connectedCallback)。在上面的代码段中,我将<style>标记放在自定义元素的<template>中,并在x-foo定义后移动它。

customElements.define( 'x-foo', class XFoo extends HTMLElement {
  constructor() {
    super()
    this.attachShadow( { mode: 'open'} )
    this.shadowRoot.appendChild( tpl.content.cloneNode( true ) )
  }
} )

customElements.whenDefined( 'x-foo' ).then( () =>
  document.head.appendChild( tpl.content.getElementById( 'global' ) )
)
<x-foo id="1" active></x-foo>
<x-foo id="2"></x-foo>
<x-foo id="3"></x-foo>

<!-- custom element v1 -->
<template id="tpl">
  <style id="global">
    x-foo[active] + x-foo { background: yellow ; color: red }
  </style>

  <style>
    :host { background: lightblue ; display: inline-block }
    span { color: initial }
  </style>

  <span>Hello</span>
</template>

注意:我使用了自定义元素(v1)而不是Polymer,它可以在Chrome v53+中使用。