0

我有以下 HTML:

<ul id="navbar-main" class="navbar-nav mr-auto">
    <li class="nav-item active">
        <a href="https://travian.dev/materials" class="nav-link nav-materials">
            <span class="invisible">Materials</span>
        </a>
    </li>
</ul>

以及以下 SCSS:

#navbar-main {
  li {
    &.nav-item {
      .nav-link {
        width: 50px;
        height: 50px;
        background: no-repeat center;
        background-size: contain;

        &.nav-materials {
          background-image: url('../images/buttons/menu-materials.png');
        }
      }

      &.active {
        .nav-link {
          &.nav-materials {
            background: red;
          }
        }
      }
    }
  }
}

这是可行的,但我希望它更易于维护/更易于阅读。如果可能的话,我希望它是这样的:

#navbar-main {
  li {
    &.nav-item {
      .nav-link {
        width: 50px;
        height: 50px;
        background: no-repeat center;
        background-size: contain;

        &.nav-materials {
          background-image: url('../images/buttons/menu-materials.png');

          .active { // here something to actually select .nav-item.active .navlink.nav-materials
            background: red;
          }
        }
      }
    }
  }
}
4

2 回答 2

0

老实说,我认为您无法真正改进您提供的原始 SCSS。Sass 父选择器 ( &) 选择整个父链

这很尴尬,但是您可以使用@at-root它返回样式表的根目录,然后替换部分选择器,如下所示:

/// Replace `$search` with `$replace` in `$string`
/// @author Hugo Giraudel
/// @param {String} $string - Initial string
/// @param {String} $search - Substring to replace
/// @param {String} $replace ('') - New value
/// @return {String} - Updated string
@function str-replace($string, $search, $replace: '') {
  $index: str-index($string, $search);

  @if $index {
    @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
  }

  @return $string;
}

#navbar-main {
  li {
    &.nav-item {
      .nav-link {
        width: 50px;
        height: 50px;
        background: no-repeat center;
        background-size: contain;

        &.nav-materials {
          background-image: url('../images/buttons/menu-materials.png');

          @at-root #{str-replace(#{&}, ".nav-item", ".nav-item.active")} {
            background: red;
          }
        }
      }
    }
  }
}
于 2018-05-30T13:14:28.970 回答
0

我认为不可能以可维护的方式在 Scss 中的父选择器之间插入选择器的一部分,但也许……</p>

首先,有用的文档:CSS-Tricks 中的 Sass Ampersand (以及最后的 3 篇文章!)在众所周知的可以使用(以及不能使用)以及何时使用的情况下使用 mixin参考两次(我不知道后者,我用 and 尝试+失败了很多次,叹息&#{&}&&&li&

这个mixin对你 情况没有帮助,但这是我的看法:

Scss mixin需要 3 个参数来构建一个或另一个选择器和任何规则块

➡️ Codepen

@mixin nav-bg($parent, $active, $sel) {
  @at-root #{$parent} {
    &#{$active $sel} {
      @content;
    }
  }
}


#navbar-main {
  li {
    &.nav-item {
      .nav-link {
        width: 50px;
        height: 50px;
        background: no-repeat center;
        background-size: contain;
      }

      @include nav-bg(&, '', '.nav-materials') {
        background-image: url('../images/buttons/menu-materials.png');
      }

      @include nav-bg(&, '.active', '.nav-materials') {
        background: red;
      }
    }
  }
}


// output
#navbar-main li.nav-item .nav-link {
  width: 50px;
  height: 50px;
  background: no-repeat center;
  background-size: contain;
}
#navbar-main li.nav-item .nav-materials {
  background-image: url("../images/buttons/menu-materials.png");
}
#navbar-main li.nav-item.active .nav-materials {
  background: red;
}


如果您的目标是尽可能可维护,我建议您完全改变嵌套选择器的方式并减少它们的特异性
这是我重写你的块的方法:

➡️特异性较低(Codepen)

#navbar-main {
  .nav-link {
    width: 50px;
    height: 50px;
    background: no-repeat center;
    background-size: contain;
  }

  .nav-materials {
    background-image: url('../images/buttons/menu-materials.png');
  }

  .active {
    .nav-materials {
      background: red;
    }
  }
}

Sass references: [@content](http://sass-lang.com/documentation/file.SASS_REFERENCE.html#mixin-content), [@at-root](http://sass-lang.com/documentation/file.SASS_REFERENCE.html#at-root)

我还会用一个类替换该 id,即使对于您确定在页面上只存在一次的组件也是如此。在那种情况下,我抗拒了几年,这几乎和其他情况一样是一场瘟疫……</p>

CSSWizardry保持你的 CSS 选择器简短是一个好的开始(扫描他从 2012 年到 2016 年的档案以获取更多信息)可扩展的 CSS 方法©

于 2018-05-30T13:53:26.897 回答