Как добавить класс чтобы прежние классы остались js
Перейти к содержимому

Как добавить класс чтобы прежние классы остались js

  • автор:

Курсы javascript

Правильно ли я понял, что 2-й вариант работает не на всех браузерах, только на новых, и лучше воспользоваться первым?

Последний раз редактировалось newobject, 20.07.2014 в 22:21 .
20.07.2014, 22:38
Регистрация: 27.05.2010
Сообщений: 33,009
20.07.2014, 22:54
Регистрация: 30.04.2013
Сообщений: 92

newobject,
я новенькая в этом деле но все же)))

я делаю это так
если есть основной блок

$(".osnovnoy-div(название class или id основного дива) div(или за место div любой другой элемент span или что то свое)[id*=id-esli-est'']").addClass('new-name-class').html();

как выглядит это

 

после как скрипт обработает

Строго не судите пожалуйста я только учусь))

Добавление/удаление классов с помощью JavaScript свойства classList

classList — это свойство, которое открывает нам доступ к четырём методам. С их помощью мы можем добавлять, удалять и проверять наличие класса у того или иного элемента средствами нативного JavaScript-кода.

Element.classList

Свойство classList возвращает список классов элемента. Так же в этом свойстве присутствует 4 метода:

  • add – добавление класса;
  • remove – удаление класса;
  • toggle – переключение класса;
  • contains – проверка наличия класса у элемента.
// добавление элементу класс "foo" el.classList.add("foo"); // удаление класса "bar" el.classList.remove("bar"); // переключение класса "foo" el.classList.toggle("foo"); // возвращает "true" если у класса есть класс "foo", в противном случае "false" console.log( el.classList.contains("foo") ); // добавление нескольких классов el.classList.add( "foo", "bar" );

Поддержка

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

Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: http://callmenick.com/2014/10/23/add-remove-classes-with-javascript-property-classlist/
Перевел: Станислав Протасевич
Урок создан: 23 Октября 2014
Просмотров: 179500
Правила перепечатки

5 последних уроков рубрики «jQuery»

Анимация набора текста на jQuery

Сегодня мы бы хотели вам рассказать о библиотеке TypeIt — бесплатном jQuery плагине. С её помощью можно имитировать набор текста. Если всё настроить правильно, то можно добиться очень реалистичного эффекта.

Временная шкала на jQuery

jQuery плагин для создания временной шкалы.

Заметка: Перезагрузка и редирект на JavaScript

Быстрая заметка, где вы сможете найти парочку JS сниппетов для перезагрузки и перенаправления пользователей через JavaScript.

Прототипы — JS: Введение в ООП

В этом уроке дается небольшое введение в тему прототипов. Полностью раскрыть её одним уроком невозможно. Не хватит даже целого курса. Прототипы познаются только через практику, перемешанную с теоретической подготовкой. Поэтому не переживайте, если не всё поймёте с первого раза, это нормально.

Прототипы — это механизм, который оказывает основное влияние на то, как работают объекты в JavaScript. Сами они напрямую в коде используются редко (и обычно только в библиотеках), но их знание важно для понимания поведения кода и отладки. Особенно при работе с классами, которые мы изучим дальше по курсу. В этом уроке мы затронем только самые основы. Глубоко разобраться с прототипами поможет наш курс, указанный в дополнительных материалах.

В JavaScript с каждым объектом связан прототип. Прототип – это обычный объект, хранящийся в специальном служебном поле [[prototype]] (к этому полю невозможно обратиться напрямую). Его можно извлечь так:

const date = new Date(); // Эта функция извлекает прототип объекта из самого объекта const proto = Object.getPrototypeOf(date); // Date <> // В прототипе хранится не конструктор // Что там хранится – узнаем дальше proto === Date; // false const numbers = [1, 2]; Object.getPrototypeOf(numbers); // [] – отображение отличается, но это массив // Прототипы есть и у конструкторов, которые мы определяем сами function Company(name)  this.name = name; > const company = new Company(); Object.getPrototypeOf(company); // Company <> 

Для чего нужны прототипы

Представим, что мы обращаемся к свойству объекта, и при этом никакого свойства в этом объекте нет. В таком случае мы получим значение undefined . Обычно это так и работает, но есть одна важная особенность.

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

В реальности процесс еще сложнее. Если свойство не найдено в прототипе, то JavaScript смотрит прототип прототипа и так далее. Так он проходит до конца цепочки прототипов, то есть до последнего прототипа — это всегда null . На базе этого механизма реализуется наследование. Эта тема выходит за рамки текущего урока.

Прототипы есть даже у обычных JavaScript-объектов:

Object.getPrototypeOf(<>); // <> — это и есть Object 

Именно по этой причине даже пустые объекты содержат свойства и методы:

const obj = <>; // То же самое можно сделать так: const obj = new Object(); // Это функция-конструктор, из которой был получен текущий объект, в нашем случае — Object obj.constructor; // [Function: Object] // У obj нет своего собственного свойства constructor, оно пришло из прототипа Object.hasOwn(obj, 'constructor'); // false Object.hasOwn(obj, 'name'); // false obj.name = 'hexlet'; // Имя есть в самом объекте, потому что мы его только что добавили Object.hasOwn(obj, 'name'); // true 

Доступ к прототипу можно получить не только из объектов, но и из свойства prototype конструктора, который эти объекты создаёт:

function Company(name)  this.name = name; > // Одно и то же, полученное разными способами // Company.prototype === Object.getPrototypeOf(new Company()) 

Теперь мы можем ответить на вопрос, откуда берется прототип. Прототип – это объект, находящийся в свойстве prototype функции-конструктора, а не сам конструктор. Проверить работу прототипов достаточно легко, изменив их:

// Добавляем свойство getName (делаем его методом) Company.prototype.getName = function getName()  // this по-прежнему зависит от контекста, в котором вызывается return this.name; > const company = new Company('Hexlet'); // Свойство доступно! console.log(company.getName()); // => Hexlet 

При этом никто не мешает заменить значение свойства getName в конкретном объекте. Это никаким образом не отразится на других объектах, так как они извлекают getName из прототипа:

const company1 = new Company('Hexlet'); const company2 = new Company('Google'); company2.getName = function getName()  return 'Alphabet'; > // Этот вызов возьмет свойство из самого объекта company2.getName(); // Alphabet // Этот вызов возьмет значение свойства из прототипа company1.getName(); // Hexlet 

Создание свойств через прототип – и есть правильный способ создания своих абстракций в JavaScript. Любая новая абстракция, которая нам нужна в коде, должна выглядеть как конструктор и прототип, наполненный нужными свойствами.

Что даёт этот механизм?

Самое простое – расширение ядра языка и библиотек без прямого доступа к исходному коду. Прототипы – невероятно гибкий механизм, который позволяет менять всё что угодно из любого места программы в рантайме, то есть во время работы. Например, мы можем добавить или заменить любые методы в любых объектах самого языка:

const numbers1 = [1, 3]; // Как только выполнится этот код, все массивы, // включая уже созданные, обзаведутся методом last Array.prototype.last = function last()  // Такое обращение сработает, ведь this — это ссылка на сам объект, // который в нашем случае является массивом return this[this.length - 1]; > numbers1.last(); // 3 const numbers2 = [10, 0, -2]; numbers2.last(); // -2 // Пример замены // Это запрещенный прием, никогда так не делайте в реальном коде Array.prototype.map = function map()  return 'Ehu!'; > numbers1.map(); // "Ehu!" 

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

// Очень злой код, который ломает работу метода push Array.prototype.push = function push(value)  return this.unshift(value); > const numbers = [1, 2]; numbers.push(3); console.log(numbers); // => [3, 1, 2] . 

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов

Наши выпускники работают в компаниях:

Как добавить класс чтобы прежние классы остались js

Все чаще слышу и читаю про то, что в ближайшем будущем , web выйдет на новый уровень. Использование web-components станет неким стандартом , собственно , на что рассчитывают в W3C. И встает вопрос, что думают по этому поводу ребята из Яндекс ? По сути , он будет уметь и делать все то , что делает сейчас БЭМ , тот же React. Все будет работать только нативными средствами. Что дает не малый прирост в скорости. Как будет жить и существовать БЭМ , после того , как это все станет более имение реальностью?

Комментарии: 7
9 years ago

Мастер-класс по БЭМ CSS

Привет! Мне нужно будет провести мастер-класс по БЭМ на час. Не презентацию, а именно мастер-класс, когда люди сидят со своими компьютерами и вместе что-то делают. Важно сосредоточиться именно на CSS и немного на декомпозиции и сборке. JavaScript и шаблоны пока не нужны. Кто-нибудь делал подобное? Может быть в ШРИ такое было? Поделитесь, пожалуйста, черновиками, ссылками на репозитории или (ну, вдруг мне повезет) видео. Спасибо!

Комментарии: 8
9 years ago

Stylus и глобальные перемененные

Добрый день 🙂 Или кому-то ещё утро 😉

Как использовать глобальные переменные less, sass, stylus и т.д. при написании кода?

У меня есть соображение, что нужно объявить блок с ними и потом его просто подключить в проекте где-то вначале, но есть сомнения.

Как это сделать правильней?

Комментарии: 4
9 years ago

Добавление новых блоков.

Здравствуйте. Начал знакомство с БЭМ-инструментами, до этого использовал только методологию наименования классов. На данный момент хочу использовать бэм-инструменты для верстки однотипных шаблонов. Но у меня возникли проблемы с добавлением новых своих сущностей (а не блоков яндекса из bem-core и bem-components) в common.blocks, внятной документации не нашел. Использую enb-bem + bwmsjon + bemhtml. Также хотелось бы узнать, как отключить минификацию файлов html при сборке. Сейчас весь html склеивается в одну строку, а хотелось бы получать файл, пригодный для дальнейшей интеграции на cms.

Комментарии: 4
9 years ago

Вынесение «контекстно-зависимых» стилей в отдельный блок

Начал изучать БЭМ CSS. Как я понимаю, блоки должны быть максимально независимы от контекста, в котором они используются., поэтому я при написании блоков выделяю «контекстно-зависимые» стили (margin/padding, переопределения стилей Bootstrap и т.д.) в отдельный блок и навешиваю его вместе с основным блоком на один элемент:

.corp-offer-builder-ctx__nav < margin: 0; >.corp-offer-builder-ctx__page-num < padding: 0 10px; >.corp-offer-builder-ctx__button_save .dropdown-menu

Как я себе представляю, это помогает отделить блок от контекста и использовать его в других местах. Насколько адекватен такой подход и есть ли какие-то другие, возможно, более правильные подходы?

Комментарии: 1
9 years ago

Подскажите как правильно связать 2 блока

Подскажите как правильно связать несколько блоков например для реализации табов. Например для такой структуры

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

Комментарии: 21
9 years ago

Layout

Привет ! Подскажите пожалуйста, в методологии есть возможность создать layout как в Jade , подключать все скрипты в теге head и для других страниц.

Комментарии: 25
9 years ago

Модульная сборка, терминология

Есть такая страничка, заявляющая, что она раскрывает смысл терминов Блок, Элемент, Модификатор. https://ru.bem.info/method/definitions/ Но, во-первых, нет конкретного определения, и, во-вторых, ничего не говорится про технологии, реализации, и другие важные при разработке сборки части.

Надо бы определиться с терминологией и определениями, чтобы можно было двигаться дальше. Подсобите, пожалуйста.

  • БЭМ — акроним Блок-Элемент-Модификатор;
  • Блок — ключевая самодостаточная сущность, описываемая набором реализаций (обычно, набор файлов и папок в папке блока);
  • Элемент — вспомогательная сущность, составная часть блока, описываемая аналогично блоку, которая имеет ровно один родительский блок, и не может использовать вне его контекста;
  • БЭМ-сущность — это определение содержания страницы или сущность в БЭМ-предметной области: блок ИЛИ элемент со всеми его состояниями (модификаторами);
  • БЭМ-предметная область — предметная область, описывающая все возможные варианты БЭМ-сущностей, их свойств, и отношений между ними;
  • Методология БЭМ — это набор паттернов и способ описывать действительность при помощи кода и размышлять о БЭМ-сущностях вне зависимости от того, на каком языке программирования реализуется проект;
  • Модификатор — состояние БЭМ-сущности, описываемое реализациями аналогично БЭМ-сущностям, может иметь строго одно строковое или булевое значение, не может как использоваться отдельно от БЭМ-сущности, так и считаться отедльной БЭМ-сущностью, поскольку является его состоянием (часть целого не может быть целым, если целое состоит не только из этой части);
  • Уровень — набор реализаций БЭМ-сущностей (обычно, набор папок с блоками и их внутренней структурой с элементами и модификаторами);
  • Библиотека — набор уровней;
  • Реализация (в технологии) — функциональная часть БЭМ-сущности, описанная в рамках конкретной технологии файлом или папкой с набором файлов;
  • Технология (tech, technology) — набор процессов для преобразования исходных файлов в целевой продукт (материалов в изделие, результат работы процессов, см. wiki: Технология);
  • БЭМ-технология — технология, применимая к БЭМ-сущностям;
  • Технология сборки — процесс преобразования реализаций блоков, используемый инструментами для сборки (обычно, модуль или набор , stateful?);
  • Технологии борщика — технология, реализуемая js-файлами, используемая инструментом borschik;
  • Цель (сборка) — результат работы технологии сборки;
  • Зависимость — способ включения в сборку сущности или её состояний других сущностей или состояний;
  • Зависимость по БЭМ-технологии — зависимость, используемая в случае сборки определенной БЭМ-технология (верно?);
  • Бандл (сборка) — это набор реализаций сущностей, описанный некоторой специальной реализацией (точкой входа для сборщика с набором сущностей, обычно, в виде реализации технологии bemdecl.js или bemjson.js), и некоторое кол-во собранных целей на выходе, а также способный включать в себя дополнительные уровни;
  • Merged-бандл — частный случай бандла, включающий в себя сборку всех используемых наборов сущностей и их состояний со всех бандлов;
  • Dist-бандл — частный случай бандла, включающий в себя сборку всех доступных БЭМ-сущностей, обычно используется для сборки библиотек;
  • JS-бандл — целевой файл бандла с реализацией JS;
  • CSS-бандл — целевой файл бандла с реализацией CSS (?, противоречит JS-бандлу, где в сборку включаются еще и шаблоны, и стили);
  • JS-бандл (путаница, может mixed-бандл?) — цель специальной технологии, результат которой содержит в себе CSS, JS и шаблоны, поставляемая в виде одного файла технологии JS.

Off-topic. А еще вот такое хочу:

 // возвращаем первое удачно разрешенное target('bemdecl', oneOf( // либо грузим файл `//.bemdecl.js` fs.provide('bemdecl.js'), // либо пытаемся загрузить bemjson.js и собрать динамически из bemjson.js bemjsonToBemdecl(fs.provide('bemjson.js')) )); 

Комментарии: 20
9 years ago

Вспомогательные классы в БЭМ

«Я правильно понимаю, что по БЭМу я не могу добавлять общие вспомогательные классы ко всем блокам? Например, есть класс center , который центрирует содержимое по обеим осям. Хочется иметь его в шапке и еще в паре блоков.»

С одной стороны, БЭМ утверждает: «Не может быть классов вне блоков». С другой стороны, в БЭМ есть понятие миксов — нескольких блоков на одном DOM-узле.

Этот случай — наш.

Предлагаю рассмотреть класс center как универсальный блок, который можно подмешивать к любым другим блокам, чтобы центрировать их содержимое.

Важно помнить, что миксы можно использовать не только в CSS, но и в JavaScript.

Подробнее об этом можно узнать из доклада «Миксы во вселенной БЭМ».

Комментарии: 14
9 years ago

Шрифты в bem

Приветствую, подскажите пожалуйста, куда нужно класть шрифты?

Комментарии: 5
9 years ago

BEM и WAI ARIA

Можем ли мы использовать вместо BEM модификаторов WAI ARIA атрибуты, в случаях, когда нужно отобразить состояние и прочие кейсы на доступность?

Можем ли мы опираться только на ARIA-атрибуты, если нам нужно написать какую-то логику на задисейбленный элемент?

if (this.attr('aria-disabled')) <> 

Коллега аргументирует, что раз мы используем уже методологию, то зачем нам распыляться и использовать атрибуты, если есть модификаторы:

if (this.elem('some-element').mod('disabled')) <> 

Комментарии: 2
9 years ago

Зачем БЭМ на маленьком проекте?

Говорят, что с БЭМом удобнее и быстрее разрабатывать. Но у нас в проекте всего 10 страниц, когда что-то надо поправить, наш фронтендер всё правит быстро, зачем нам БЭМ? Если кто-то с маленьких проектов может привести пример, как он/она выиграл от БЭМа, будет очень круто.

Комментарии: 8
9 years ago

БЭМ — это не только про CSS

Телезритель из Воронежа Ваня @voischev задает вопрос на давнюю тему «БЭМ — это не только про CSS», а мы с радостью и отвечаем:

Да, действительно, БЭМ — это не только про CSS.

БЭМ — это про компонентный подход к разработке в целом.

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

Например, если перед нами логотип, то скорее всего он будет реализован в двух технологиях: шаблоне и стилях.

.logo

И шаблон и стили будет удобно положить в одну папку. Так при желании переиспользовать блок мы легко найдем все его части и спокойно перенесем на новое место в отличие от ситуации, когда CSS — это одна «портянка» в папке css/ , а JavaScript — в js/ , и чтобы перенести какую-то часть куда-то, нужно еще долго копаться в контексте.

Разумеется, встречаются блоки, которым требуется еще и JS для работы. Их реализацию по той же логике, что и выше, мы также кладем в папку с блоком. Выглядеть это может, например, так:

$('.logo').on('click', doSomething); 

Конечно, бывают ситуации, когда блок состоит только из CSS (например, clearfix или только JS, как, скажем, блок для работы с куками.

Логика при этом не меняется: это по-прежнему блоки, которые по-прежнему имеют свою папку в файловой системе и аналогично другим блокам попадают в сборку.

Следуя все той же логике, мы реализуем разные технологии блока. Ими могут быть не только традиционные CSS и JS, но и картинки, тесты, документация, примеры использования, исходники и так далее. Со временем блок обрастает нужным «мясом», а мы все также легко можем его декомпозировать и масштабировать без урона для проекта.

В качестве примера можно взглянуть на блок button из библиотеки bem-components.

Когда-то давно БЭМ со своим «компонентным» подходом (тогда он еще так не назывался) нес в массы новые, не всегда понятые идеи. Сегодня ситуация изменилась. Этот же компонентный подход уже не нов и реализован не в одном, а многих продуктах, например, в Polymer или даже в стандарте Web Components.

Рассмотрим на примерах.

«Вы говорите, что блоки должны быть независимыми, но на уровне JavaScript они обязаны общаться друг с другом. Как?»

Давайте рассмотрим пример: у нас есть форма, перед отправкой которой необходимо проверить, что введено корректное значение, а в случае ошибки показать попап с предупреждением.

.popup < display: none; >.popup_visible
Как это могло быть реализовано в стиле old school?
$('.button').on('click', function(e) < if (!/\S+@\S+\.\S+/.test($('.input').val())) < $('.popup').addClass('popup_visible'); return false; >>); 

Всего 6 простых строчек, все работает. Однако, так делать плохо. Почему?

Эти 6 строк кода — отличный пример того, что называют сильной связанностью кода: кнопка «знает» про поле ввода и попап, кроме того, она явно подозревает, что находится внутри формы.

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

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

Что можно улучшить?
$('.form').on('submit', function(e) < if (/\S+@\S+\.\S+/.test($('.input', this).val())) return true; e.preventDefault(); $('.popup', this).addClass('popup_visible'); >); 

Мы переписали форму так, чтобы за все, что происходит с ней, отвечала она сама. Теперь компоненты внутри ничего не знают о существовании друг друга. А мы можем смело взять кнопку и перенести ее на другой проект, ведь она стала независимой: теперь за ней не потянется знание о какой-то форме, поле ввода и попапе.

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

Есть ли что-то еще, что можно улучшить?

Да. Если мы добавим еще одно поле, придется рефакторить код. Кроме того, чтобы гарантировать перекрытие попапом любых других элементов на странице, нам необходимо положить его в самом конце DOM-дерева, перед закрывающим тегом .

Продолжаем улучшать

Вынесем попап из формы и добавим еще одно поле. Сами поля смиксуем с элементами формы.

Микс — это объединение нескольких блоков на одном DOM-узле.

   
Пожалуйста, введите корректный email

Теперь наш код выглядит так:

$('.form').on('submit', function(e) < if (/\S+@\S+\.\S+/.test($('.form__email', this).val())) return true; e.preventDefault(); $('.form__hint').addClass('popup_visible'); >); 

Мы исправили предыдущие проблемы, но появилась новая: если на странице окажется несколько форм, как каждая из них найдет свой попап?

Решение, да не одно

В качестве одного из решений мы можем реализовать механизм, который позволит выражать один блок на нескольких DOM-нодах. Схематично он может выглядеть так:

   
Пожалуйста, введите корректный email

Мы добавили форме data-атрибут с идентификатором и помимо элемента примиксовали к попапу саму форму с таким же идентификатором. Теперь мы можем в коде сказать, что нам нужен элемент hint именно этого блока form , а не какого-то другого:

$('.form').on('submit', function(e) < if (/\S+@\S+\.\S+/.test($('.form__email', this).val())) return true; e.preventDefault(); $('.form__hint').filter('.form[data-id=' + $(this).data('id') + ']').addClass('popup_visible'); >); 

Следующее решение поможет нам сохранить независимость блоков, но избавиться от необходимости вносить изменения в DOM. Воспользуемся паттерном проектирования Посредник в очень упрощенном виде.

С ним наши компоненты будут знать о существовании посредника, но не будут ничего знать друг о друге. Вся коммуникация будет происходить на основе сообщений, которые компоненты будут публиковать и слушать на посреднике.

Чтобы максимально упростить пример, сделаем таким посредником body . Он всегда присутствует в коде и определенно знает о всех компонентах, которые находятся внутри, + может обеспечить обмен сообщениями.

   var page = $('.page'); page.on('error', function(e, data) < $('.popup') .text(data) .addClass('popup_visible'); >); $('.form').on('submit', function(e) < if (/\S+@\S+\.\S+/.test($('.form__email', this).val())) return true; e.preventDefault(); page.trigger('error', 'Ошибка валидации'); >); 

Теперь в случае ошибки валидации форма сообщит об этом посреднику — page . Все компоненты, которые должны реагировать на это событие, могут «подписаться» на него через page.on() .

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

Подытожим: методология БЭМ — не только про CSS. Она затрагивает все технологии реализации блока, включая JS, и и помогает писать JavaScript-код, который сохранит независимость ваших блоков, упростит рефакторинг и продлит жизнь проекту.

«Зачем нужен i-bem.js , если можно писать JS для независимых блоков на привычном jQuery ?»

Такой вариант возможен. И более того, i-bem.js написан с использованием jQuery .

Зачем же нам понадобился отдельный блок?

Решая одни и те же задачи на JavaScript в терминах блоков, элементов и модификаторов, мы регулярно делали одни и те же действия. И чтобы автоматизировать процесс и избавиться от копипаста, а также предоставить удобные хелперы пользователям, мы написали i-bem.js.

Если у вас остались вопросы, смело задавайте их в комментариях. Мы обязательно ответим!

Комментарии: 22
9 years ago

Вкладывание элементов в элементы и другие тонкости

По мотивам обсуждения в твиттере с подачи @delaz, решили написать пост и собрать еще вопросов и тем для разъяснения, которые в будущем планируем добавить в раздел про методологию.

Что у нас получилось?

  1. БЭМ — это не про префиксы.
  2. БЭМ — это не про длинные названия классов.
  3. Нельзя использовать элементы элементов в нейминге.
  4. Миксы.
  5. БЭМ не запрещает каскад (но и не приветствует).
  6. Как понять, когда делать блок, а когда — элемент.

Пойдем по порядку, а вы задавайте вопросы или дополняйте список в комментариях. Ответы будем выносить в пост.

«БЭМ — это длинные имена классов. b-button — это длинно!»

Отвечаем: БЭМ не навязывает префиксы. Чтобы писать хорошо поддерживаемый и реиспользуемый код, префиксы совершенно не нужны. Исторически они появились в переходный период для того, чтобы отличать новый код, написаный по БЭМ, от старого. Со временем мы от них отказались. Если посмотреть в код, можно увидеть, что префиксов там нет.

«А как же префикс js- или i- для блоков без визуального представления?»

Когда-то можно было сверстать сайт практически без JS-кода. Сейчас большая часть блоков имеет JS-представление. Глядя на текущую ситуацию мы поняли, что нет нужды как-то отличать технологии реализации блока на уровне нейминга. Посмотрите, к примеру, на Web Components. Объективно необходимости в префиксах нет, но каждый волен выбирать, что ему, проекту или команде удобнее и/или привычнее.

«Префиксы — ладно. А просто длинные названия блоков?»

В этом и похожих случаях вы можете использовать классы типа btn вместо button . Это никак не помешает вам разрабатывать по БЭМ. Все как с названием переменных в JS: context , ctx или c . Но помните, вам, вашим коллегам и тем, кто будет разрабатывать и поддерживать проект после вас это предстоит читать, понимать и с этим работать 😉

Остается вопрос про неймспейсы — мы пишем имя блока перед именем элементов ( button__icon ) и модификаторов ( button_active ).

Если декомпозировать «проблему», можно выделить 2 потенциальных минуса:

  • Результирующий код, который приходится гонять по сети, весит больше. Тут на помощь приходит gzip , который отлично жмет повторяющиеся последовательности и сводит минус на нет.
  • Приходится больше кнопок нажимать на клавиатуре. Здесь помогают автокомплит в редакторе и инструментарий, который автоматически добавляет префиксы (CSS-препроцессоры и шаблонизаторы). Когда вы видите эти два минуса и больше ничего кроме них, мы предлагаем подумать и выбрать, что важнее — время, необходимое на нажатие клавиш, или время, затраченное на обдумывание архитектуры. Во втором случае БЭМ как раз очень сильно помогает. А первое легко автоматизировать не в урон проекту.

И тогда, благодаря неймспейсам, будет решено следующее:

  1. Исчезнет опасность случайно «задеть» внутреннее устройство блока. Мы получим аналог скоупа в JS, но для CSS. Для этого в Web Components придумали Shadow DOM, но в действительности простого добавления имени блока достаточно, чтобы получить тот же результат без лишних телодвижений.
  2. С первого взгляда на любой класс, хоть в CSS, хоть в HTML, хоть в любой другой технологии реализации блока, мы тут же поймем, к какому блоку он относится и какую задачу решает. Сравните: active (на что повлияет этот класс?) VS. input_active или item VS. nav__item .

«Что вы скажете на nav__item__link ? Все равно длинно»

Да. И к тому же не по БЭМу 🙂

Неймспейсом служит только имя блока. А отражать вложенность в именах элементов не нужно. Это не только длинно, но еще и не позволит при повторном использовании блока в другой ситуации (или просто при рефакторинге) легко вынуть один элемент из другого. Плоская структура касается не только нейминга, но и расположения кода на файловой системе:

nav/ __item/ nav__item.css __link/ nav__link.css 

Для выражения вложенности вполне достаточно DOM-дерева:

«Логично. Как отличить — делать блок или элемент? Например, nav__link — это элемент меню или самостоятельный блок link , который будет использоваться и в других местах на странице?»

Тут нам на помощь приходят миксы — возможность смешать на одном DOM-узле несколько блоков (или элементов/модификаторов) одновременно.

Предыдущий пример вполне может выглядеть так:

При этом все общее, что есть у всех ссылок на проекте, будет описано в блоке link , а особенности, присущие только ссылке внутри nav — для nav__link .

«Почему нельзя стилизовать ссылки каскадом через .nav__item .link ?»

  1. Это несемантично. А если там в будущем окажется не ссылка вовсе?
  2. Во-вторых, это влечет за собой дополнительные сложности, ведь каскад затронет и вложенные сущности. Например, если в будущем вы захотите усложнить архитектуру или добавить выпадающее меню.
  3. Наконец, структура может поменяться и nav__item совсем исчезнуть.

«Получается, что в каскадных таблицах стилей нельзя использовать каскад?»

Можно. Но нужно понимать, какие последствия это влечет. Например, каскад уместен, чтобы менять элементы в зависимости от состояния блока ( .nav_hover .nav__link < text-decoration: underline; >) или, скажем, темы ( .nav_theme_islands .nav__item < line-height: 1.5; >).

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

«Как в принципе отличать, где блок, а где элемент?»

Если хочется переиспользовать кусок кода вне контекста родителя — это точно блок. Если кусок кода не имеет смысла без родителя — это скорее всего элемент. Аналогией служит Shadow DOM в Web Components.

Исключением может быть ситуация, когда у такого элемента оказывается слишком богатый внутренний мир и возникает желание сделать его собственные элементы. Тогда это можно представить как служебный «приватный» блок.

Что скажете? Наши ответы помогут вам разобраться в ваших ситуациях или же нам стоит подумать над чем-то еще? Будет очень здорово получить от вас вопросы или же примеры, которые мы сможем объяснить. А потом вынести всю эту полезную информацию в раздел сайта.

Очень ждем ваших комментариев!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *