从SASS mixin中访问父选择器

时间:2013-04-22 15:16:11

标签: sass compass-sass css

我使用display:inline-block为按钮设置了mixin。我试图找到最终会使用mixim的任何类的父类,所以我可以在那里添加font-size:0px行以确保我不需要对我的HTML进行调整以避免不必要的每个按钮之间的空间。

这是一个例子......我想要的。父类接收font-size:0px行。

@mixin button() {
    display:inline-block;
    font-size: 1em;
    //other stuff to make a pretty button
    && { font-size: 0px; }
}

.parent{
    .child {
        @include button();
    }
}

4 个答案:

答案 0 :(得分:13)

截至Sass 3.4,现在已经可以了。

@mixin parent {

  @each $selector in & {

    $l: length($selector);

    @if ($l == 1) {
      @error "Used parent mixin on a top-level selector";
    } @else {

      $parent: nth($selector,1);
      @for $i from 2 to $l {
        $parent: append($parent,nth($selector,$i));
      }

      @at-root #{$parent} {
        @content;
      }

    }
  }
}

// Use
.grandparent {
  .parent{
      .child {
        font-size: 1em;
          @include parent {
            font-size: 0px;
          }
      }
  }
}

// Result
.grandparent .parent .child {
  font-size: 1em;
}
.grandparent .parent {
  font-size: 0px;
}

// Errors:
.root {
  @include parent {
    content: "Won't work";
  }
}
.grandparent .parent, .root {
  @include parent {
    content: "Also won't work";
  }
}

答案 1 :(得分:7)

不,这是不可能的。不过你可以这样做:

@mixin button($child: '.child') {
    font-size: 0px;
    //other stuff to make a pretty button

    #{$child} {
        display:inline-block;
        font-size: 1em;
    }
}

.parent{
    @include button();
}

输出:

.parent {
  font-size: 0px;
}
.parent .child {
  display: inline-block;
  font-size: 1em;
}

答案 2 :(得分:2)

有一个XXX! CSS 4规范草案中的选择器,它将作为您喜欢的方式。如果选择器匹配

,它会宣布CSS样式声明的主题

所以如果你有这个选择器

.a > .b! > .c

它会匹配,例如为此

<div class="a">
    <div class="b">
        <div class="c">
        </div>
    </div>
</div>

但样式声明不会对.c生效,而是.b,因为我用感叹号宣布,这个元素应该是样式的主题 http://dev.w3.org/csswg/selectors4/#subject

您现在无法立即使用它。但是有一个jQuery插件,就是这样的polyfill。 http://dev.w3.org/csswg/selectors4/

另见此堆栈:Is there a CSS parent selector?

如何申请? 好吧,我不完全确切地知道SASS,但是很少会是

*! > & {
    /* ... */
}

答案 3 :(得分:0)

虽然Karol的答案接近完美,但它没有考虑伪元素或伪选择器。此外,如果使用多个complex selector,代码将重复。我提出了一个简化版本:

@mixin parent {
    $parents: ();
    $parent: '';

    @each $selector in & {
        $length: length($selector);
        $index: 0;
        $last-selector: nth($selector, $length);

        @if ($length == 1) {
            @error "Used parent mixin on a top-level selector";
        } @else {
            $index: str-index($last-selector, '::');

            @if ($index) {
                $last-selector: str-slice($last-selector, 1, $index - 1);
            } @else {
                $last-selector: null;
            }
            // Inspect allows us to combine two selectors in one block.
            $parent: inspect(set-nth($selector, $length, #{$last-selector}));
            $parents: join($parents, $parent, comma);
        }
    }
    @at-root #{$parents} {
        @content;
    }
}

有一个第一个循环迭代selector list(末尾有逗号的选择器)。因为复杂的选择器也被视为列表,我们只需要删除列表的最后一个元素。没有循环迭代复合或简单选择器,因为我们只需要丢弃最后一个。

Sass中没有删除列表元素的功能,但我们可以使用set-nth设置元素的值。通过将最后一个元素作为空字符串并取消引用它,我们可以从列表的打印表示(字符串)中删除最后一个元素。由于选择器可以是字符串,我们只需使用新字符串作为选择器。

使用以下内容时:

.grandmother,
.grandfather {
  .parent {
      .child {
        font-size: 10em;
          @include parent {
            font-size: 5em;
          }

          &::after {
            font-size: 1px;
            @include parent {
              font-weight: bold;
            }
          }
      }
  }
}

我们得到以下信息:

.grandmother .parent .child,
.grandfather .parent .child {
  font-size: 10em;
}
.grandmother .parent,
.grandfather .parent {
  font-size: 5em;
}
.grandmother .parent .child::after,
.grandfather .parent .child::after {
  font-size: 1px;
}
.grandmother .parent .child,
.grandfather .parent .child {
  font-weight: bold;
}

注意:伪元素和伪选择器不是元素的子元素,而是附加,因此它们本身没有父元素。我认为父母的意思是Sass筑巢意义上的父母。