SASS / SCSS-制作一个将“退出”以修改选择器父级的选择器

时间:2018-09-11 22:49:06

标签: css sass

我想在一个代码块中包含选择器的所有相关样式,以便可以轻松地引用它。

在我的应用程序中,选择器的有效样式将根据其所在的上下文而发生巨大变化。例如,假设此CSS:

.container.theme-dark .message
{
    font-size: 16px;
    background-color: black;
    color: white;
}

.container.theme-light .message
{
    font-size: 16px;
    background-color: white;
    color: black;
}

然后,假设我有以下HTML:

<div>
    <div class="container theme-dark">
        <div class="message">Hello World</div>
    </div>
    <div class="container theme-light">
        <div class="message">Hello World</div>
    </div>
</div>

现在使用SCSS,我将像这样创建相关的CSS:

.container
{
    &.theme-dark
    {
        .message
        {
            background-color: black;
            color: white;
        }
    }

    &.theme-light
    {
        .message
        {
            background-color: white;
            color: black;
        }
    }

    .message
    {
        font-size: 16px;
    }
}

我希望能够使用SCSS生成该CSS,并将.message元素的所有相关信息都放在一个位置。例如(使用虚构的$运算符可以完成我想完成的工作):

.container
{
    .message
    {
        font-size: 16px;

        $.theme-light
        {
            background-color: white;
            color: black;
        }

        $.theme-dark
        {
            background-color: black;
            color: white;
        }
    }
}

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

我认为这可能有效,就像您在说什么? (如果您将每个示例分别标记为“理想的CSS输出”,“当前的SCSS,太多的.message块”和“理想的SCSS格式”,这将对我有帮助)

.container
{
    @at-root .message
    {
        font-size: 16px;

        .theme-light &
        {
            background-color: white;
            color: black;
        }

        .theme-dark &
        {
            background-color: black;
            color: white;
        }
    }
}

有了@at-root,它将生成.theme-light .message,对于某些用法来说可能太宽容了,所以不是理想的解决方案...

https://codepen.io/anon/pen/ZMxjEq

基本上&被完整的树路径所取代,因此.container .message(如果没有@at-root,则将生成.theme-light .container .message),该结构不适用于该结构。也许还要考虑一下,我会说这是一个合理的妥协:

.container
{
    .message
    {
        font-size: 16px;
    }
    @at-root .message
    {
        .theme-dark
        {
            ...
        }

        .theme-light
        {
            ...
        }
    }
}

它是apparently a kind of hacky solution,但显然可以使用

This page might have some better guidance as well

答案 1 :(得分:1)

如果您以编程方式使用sass,则可以实现此组织:

$themes: light dark;

.container {
    @for $i from 1 through length($themes) {
        &.theme-#{nth($themes,$i)} {
            .message {
                font-size: 16px;
                @if nth($themes,$i) == light {
                    background-color: white;
                    color: black;
                } @else if nth($themes,$i) == dark {
                    background-color: black;
                    color: white;
                }
            }
        }
    }
}

这将生成:

.container.theme-light .message {
  font-size: 16px;
  background-color: white;
  color: black;
}
.container.theme-dark .message {
  font-size: 16px;
  background-color: black;
  color: white;
}

嵌套循环自动将同一代码块中每个级别的详细信息分组。这也可以缩放到多层嵌套。关键是在内部循环中,您可以引用外部循环的选择器。

答案 2 :(得分:0)

我最终找到了这个GitHub: https://github.com/imkremen/sass-parent-append/blob/master/parrent-append.scss

我已适应此解决方案:

@function str-to-list($string, $separator: ' ', $startAt: 1) 
{
    $workStr: str-slice($string, $startAt);
    $list: ();
    $indexOfFirstSpace: str-index($workStr, $separator);
    @if ($indexOfFirstSpace == null)
    {
        $list: ($workStr);
    }
    @else
    {
        $list: (str-slice($workStr, 1, $indexOfFirstSpace - 1));
        $list: join($list, str-to-list($workStr, $startAt: $indexOfFirstSpace + 1));
    }
    @return $list;
}

@function getBase($appendix)
{
    $parentSelector: str-to-list(#{&});
    $pos: (length($parentSelector) - 1);
    $selector: set-nth($parentSelector, $pos, nth($parentSelector, $pos) + $appendix);
    @return $selector;
}

@mixin base($appendix)
{
    @at-root #{getBase($appendix)}
   {
      @content;
   }
}

然后我可以这样使用:

.container
{
    .message
    {
        font-size: 16px;
    }

    @include base(".theme-light")
    {
        background-color: white;
        color: black;
    }

    @include base(".theme-dark")
    {
        background-color: black;
        color: white;
    }
}

编译成这样:

.container .message
{
    font-size: 16px;
}

.container.theme-light .message
{
    background-color: white;
    color: black;
}

.container.theme-dark .message
{
    background-color: black;
    color: white;
}