尽管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;
}
注:伪元素和伪选择是不是一个元素的孩子,但都连接因此没有父母本身。我认为父母意味着萨斯嵌套意义上的父母。
将font-size设置为0px是删除不需要的空间的不可靠方法。如果用户在他们的浏览器中强制使用最小字体大小,则无法对此进行任何操作。 – cimmanon 2013-04-22 15:33:39
我已经看过几次,以确保在HTML中存在换行符时,内联块不会在它们之间获得额外的空间。那么什么是更好的解决方案呢? – MacBryce 2013-04-22 16:43:46
我注释掉HTML本身的空格。使用CSS的唯一可靠方法是,元素不能内联(通过float,table-cell,通过Flexbox作为Flex元素等)。 – cimmanon 2013-04-22 16:53:29