У меня есть следующий 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;
}
}
}
}
}
}
IMHO этот вопрос касается родительского селектора Sass & (и @at-root и #{&}), который, ну, существует, а не родительского селектора CSS (этот квест был закрыт как обман и снова открыт)






Честно говоря, я не думаю, что вы действительно можете улучшить исходный 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;
}
}
}
}
}
}
Я не думал, что можно использовать вставлять как часть селектора между родительским селектором в Scss ремонтопригодным способом, но, возможно ...
Во-первых, полезная документация: Sass Ampersand (и 3 статьи в конце!) из CSS-Tricks ссылается на используя миксин после хорошо известных случаев, когда & можно использовать (а где нельзя), а также #{&}, когда вы хотите использовать & дважды (я не знал о последнем и Я пробовал + много раз терпел неудачу с && и li&, вздох).
Этот миксинкак есть не поможет в вашем случае, но вот мой вариант:
Миксин scss, который будет принимать 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)Я бы также заменил этот идентификатор классом, даже для компонентов, которые, как вы точно знаете, будут существовать на странице только один раз. Я сопротивлялся пару лет в этом случае, и это почти такая же чума, как и все остальные ...
Делайте селекторы CSS короткими от CSSWizardry - хорошее начало (просмотрите его архивы с 2012 по 2016 год, чтобы узнать больше) Методологии CSS этот масштаб ©:
Вы не можете, потому что
.active- это класс элемента<li>. Вы не можете перемещаться вверх с помощью селекторов.