Как выбрать родительский элемент с помощью scss

У меня есть следующий 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;
          }
        }
      }
    }
  }
}

Вы не можете, потому что .active - это класс элемента <li>. Вы не можете перемещаться вверх с помощью селекторов.

Terry 30.05.2018 14:21

IMHO этот вопрос касается родительского селектора Sass &@at-root и #{&}), который, ну, существует, а не родительского селектора CSS (этот квест был закрыт как обман и снова открыт)

FelipeAls 30.05.2018 14:24
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
CSS: FlexBox
CSS: FlexBox
Ранее разработчики использовали макеты с помощью Position и Float. После появления flexbox сценарий полностью изменился.
0
2
1 841
2

Ответы 2

Честно говоря, я не думаю, что вы действительно можете улучшить исходный 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 этот масштаб ©:

Другие вопросы по теме