跨越上边界的选择者还是什么?

时间:2012-09-04 10:58:20

标签: css css-selectors shadow-dom

我正在为我们公司编写RIA系统(仅限铬)。不同控件的数量正在增长,我决定使用Shadow DOM简化代码。它很棒,但有时它需要外部重新造型。这就是问题,例如:

任务栏:

<taskbar side="right">
  <menubtn />
  <applist scrollable>
    <btn app="SpoPlanMon" />
  </applist>
  <tray />
</taskbar>

使用Shadow DOM,applist转换为:

<applist>
  <scroll-wrap>
    <scroll-bar>
      <scroll-slider />
    </scroll-bar>
    <scroll-cont>
      <btn app="SpoPlanMon" />
    </scroll-cont>
  </scroll>
</applist>

在这种情况下,我需要根据<scroll-slider />侧(在所谓的属性中指定,可以动态更改)来设置<taskbar />样式。不幸的是,我不能只写taskbar[side="top"] scroll-slider {...},因为只允许低边界封装。

有没有办法从“另一边”css选择元素?或者像video::-webkit-media-controls-panel

之类的东西

2 个答案:

答案 0 :(得分:1)

如果您使用的是成熟的Web Components而不是Shadow DOM,那么您应该能够从Javascript获取父任务栏元素。像这样:

<element>
    <template>
        ...
    </template>
    <script>
        if (this !== window) {
            this.lifecycle({
                created: function() {
                    this.parentElement.attributes['side'].nodeValue; // "right"
                }
            });
        }
    </script>
</element>

然而,这使得您无法再在任务栏之外使用applist组件,这通常是一件坏事。我们应该尝试使组件尽可能模块化,独立和可重用。问问自己,“我究竟需要了解哪些父元素?”您可以改为将应用列表写为

<applist scrollable="right">...

为了在任何地方使用此组件的能力,复制是一个很小的代价。谁知道?将来,您可以决定使用side="right"scrollable="bottom"的方式使用任务栏和应用列表!

<强>更新

如果您希望允许Shadow DOM元素的样式随主机元素的更改而动态更改,您很快就可以使用@host @-rule。规范在这里根本不清楚,但我认为它会像这样使用(取自a comment on a bug for the W3 spec for Web Components):

@host {
    div { background-color: white; }
    .warning { background-color: yellow; }
    .important .warning { background-color: orange; }
}

这会(我认为)为主机提供白色的默认背景颜色,如果主机具有类warning,则会将其覆盖为黄色。它还会在主机内部设置警告元素,背景颜色为橙色,如果主机具有类important

答案 1 :(得分:1)

您可以使用CSS变量将左/右上下文传递到滑块。有关工作示例,请参阅this jsfiddle。 (您必须在Chrome中启用启用实验性WebKit功能标记。)

以下是它的工作原理:外部组件为每个依赖于上下文的属性设置变量(在这种情况下,在左侧或右侧)。在这个例子中,我只是设置一个变量,一个颜色:

<style>
*[side="right"] {
  -webkit-var-slider-color: red;
}

*[side="left"] {
  -webkit-var-slider-color: green;
}
</style>
<taskbar side="right">
  <menubtn />
  <applist scrollable>
    <btn app="SpoPlanMon" />
  </applist>
</taskbar>​

该组件只使用变量:

<applist>
  <style>
  scroll-slider {
    background: grey; /* default */
    background: -webkit-var(slider-color);
  }
  </style>
  <scroll-wrap>
    <scroll-bar>
      <scroll-slider />
    </scroll-bar>
    <scroll-cont>
      <btn app="SpoPlanMon" />
    </scroll-cont>
  </scroll>
</applist>

在此示例中,<taskbar side="right">元素将slider-color变量设置为红色。 CSS变量自动流入Shadow DOM,因此在applist中,滚动滑块的背景设置为红色。如果您将任务栏更改为side =“left”,则会重新计算样式,并且滚动滑块的背景会自动翻转为绿色。

如果要配置更多属性,只需使用更多变量。

在使用它的地方定义属性的目的

background: grey; /* default */
background: -webkit-var(slider-color);

是处理未设置变量的情况。在这种情况下,第二个属性定义将无效,导致它被删除,因此第一个属性定义适用。正确设置变量后,第二个定义有效并覆盖第一个定义。

关于CSS变量的简洁部分是它们与定义变量的元素一起嵌套。因此,如果SpoPlanMon Shadow DOM中有<taskbar side="left">,它会将slider-color变量重置为绿色,嵌套在其中的任何滑块都将为绿色。

有一个设计方案允许Web组件使用作者定义的伪ID将shadow DOM中的部件暴露给“来自外部”的样式。 (W3 Bug 15196并不是非常具有描述性,但这是规范错误。)

要使用伪ID解决此问题,AppList会使用伪ID公开其滚动滑块:

<applist>
  <scroll-wrap>
    <scroll-bar>
      <scroll-slider pseudo="slider" />
    </scroll-bar>
    <scroll-cont>
      <btn app="SpoPlanMon" />
    </scroll-cont>
  </scroll>
</applist>

然后任务栏可以设置样式:

<taskbar side="right">
  <style scoped>
    taskbar[side="right"] applist:pseudo(slider) {
      /* styles apply to the <scroll-slider> */
    }
  </style>
  <menubtn />
  <applist scrollable>
    <btn app="SpoPlanMon" />
  </applist>
  <tray />
</taskbar>

这很好,因为它将任务栏上下文的样式与任务栏一起保存。应用程序列表需要在其滑块上放置一个伪,因此如果你重复使用一个没有为你需要设置样式的所有内容的组件,你就会遇到麻烦(CSS很强大,所以它带来很大的功能来搞砸了,所以我认为组件通常不会暴露很多伪ID。)

这没有实现,甚至在规格中!事实上,确切的语法可能会改变。所以现在你不能依赖伪ID解决方案。 CSS变量可能是要走的路。