【问题标题】:Access the parent selector from within a SASS mixin从 SASS mixin 中访问父选择器
【发布时间】:2013-04-15 13:29:35
【问题描述】:

我已经使用 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();
    }
}

【问题讨论】:

  • 将 font-size 设置为 0px 是删除不需要的空格的不可靠方法。如果用户在他们的浏览器中强制设置了最小字体大小,那么您将无能为力。
  • 我已经看过几次了,以确保当 HTML 中有换行符时,内联块之间不会有多余的空格。那么对于这个问题有什么更好的解决方案呢?
  • 我注释掉 HTML 本身的空白。使用 CSS 实现此目的的唯一可靠方法是使元素不内联(通过浮动、表格单元格、通过 Flexbox 等作为 flex 元素)。

标签: sass compass-sass css


【解决方案1】:

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

@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】:

    有一个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 中的确切含义,但在 LESS 中会是

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

    【讨论】:

    • 谢谢!期待 CSS4。
    【解决方案3】:

    从 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";
      }
    }
    

    【讨论】:

    • 是否所有这些都需要让父类的字体大小为 1px?如果没有,你能举一个更简单的例子吗?
    【解决方案4】:

    虽然 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 嵌套意义上的父母。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-07
      • 1970-01-01
      • 2013-09-16
      • 2023-01-24
      • 2013-07-10
      相关资源
      最近更新 更多