Работа с модификаторами
Поведение блока описывается с помощью состояний. Модификаторы содержат информацию о состояниях блока. Перевод блока в другое состояние производится при помощи установки/снятия модификатора. Изменение модификатора создает событие, которое можно использовать для работы с блоком.
Например, чтобы отметить чекбокс, блоку нужно установить модификатор в значение .
Для корректной работы JavaScript в БЭМ-проекте все манипуляции с модификаторами должны производиться при помощи методов-хелперов. Изменять значение модификаторов следует с помощью спец методов, а не менять напрямую CSS-класс на соответствующем DOM-узле.
Реакция на изменение модификаторов
В БЭМ реакция на установку/снятие модификатора описывается декларативно: изменение состояния автоматически вызывает код, который задекларирован для этого состояния. Если появляется модификатор (добавляется новый класс к DOM-узлу), то вся функциональность, свойственная этому модификатору, также применяется. Если модификатор исчезает, функциональность отключается.
Переход блока из одного состояния в другое часто сопровождается изменениями его внешнего вида. Так как добавление модификатора блоку изменяет его класс на DOM-узле, а стили написаны опираясь только на классы, изменение класса автоматически приводит к изменению внешнего вида блока.
Чтобы динамически изменять состояния блоков и элементов, используются специальные методы для установки и снятия модификаторов.
Один из способов решения этой задачи — жестко прописать все условия в коде и постоянно выполнять проверку. Такой подход неудобен, так как любое изменение потребует изменений в коде вручную.
Другой способ — использовать методологию БЭМ и задекларировать поведение блока таким образом, чтобы получить возможность перекрывать каждый модификатор отдельно на новом уровне переопределения. В декларации можно указать, как блок или элемент должен отреагировать на изменение модификатора.
block('button').onSetMod({ focused: { true: this.onFocus, false: this.onBlur } });
Такой подход дает возможность:
-
Определять каждому состоянию свой внешний вид, добавив стили модификатору.
-
Изменять или полностью перекрывать поведение блока с помощью .
Разделение кода на части
В БЭМ-методологии поведение каждого блока описывается независимо. Независимость блоков в JavaScript позволяет повторно использовать блоки и реализуется за счет использования принципов:
Логика работы каждого блока, его опциональных элементов и модификаторов описывается в отдельных файлах. JavaScript-файлы хранятся в соответствии с правилами организации файловой структуры БЭМ-проекта.
Рассмотрим на примере логотипа (блок ), реализованного в технологии CSS.
Блок в файловой структуре проекта:
logo/ # Директория блока logo logo.css # Реализация блока logo в технологии CSS
Добавим блоку новую функциональность: нажатие на логотип будет вызывать какое-то действие.
JavaScript-реализация блока :
document.querySelector('.logo').addEventListener('click', doSomething, false);
Файл в файловой структуре блока :
logo/ # Директория блока logo logo.css # Реализация блока logo в технологии CSS logo.js # Реализация блока logo в технологии JavaScript
Реализация поведения блока, как и его внешнего вида, независима и отделена от реализации других блоков не только логически, но и физически — вынесена в отдельный файл.
Принцип инкапсуляции
В БЭМ внутренняя реализация блока скрыта. Блок предоставляет API для . Таким образом достигается независимость блока, возможность его повторного использования.
Элементы всегда являются внутренней реализацией блока, поэтому возможно только через API самого блока.
Принцип декларативности
Логика работы блока описывается декларативно: как набор действий и условий, при которых эти действия необходимо выполнять. Это позволяет разделять функциональность блока на отдельные части и использовать .
Принцип наследования
Декларативное описание поведения блоков позволяет использовать методы базового блока внутри производного, наследовать их. Новый блок может получать все свойства и методы базового.
Также можно создавать цепочки наследования — блок наследуется от другого, который, в свою очередь, наследуется от третьего и т.д.
Селекторы
В БЭМ не используют селекторы тегов и идентификаторов. Стили блоков и элементов описываются через селекторы классов.
Селекторы классов
Позволяют указать конкретный HTML-элемент страницы, независимо от тега. Обращение к селектору класса происходит через атрибут , который должен иметь каждый HTML-элемент.
Значением атрибута может быть разделенный пробелами список слов. Это позволяет использовать разные на одном DOM-узле.
Пример
HTML-реализация:
header class="header"> button class="header__button button button_theme_islands">...button> header>
Совмещение тега и класса в селекторе
Методология БЭМ не рекомендует совмещать теги и классы в селекторе. Объединение тега и класса (например, ) повышает специфичность CSS-правил, что усложняет задачу их переопределения. Это приводит к войнам значимости, при которых таблицы стилей загружаются излишне сложными селекторами.
Пример
HTML-реализация:
button class="button">...button>
CSS-правила заданы в селекторе .
Допустим, блоку добавили модификатор со значением :
button class="button button_active">...button>
Селектор не переопределит свойства блока, записанные как , так как специфичность выше чем у . Для успешного переопределения селектор модификатора блока также должен быть скомбинирован с тегом .
В результате развития проекта могут, например, появиться блоки с селекторами , и . В таком случае все модификаторы блока и вложенные в него элементы потребуют четыре разные декларации для каждого случая.
Нужно стараться использовать простые селекторы классов:
.button {} .button_active {}
Вложенные селекторы
Методология БЭМ допускает использование вложенных селекторов, но рекомендует свести их применение к минимуму. Вложенные селекторы увеличивают связность кода и делают его повторное использование невозможным.
При использовании вложенных селекторов важно соблюдать принцип инкапсуляции: правила одного блока не должны влиять на внутренний мир другого блока. Элементы — это внутренняя реализация блока
Таким образом, блок влияет только на свои элементы и не может воздействовать на элементы другого блока.
Вложенность уместна, если необходимо изменить стили элементов в зависимости от модификатора (например, состояния блока или заданной темы):
Пример
CSS-реализация:
.button_hovered .button__text { text-decoration: underline; } .button_theme_islands .button__text { line-height: 1.5; }
Комбинированные селекторы
Методология БЭМ не рекомендует использовать комбинированные селекторы. Комбинированные селекторы (например, ) имеют более высокую специфичность, чем одиночные селекторы, что усложняет задачу их переопределения.
Пример
HTML-реализация:
button class="button button_theme_islands">...button>
CSS-правила заданы в селекторе .
Допустим, блоку добавили модификатор с значением :
button class="button button_theme_islands button_active">...button>
Селектор не переопределит свойства блока, записанные как , так как специфичность выше, чем у . Для успешного переопределения селектор модификатора блока также должен быть скомбинирован с селектором и объявлен ниже , так как специфичность обоих селекторов одинакова:
CSS-реализация:
.button.button_theme_islands {} .button.button_active {}
Нужно стараться использовать простые селекторы классов:
.button_theme_islands {} .button_active {}
Именование
Имя селектора должно полно и точно описывать представляемую им БЭМ-сущность.
В качестве примера рассмотрим следующие четыре строки CSS-кода:
.button {} .button__icon {} .button__text {} .button_theme_islands {}
С определенной долей вероятности можно предположить, что мы имеем дело с одним блоком и его HTML-реализация выглядит следующим образом:
button class="button button_theme_islands"> span class="button__icon">span> span class="button__text">...span> button>
Сложнее сделать подобное предположение с такой группой селекторов:
.button {} .icon {} .text {} .theme_islands {}
Имена , , не так информативны.
Общие правила именования блоков, элементов и модификаторов позволяют:
-
сделать имена CSS-селекторов максимально информативными и понятными;
-
решить проблему коллизии имен;
-
независимо описывать стили блоков и их опциональных элементов.
Пример
HTML-реализация:
div class="logo logo_theme_islands"> img src="URL" alt="logo" class="logo__img"> div> div class="user user_theme_islands"> img src="URL" alt="user-logo" class="user__img"> ... div>
Именование CSS-классов:
.logo {} .logo__img {} .logo_theme_islands {} .user {} .user__img {} .user_theme_islands {}
Служба
Корабль после вступления в строй вошёл в состав 175-й БЭМ Тихоокеанского флота ВМФ СССР. С 17 по 21 ноября совместно с крейсером «Адмирал Сенявин» и эсминцем «Выдержанным» под флагом вице-адмирала В. А. Фокина посетил Джакарту (Индонезия), по итогам года признан лучшим кораблём Тихоокеанского флота.
С 24 августа по 16 июля 1969 года эсминец прошёл модернизацию по проекту 56А на «Дальзаводе» (79-я бригада строящихся и ремонтируемых судов, Владивосток), после её завершения включён в состав 9-й ди ПЛК, но 26 декабря переведён в состав 175-й БРК; с по 26 апреля 1970 года корабль принимал участие в учениях «Океан», пройдя за время учений 3825 морских миль.
В период с 17 июля 1970 по 8 февраля 1971 года «Возбуждённый» участвовал в несении боевой службы в Индийском океане; за время несения службы эсминец прошёл 23 140 морских миль, посетил порты Бербера (четыре раза) и Аден, обеспечивал подъём космического аппарата «Зонд-8». 16 июня 1971 года включён в состав 173-й БЭМ Камчатской флотилии, в ноябре совершил поход в Индийский океан. В январе 1972 года корабль вышел на новую боевую службу в Индийский океан совместно с БПК «Строгий» (под флагом контр-адмирала В. С. Круглякова), с 11 по 16 апреля КУГ нанесла визит в Ум-Каср (Ирак), с 10 по 15 июля 1972 года — в Порт-Луи (Маврикий).
С 7 октября по 2 марта «Возбуждённый» находился в ремонте на «Дальзаводе». В 1979 году вышел на боевую службу в Индийском океане: в составе КУГ (совместно с ракетным крейсером «Адмирал Фокин» и БПК «Строгий») с 5 по 9 ноября нанёс визит в Хайфон (Вьетнам), с боевой службы возвращался своим ходом.
В 1981 году эскадренный миноносец выполнял задачи боевой службы в Индийском океане, с 26 по 31 мая 1981 года нанёс визит в Аден (Южный Йемен). 8 марта 1982 года приказом министра обороны СССР корабль был отправлен на консервацию и поставлен на прикол. 1984-1988м на прикол не стоял в Петропавловск-Камчатский, нес боевое дежурство.В 1987 введен в состав ВМФ и два года нес боевую службу и участвовал в учениях Камчатской флотилии[источник не указан 2757 дней]; приказом министра обороны СССР от 25 апреля 1989 года исключён из списков кораблей ВМФ СССР и 1 октября расформирован. В 1990 году затоплен у берегов Камчатки после проведения по нему артиллерийских стрельб. с 1980 по 1983 корабль 3 раза заходил в йемен был во вьетнаме кам-рань и в эфиопии о-ва дахлак . в1982 его не отправляли в консервацию.
Основы БЭМ
Методология БЭМ — это набор универсальных правил, которые можно применять независимо от используемых технологий, будь то CSS, Sass, HTML, JavaScript или React.
БЭМ помогает решить следующие задачи:
- повторно использовать верстку
- безболезненно менять верстку местами в одном проекте
- переносить готовую верстку из проекта в проект
- создавать стабильный, предсказуемый и понятный код
- сократить время на отладку проекта
В БЭМ-проекте любой интерфейс делится на , которые могут содержать . Блоки — это независимые компоненты страницы. Элементы не существуют вне блока. Каждый элемент может принадлежать только одному блоку.
Именно блокам и элементам посвящены первые две буквы в аббревиатуре БЭМ.
Имя блока всегда уникально. Оно задает пространство имен для элементов и устанавливает видимую связь между всеми составляющими блока. Длинные, но понятные имена блоков и элементов позволяют определить связь между компонентами и не потерять составные части этих компонентов при переносе верстки.
Чтобы показать всю силу БЭМ-нейминга, рассмотрим пример с формой. По БЭМ-методологии форма будет представлена блоком . В HTML имя блока всегда записывается в атрибуте :
Все части формы (блок ), которые не имеют смысла в отрыве от нее, считаются ее элементами. Таким образом поле ввода () и кнопка () — это элементы блока . Принадлежность элемента к блоку также выражается в имени через классы:
Обратите внимание, что имя блока отделяется от имени элемента специальным разделителем. В в БЭМ для разделителя используются два подчеркивания
Разделители могут быть любыми. Существуют , и каждый разработчик выбирает наиболее удобную для себя
Важно, чтобы разделители давали возможность на программном уровне отличать блоки от элементов и модификаторов
Из имен селекторов очевидно, что для переноса формы в другой проект, необходимо скопировать все ее составляющие:
.form__search {}.form__submit {}
Запись имен в классах с помощью блоков и элементов решает еще одну важную проблему: избавляет от вложенности селекторов. У всех селекторов в БЭМ-проекте одинаковый вес. То есть переопределять стили, написанные по БЭМ, гораздо удобнее.
Теперь, чтобы использовать такую же форму в другом проекте, достаточно просто скопировать ее разметку и стили.
Суть именования компонентов в БЭМ в том, что в имени можно явно указать связь блока и его элементов.
Элемент
Составная часть блока, которая не может использоваться в отрыве от него.
Особенности:
-
характеризует смысл («что это?» — «пункт»: , «текст»: ), а не состояние («какой, как выглядит?» — «красный»: , «большой»: ).
-
Структура полного имени элемента соответствует схеме: . Имя элемента отделяется от имени блока двумя подчеркиваниями ().
Пример
form class="search-form"> input class="search-form__input"> button class="search-form__button">Найтиbutton> form>
Вложенность
-
Элементы можно вкладывать друг в друга.
-
Допустима любая вложенность элементов.
-
Элемент — всегда часть блока, а не другого элемента. Это означает, что в названии элементов нельзя прописывать иерархию вида .
Пример
form class="search-form"> div class="search-form__content"> input class="search-form__input"> button class="search-form__button">Найтиbutton> div> form> form class="search-form"> div class="search-form__content"> input class="search-form__content__input"> button class="search-form__content__button">Найтиbutton> div> form>
Имя блока задает пространство имен, которое элементов от блока ().
Блок может иметь вложенную структуру элементов в DOM-дереве:
Пример
div class="block"> div class="block__elem1"> div class="block__elem2"> div class="block__elem3">div> div> div> div>
Однако эта же структура блока в методологии БЭМ всегда будет представлена плоским списком элементов:
Пример
.block {} .block__elem1 {} .block__elem2 {} .block__elem3 {}
Это позволяет изменять DOM-структуру блока без внесения правок в коде каждого отдельного элемента:
Пример
div class="block"> div class="block__elem1"> div class="block__elem2">div> div> div class="block__elem3">div> div>
Структура блока меняется, а правила для элементов и их названия остаются прежними.
Принадлежность
Элемент — всегда часть блока и не должен использоваться отдельно от него.
Пример
form class="search-form"> input class="search-form__input"> button class="search-form__button">Найтиbutton> form> form class="search-form"> form> input class="search-form__input"> button class="search-form__button">Найтиbutton>
Необязательность
Элемент — необязательный компонент блока. Не у всех блоков должны быть элементы.
Пример
div class="search-form"> input class="input"> button class="button">Найтиbutton> div>
Задачи уровней переопределения
Уровни переопределения решают следующие задачи:
Добавление блоков в проект
Блоки с любого уровня могут использоваться в проекте без изменений.
Пример ниже показывает, как использовать кнопку из сторонней библиотеки в проекте. Для этого необходимо подключить библиотеку с блоком на отдельный уровень. Копировать код блока на уровень с общими проектными блоками не нужно.
Файловая структура проекта с подключенным уровнем библиотеки:
project/ common.blocks/ # уровень переопределения с блоками проекта header/ logo/ library.blocks/ # уровень переопределения c блоками библиотеки button/ # блок button
В результате сборки проекта блок будет подключен в проект:
@import "common.blocks/header/header.css"; @import "common.blocks/logo/logo.css"; @import "library.blocks/button/button.css";
Изменение реализации блока
Блоки с любого уровня можно изменять под требования проекта на другом уровне переопределения:
-
доопределять — добавлять новые свойства блоку;
-
переопределять — изменять существующие свойства блока.
Количество уровней, с которых собирается конечная реализация блока, и порядок их подключения могут быть любыми. Исходная реализация блока доопределяется или переопределяется реализациями с каждого последующего уровня. Поэтому в сборку сначала должна попасть исходная реализация, а затем — изменения со всех уровней переопределения.
Схема показывает подключение БЭМ-сущностей с разных уровней переопределения в сборку:
Пример ниже показывает, как изменить реализации блока из сторонней библиотеки, которая подключена в проект как отдельный уровень ():
project/ common.blocks/ # уровень переопределения с блоками проекта header/ logo/ library.blocks/ # уровень переопределения c блоками библиотеки button/ # блок button
Исходная CSS-реализация блока :
CSS-реализация:
.button { position: absolute; border: 1px solid rgba(0,0,0,.2); border-radius: 3px; background-color: #fff; }
Отображение:
Чтобы внести изменения, необходимо:
-
Переопределить блок — изменить цвет и размер кнопки.
-
Доопределить блок — добавить кнопке тень.
Для этого необходимо создать блок на уровне проекта и разместить в нем файл с новыми стилями для кнопки.
Файловая структура проекта с блоком на уровне :
project/ common.blocks/ # уровень переопределения с блоками проекта header/ logo/ button/ button.css # новые правила для блока button library.blocks/ # уровень переопределения c блоками библиотеки button/ # блок button button.css button.js
Новые CSS-правила:
.button { background-color: #ffdf3a; width: 150px; box-shadow: 10px rgba(0,0,0,0.5); }
В результате сборки реализация блока будет состоять из исходных CSS-правил с уровня и добавленных — с уровня :
@import "library.blocks/button/button.css"; @import "common.blocks/button/button.css";
Повторяющееся свойство () будет переопределено (фон кнопки изменится на желтый), а новые свойства ( и ) — добавлены. Блоку применится следующий набор свойств:
.button { position: absolute; border: 1px solid rgba(0,0,0,.2); border-radius: 3px; background-color: #ffdf3a; width: 150px; box-shadow: 10px rgba(0,0,0,0.5); }
Новый вид кнопки:
В результате:
-
Исходная реализация блока не изменяется.
-
Проектные изменения для блока применятся ко всем кнопкам проекта.
-
При обновлении библиотеки до новой версии, изменения блоков, которые сделаны для проекта, сохранятся на другом уровне переопределения. Если в новой версии библиотеки изменится фон кнопки или ее размеры, в проекте для блока все равно применятся переопределенные правила.
Работа с DOM-деревом
DOM-узел экземпляра блока и элемента
В контексте экземпляра блока и элемента с DOM-представлением зарезервировано поле , содержащее jQuery-объект со ссылками на все DOM-узлы, с которыми связан данный экземпляр.
Поиск экземпляров блоков и элементов в DOM-дереве
Обращение к другому блоку в выполняется из текущего блока, размещенного на определенном узле DOM-дерева. Поиск других блоков в DOM-дереве может вестись по трём направлениям (осям) относительно DOM-узла текущего блока:
-
Внутри блока — на DOM-узлах, вложенных в DOM-узел текущего блока.
Вспомогательные методы:
-
;
-
;
-
;
-
.
-
-
Снаружи блока — на DOM-узлах, потомком которых является DOM-узел текущего блока.
Вспомогательные методы:
-
;
-
;
-
;
-
.
-
-
На себе — на том же DOM-узле, на котором размещен текущий блок. Это актуально в случае (микс).
Вспомогательные методы:
-
;
-
;
-
;
-
.
Методы и могут возвращать больше одного экземпляра в случае, когда к примешаны несколько разных экземпляров одного и того же блока () или ().
-
Сигнатура вспомогательных методов поиска блоков идентична:
block {Function|Object} – класс или описание искомого блока. Описанием служит хеш вида { block : MyBlock, modName : ‘my-mod’, modVal : ‘my-val’ }.
Для методов поиска элементов:
-
– имя, класс или описание искомого элемента. Описанием служит хеш вида или ;
-
– нужно ли учитывать вложенность одноимённых блоков.
Вспомогательные методы для поиска парные. Различаются возвращаемым значением:
-
и – возвращает первый найденный экземпляр
-
– возвращает коллекцию найденных экземпляров
Пример
modules.define('attach', , function(provide, bemDom, Button) { provide(bemDom.declBlock(this.name, { onSetMod: { 'js': { 'inited' : function(modName, modVal) { this._button = this.findChildBlock(Button); } } } })); });
Кэширующие методы поиска экземпляров элементов
Для оптимизации производительности для распространённых случаев поиска элементов одновременно по двум осям (внутри и на себе), служат кэширующие методы и . Оба метода принимают один параметр:
elem {String|Function|Object} – имя, класс или описание искомого элемента. Описанием служит хеш вида { elem : MyElem, modName : ‘my-mod’, modVal : ‘my-val’ } или { elem : ‘my-elem’, modName : ‘my-mod’, modVal : ‘my-val’ }.
Аналогично с некэширующими методами поиска кеширующие методы различаются возвращаемым значением:
-
– возвращает первый найденный экземпляр элемента
-
– возвращает коллекцию найденных экземпляров элементов
Пример
modules.define('button', , function(provide, bemDom, ButtonControl) { provide(bemDom.declBlock(this.name, { setName : function(name) { this._elem(ButtonControl).setName(name); }, setValue : function(value) { this._elem(ButtonControl).setValue(value); } })); });
Кеширующий метод поиска экземпляра блока элемента
_block() — возвращает экземпляр блока для элемента.
Пример
modules.define('my-form__submit-control', , function(provide, bemDom) { provide(bemDom.declElem('my-form', 'submit-control', { _onClick : function() { this._block().submit(); } })); });
Проверка вложенности
containsEntity(entity) — проверяет вложен ли переданный экземпляр entity {i-bem-dom:Entity} в текущий экземпляр.
Динамическое обновление блоков и элементов в DOM-дереве
В модуле предусмотрены следующие функции для добавления и замены фрагментов DOM-дерева.
-
Удалить DOM-фрагмент:
destruct(ctx, )
Сигнатура функции:
-
– корневой DOM-элемент. Удаляется со всем вложенными DOM-узлами.
-
– не удалять корневой DOM-элемент, если значение . По умолчанию .
-
-
Добавить DOM-фрагмент:
-
— в конец указанного контекста;
-
— в начало указанного контекста;
-
— перед указанным контекстом;
-
— после указанного контекста;
-
-
Заместить DOM-фрагмент:
-
— внутри указанного контекста;
-
— заменить указанный контекст новым DOM-фрагментом.
Сигнатура функций добавления и замены идентична:
-
– DOM-элемент
-
– содержимое
-
Все функции возвращают DOM-элемент с содержимым для которого была выполнена .
Чтобы упростить создание БЭМ-сущностей на обновляемых фрагментах DOM-дерева, можно использовать шаблонизатор BEMHTML, подключив его в качестве ym-модуля. БЭМ-сущности описываются в формате BEMJSON непосредственно в коде блока. Функция генерирует HTML-элементы по BEMJSON-декларации в соответствии с правилами именования БЭМ.
Пример
Метод блока удаляет элемент , если он существовал, и создает новый элемент с помощью функции :
modules.define( 'attach', , function(provide, BEMHTML, bemDom) { provide(bemDom.declBlock(this.name, { _updateFileElem : function() { bemDom.replace( this._elem('file').domElem, BEMHTML.apply({ block : 'attach', elem : 'file', content : this.getValue() })); return this; } })); });
Миксы
Позволяют:
-
совмещать поведение и стили нескольких сущностей без дублирования кода;
-
одинаково форматировать разные HTML-элементы.
Внешняя геометрия и позиционирование
В CSS по БЭМ стили, отвечающие за внешнюю геометрию и позиционирование, задаются через родительский блок.
Пример
HTML-реализация:
header class="header"> button class="button header__button">...button> header>
CSS-реализация кнопки:
.button { font-family: Arial, sans-serif; text-align: center; border: 1px solid black; } .header__button { margin: 30px; position: relative; }
В данном примере внешняя геометрия и позиционирование блока задана через элемент . Блок не специфицирует никакие отступы и может быть легко переиспользован в любом месте.
HTML-реализация:
footer class="footer"> button class="button">...button> footer>
Стилизация групп блоков
Иногда необходимо применить одинаковое форматирование сразу к нескольким различным HTML-элементам веб-страницы.
Обычно для решения подобных задач применяют групповые селекторы.
Пример
HTML-реализация:
article class="article">...article> footer class="footer"> div class="copyright">...div> footer>
CSS-реализация:
.article, .footer div { font-family: Arial, sans-serif; font-size: 14px; color: #000; }
В данном примере текст внутри блоков и имеет один и тот же цвет и шрифт.
Несмотря на то, что групповые селекторы позволяют быстро изменить дизайн страницы, такой подход увеличивает связанность кода.
Поэтому в БЭМ для того, чтобы единообразно отформатировать целый набор HTML-элементов, используют .
Пример
HTML-реализация:
article class="article text">...article> footer class="footer"> div class="copyright text">...div> footer>
CSS-реализация:
.text { font-family: Arial, sans-serif; font-size: 14px; color: #000; }