БЭМ с SASS и :hover

Каков правильный способ объявления состояний активности/фокуса/зависания с использованием БЭМ с SASS? Например, у меня есть такая структура:

<div class="card">
    <img class="card__image" src="..." alt="">
    <div class="card__overlay">
        <div class="card__title"></div>
    </div>
</div>    

И СКСС:

.card {
   &__image {
   }

   &__overlay {
   }

   &__title {
   }
}

И я хочу изменить элементы при наведении на блок. Это не работает:

.card {
   &__overlay {
       display: none;
   }

   &:hover {
       &__overlay {
           display: block;
       }
   }
}

И писать все .project__image только для этого экземпляра кажется неправильным.

Есть ли другой способ сделать это?


person so4t    schedule 01.12.2015    source источник
comment
Проблема вот в чем именно? Если вы посмотрите на скомпилированные результаты, ответ кажется довольно очевидным. Попробуйте прогнать результаты через валидатор, если вы все еще не понимаете, что не так с CSS.   -  person cimmanon    schedule 01.12.2015
comment
Оно работает. Проверьте это.   -  person Alex    schedule 01.12.2015
comment
Не работает второй раздел кода, а не первый. Тот, который находится в состоянии наведения.   -  person so4t    schedule 01.12.2015
comment
Не работает не объясняет в чем проблема. importblogkit.com/2015/07/does-not-work   -  person cimmanon    schedule 01.12.2015
comment
Извини. Это не работает, потому что компилируется в .card:hover__overlay вместо желаемого .card:hover .card__overlay.   -  person so4t    schedule 01.12.2015


Ответы (3)


Вы можете добиться желаемого результата с помощью селектора Sass с амперсандом без использования переменных. или интерполяция.

Ссылка на родительские селекторы с помощью амперсанда (&) может быть мощным инструментом при правильном использовании. Есть простые способы использования этой функции, а также некоторые очень сложные варианты использования этой функции.

Например:

.card { 

    &__overlay {
        display:none;
    }

    &:hover & {
        &__overlay  {
            display: block;
        }   
    }
}

Результат:

.card__overlay {
    display: none;
}

.card:hover .card__overlay {
    display: block;
}

Этот код использует меньше языковых конструкций (например, не использует переменные или интерполяцию) и, возможно, является более чистой реализацией.

person aaronmarruk    schedule 07.11.2016
comment
Не знаю, почему я никогда не думал об этом, это гениально. Но что, если вам нужно применить стили и к card:hover? - person ESR; 22.12.2017
comment
Вау, это гениально! - person Aamir Khan; 13.05.2018
comment
Это не работает, если он вложен в любой другой родитель (он становится .parent .card .parent .card__overlay) - person Ivan Castellanos; 04.11.2020

Подробнее об интерполяции: http://sass-lang.com/documentation/file.SASS_REFERENCE.html#interpolation_

СКСС:

.card {
    $root: &;

    &__overlay {
        display: none;

        #{$root}:hover & {
            display: block;
        }
    }
}

РЕЗУЛЬТАТ:

.card__overlay {
  display: none;
}

.card:hover .card__overlay {
  display: block;
}

PS. Это похоже на сообщение @alireza safian, но таким образом вам не нужно дублировать имя класса. Переменная $root сделает это за вас :)

person mwl    schedule 01.12.2015
comment
К сожалению, версия Gonzales PE: 3.0.0-28, похоже, не любит этот синтаксис: S - person Simon Arnold; 08.12.2017
comment
Это похоже на анти-шаблон - person sidonaldson; 13.05.2019

Альтернативный способ:

Используйте переменную вместо амперсанда для третьего уровня.

Ссылка

САСС:

$className: card;
.card {
   &__overlay {
       display: none;
   }

   &:hover {

       .#{$className}__overlay {
           display: block;
       }
   }
}

CSS:

.card__overlay {
  display: none;
}

.card:hover .card__overlay {
  display: block;
}
person Alex    schedule 01.12.2015