Для Junior’ов, для junior’ов… а то начнут тут… да мы, да это…

Доделал проект(сайт) pug+sass+es6+gulp+BEM. Во время разработки столкнулся со многими трудностями. Эта статья рассчитана на новичков, на тех, кто не знает об отрицательных маржинах, слышали о методологии именования БЭМ, но не пробовали ее, для тех, кто не имеет огромного опыта в разработке. Надеюсь, вам здесь будет интересно. Если же вы читаете это на работе, сидя у 4-ех мониторов и одной рукой пишите код для ИИ, а второй листаете хабр, то я бы хотел у вас услышать конструктивную критику о методах, которые были использованы здесь.

Отрицательные margin и width 110%
Про такой фокус я знаю давно, но на практики применял лишь впервые. В макете было ограничение(wrapper = width: 1170px, красная граница). Справа контент соответствовал ограничению и прилегал к границе, а вот слева картинка вылезала за границу. Сначала это может пугать, но стоит подробней узнать о работе margin-letf: -100px и вы уже знаете, как решить поставленную задачу. К слову, это flex и желтым я отметил границы объектов.

Мы привыкли использовать width, height как 100%, и это понятно, все для адаптива, с помощью width, можно добиться схожего результата как и с отрицательными маржинами. Просто дайте размер потомку больше своего родителя(например, width: 130%)


Структура css по БЭМ
Это, наверно, было самое сложное для меня.

image

Эта картинка хорошо демонстрирует мой проект, да и вообще любой проект. Когда ты пишешь первую сотню строк, то все кажется простым, и ты не замечаешь проблем. Так ты дописываешь проект, длиной в 900 строк и неожиданно для себя, решил пролистать файлик, ну или добавить медиа запросы.



Ты пишешь стили для элемента в media, смотришь на сайт и не понимаешь, почему стили не работают, как требуется. В поисках проблемы ты потратил уже 15 минут, ты проверил таски в gulp и пролистал скомпилированный файл css.

Случайно, случайно … ты находишь проблему в каскадной таблице стилей, а точнее в способе наложения стилей на элементы. В самом начале моего пути в web, я конечно же читал о том, что у селекторов есть разный приоритет применения. Если кратко, то за обычный(div, ul, a, p и т.д.) селектор -1 бал, за класс-10, за идентификатор 100.



Проверив внимательно все вложенности, я все же нашел ошибку. Оказывается нужно и за вложенностью элементов следить, и придавать этому не последнее значение.

Сюда можно отнести и структуру файла css(sass). Есть Блок “portfolio”, в нем куча элементов по типу “portfolio__*”, но два класса в этой вложенности лишние, на мой взгляд.

Это был первый проект в котором я пытался строго придерживаться BEM, но не потратил и минуты на проектирование в самом начале, а придумывал классы на ходу, это привило к тому, что поддержка дается с трудом.



А вот это, на мой взгляд, хороший пример BEM’a



Длинные классы BEM
Об этой проблеме я читать в одной из статьи посвященной BEM, но сам столкнулся впервые с этим. Очень напоминает проблемы с bootstrap, в нем тоже были… есть длинные классы. Как можно обойтись минимальным количеством классов?

Это default btn.



А это уже модифицированные кнопки…









Сложные селекторы
В учет того, что писать приходилось по BEM, то отсюда вытекали некоторые осложнения в проекте. Про длинные классы я уже написал, вот еще один случай.

На страницы были 6 схожих элементов. При медиа запросах, нужно было прятать определенное количество элементов. Не создавать ведь новые классы для каждого объекта. Пришлось воспользоваться псевдоклассом nth-child(). Раньше его использовал лишь обрезанным способом(child(1), child(3), child(4) и т.д.), сейчас была необходимость спрятать все элементы, кроме первых двух. Потратив 5 мин на чтение документации воспользовался nth-child(n+3), тем самым получив нужный мне результат.



Еще один пример, как можно взять нужный элемент через группу селекторов, а не придумывать специальный класс для этого элемента.



Смотрим картинку ниже. Следующая запись div.1 > p выберет лишь объекты с классом “2”, div.3 > p соответственно будут получены объекты с классом “4”. На картинке показано, как это работает. Выбираются ближайшие элементы вниз по иерархии.



Заключение


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

Комментарии (7)


  1. Koneru
    06.12.2018 09:50

    А зачем в первом примере ухищрения? Почему нельзя просто обрезать картинку?


    1. EpicLegend_gg Автор
      06.12.2018 10:07

      Так сделали макет.
      К примеру, на больших экранах будет асимметрия сайта. Если экран маленький, то основная информация с картинки будет доставлена пользователю, а при больших экранах картинка будет смотреться иначе и при этом, вы не пишите дополнительные стили в медиа запросы.


  1. Against-vegetables
    06.12.2018 10:32

    >Как можно обойтись минимальным количеством классов?
    Можно создать класс со всеми свойствами сразу. То что у вас в примере — больше похоже на атомарный css.


  1. EaGames
    06.12.2018 11:30

    Не пойму я как можно считать класс типа: .blog-post__h3 хорошим примером… Придет сеошник и поменяет ваш `h3` на какой нибудь `h5` или вообще `p`, и потом разбирайся в этом css-е где `p` описывает .blog-post__h3.


  1. anttoshka
    06.12.2018 11:31

    Не стоит такое читать джунам. В заголовке написано про pug, gulp. О них в статье ни слова.
    Хороший пример БЭМ странный. Зачем использована вложенность и повышена специфичность?
    Сложные селекторы. Каким боком они относятся к БЭМ? По БЭМ нельзя использовать теги.
    Длинные классы. Это вообще какая-то жесть. Используйте миксины. Берем условную кнопку .blog__button, в нее добавляем через миксины import button, button--default и т.д. На выходе имеем кнопку с нужными стилями. Другой вариант все добавлять классы на кнопку, но уникальные правила добавлять на класс .blog__button. Стоит за пример взять бутстрап. На кнопке 2-3 стандартных класса, остальное можно добавить через свой уникальный класс. У вас же, как указали в комменте выше, больше похоже на атомарный CSS, чем на БЭМ.


  1. perfect_pixel
    06.12.2018 15:14

    Согласен с предыдущими комментатороми. Дополню. В каких-то аспектах вы не верно поняли суть БЭМа.
    Я конечно понимаю, что толковать бэм можно и нужно по разному. Но:
    1) Вложенность ВЕЗДЕ ужасна. Чтобы перебить в медиа запросе ваше правило, опять придется повторять эту вложенность
    2) Разбивать стили кнопок на мелкие классы, это конечно «атомарно», но что-то я сомневаюсь, что дизайнер нагородил в макете 20 разных вариантов кнопок. Сделайте более осмысленные классы для кнопок. Пусть это будет .btn_blog, .btn_comments. Ссылка 'Read more' имхо вообще не должна являться .btn
    3) Привязка в тегам, а тем более селекторы типа > — тоже далеко не бэм. Всегда представляйте, что передадите этот проект другому разработчику, и как он это сможет легко поломать.


  1. ArsenAbakarov
    06.12.2018 16:33

    Не пишите никогда something__h2… Потом задолбаетесь, выше уже писали, как пример БЭМ:

    SCSS
    $BODY_HEIGHT: 42px;
    
    .header-bottom {
      background-color: $COLOR_MAIN;
      height: $BODY_HEIGHT;
      padding: 4px 10px;
      border-radius: 10px;
      border-bottom-left-radius: 0;
      color: $COLOR_WHITE;
    
      @include screen_m {
        border-bottom-left-radius: 10px;
      }
    
      &__inner {
        height: $BODY_HEIGHT;
      }
    
      &__catalog-text {
        vertical-align: middle;
        font-size: 16px;
        font-weight: bold;
        margin-left: 5px;
    
        @include screen_m {
          display: none;
        }
      }
    
      &__icon {
        vertical-align: middle;
      }
    
      &__catalog-icon {
        margin-left: 5px;
      }
    
      &__like, &__compare, &__cart {
        position: relative;
        display: inline-block;
        vertical-align: middle;
        font-weight: bold;
        margin-left: 15px;
      }
    
      &__cart {
        font-size: 16px;
        margin-left: 20px;
      }
    
      &__like-counter {
        position: absolute;
        bottom: -5px;
        right: -5px;
      }
    
      &__compare-counter {
        position: absolute;
        bottom: -5px;
        right: -8px;
      }
    
      &__search {
        display: inline-block;
        vertical-align: middle;
        margin-left: 100px;
        margin-right: 60px;
        width: 555px;
    
        @include screen_m {
          width: 410px;
          margin-left: 20px;
          margin-right: 20px;
        }
      }
    }