«В поисках идеального css-фреймворка. Требования, реализация, maxmertkit»
Раздел: Социальные сети
Я обожаю twitter bootstrap. Прост, местами логичен, достаточно красив, подходит для быстрого прототипирования веб-интерфейсов. Но этого оказалось недостаточно. Взяв twitter bootstrap в большой проект, мне пришлось целиком его разобрать и переосмыслить css-фреймворки как боевые единицы в веб-проектах. В результате переосмысления родились требования к любому css-фреймворку, удобному как верстальщику, так и frontent-разработчику. Требования к фреймворку
Прочитав требования, которые сам же и составил, я понял, что таких фреймворков я не знаю. Значит есть над чем поработать. Краткая история созданияОчень кратко. Я сделал три версии. Первая была сделана дня за три. Естественно, на чистом css такое не напишешь, поэтому для первой версии я выбрал LESS. Сахар оказался не достаточно сладок, и для второй версии я выбрал SASS. Оказалось он гораздо гибче и позволяет делать вещи, которые на LESS реализовать сложно, а порой просто нельзя. Вторую версию я делал около трех недель, но в силу того, что я только начал осваивать SASS, вместо вспаханного поля я получил кратер. Попытка переписать то, что уже есть, все только усугубила, поэтому я приступил к третьей версии, которую вы можете видеть сейчас. Названия я давать не умею, поэтому просто добавил kit к своему никнейму. Сайт – maxmert.com. Maxmertkit. Структура файлов.Все файлы ни в коем случае не должны лежать в одной большой куче. Это, в конце концов, не только не красиво, но и не практично. Classes. Папка содержит все базовые классы, от которых наследуются все остальные виджеты. На данный момент он один – object. Modificators. Содержит все возможные модификаторы, применяемые к виджетам. На данный момент это статус, размер и другое. Widgets. Внутри все виджеты, от кнопки до галереи. Animations. CSS-анимации для виджетов. _init.scss. Инициализация типографики и базовых классов. _mixins.scss. Примеси. maxmertkit*.scss. Файлы для компиляции. По сути они просто подключают необходимые модули. Если вам что-то не нужно, просто закоментируйте импорт. style.scss. Ваши стили. Кредо.В это разделе я расскажу основные принципы, соблюдавшиеся при разработке maxmertkit. Все они, так или иначе, соответствуют требованиям, поставленным в начале статьи. Неймспейсы.Для грамотного написания своих классов в фреймворке жизненно необходимы неймспейсы. Для чего? Я думаю частенько возникает желание назвать класс для бейджа badge, а для таблицы – table. Только все время приходится вспоминать все используемые во фреймворке классы. Не совсем практично. В maxmertkit такого недостатка нет. class=”-{имяВиджета}” – все названия виджетов, например -table, -tooltip, -badge, -modal и т.д. class=”-{имяСтатуса}-” – имя статуса, например, -error-, -warning-, -info-, -disabled-, -unstyled- и т.д. class=”_{имяРазмера}” – имя размера, например, _tiny, _small, _big, _huge. class=”_{именаДругихМодификаторов}_” – например, _loading_, _unclickable_, _active_ и т.д. Что важно, для любого виджета используются одни и те же модификаторы. Например модификатор _loading_ можно поставить как кнопке, так и таблице или табу. Это позволяет не запоминать длинные составные классы для каждого из виджетов. Рассмотрим рядовой пример. Есть кнопка, которая удаляет какой-либо контент. Имеется и несколько условий. Сразу после загрузки страницы мы должны проверить, может ли данный пользователь удалять этот контент или нет (например, хватает ли кармы). Причем если не может кнопку все-равно показывать, но со статусом disabled, если может, со статусом error (чтобы кнопка была красной). Пока задача ставится целиком для css. Поэтапно.
Повторюсь, что продемонстрированные модификаторы работают для всех виджетов, не только для кнопки. На главной странице www.maxmert.com есть небольшой конструктор, позволяющий понять как они работают для других виджетов. Наследование модификаторовКогда вы применяете модификатор к виджету-родителю, все виджеты-дети его наследуют. Причем если у ребенка стоит модификатор того же типа, он переопределяет родительский. Это хорошо видно на примере группы. Это группа без модификаторов.
Добавим статус -primary-.
Добавим статус -dark- кнопке внутри группы.
Если хотите кнопки побольше, присвойте модификатор размера группе. Все внутренние виджеты (включая иконки) его унаследуют.
Промежуточные итогиИтак, пока мы решили следующие задачи (нумерация соответствует списку в начале): 1. Используем легко запоминающиеся неймспейсы. 2. Используем независимые друг от друга виджеты, которые можно легко исключить из сборки. 5. Нет необходимости помнить много составных классов для разных виджетов, потому что одни и те же модификаторы применяются ко всем виджетам. 7. Модификаторы наследуются виджетами-детьми. 8. Шрифтовые иконки. Остаются пункты: 4. Возможность легко менять имена виджетов и модификаторов. 6. При изменении модификаторов (цвета, размера и т.д.), их удаления или добавления все изменения должны быть применены ко всем виджетам. То есть если мы добавили какой-нибудь модификатор статуса, то его можно сразу же применить к любому из виджетов без правки его кода. 9. Легкая сборка новых виджетов с учетом вышеперечисленных требований. Файл темыФайл темы успешно решает задачи 4 и 6. Посмотрим каким образом. Он находится в папке themes. Название этого файла может быть любым, начинающимся с подчеркивания (требование SASS, файлы с такими названиями не компилируются отдельно), только не забудьте импортировать нужный файл темы в проект. Имена переменных внутри файла темы образуются следующим образом: ${объектРодитель}__{данныйОбъект}-{свойство}__{составнаяЧасть}-{свойство} Например, $object__group object – родитель (как я уже и говорил, пока что он один); group – это объявляемый виджет. $object__group__appendix appendix – это составная часть, находящаяся внутри виджета group (это может быть header, content и вообще все, что угодно) $object__group__appendix-border-width Это объявление толщины границы текстового придатка внутри группы. $object__dropdown__header-padding Внутренний отступ заголовка выпадающего дропдауна. Итак, как же объявляются имена виджетов? Очень просто. При объявлении виджета без его свойств всегда указывается название класса. Таким образом, если вам не нравятся названия классов, вы легко сможете поменять их в файле темы:
Посмотрим на модификаторы. Для начала разберем модификаторы статуса. Для каждого из модификаторов выделен отдельный столбец. Верхняя строка – это название. Удалив столбец с модификатором, например, error, мы получим вполне ожидаемый результат: модификатор error исчезнет и ни один из виджетов не будет изменяться при добавлении соответствующего класса -error-. Кроме того вы можете поменять название, к примеру на error1, и теперь только добавив к виджету класс -error1- вы измените его статус. Также вы можете добавить столбец со своим статусом и он сразу же будет работать со всеми виджетами. Теперь о модификаторах размера. Здесь вы так же можете поменять название модификатора в столбце, изменить множитель размера виджета, удалить или добавить свой размер. Все изменения тоже отразятся на всех виджетах. Виджеты, имеющиеся в maxmertkitНа скриншотах далеко не все, что умеют эти виджеты. В сочетании с различными модификаторами они смотрятся совершенно по-другому, появляются десятки вариантов одного виджета. Сходите на maxmert.com, посмотрите примеры, полистайте доки.
Полный список можно увидеть внутри папки widgets. ЯваскриптНа данный момент я написал 8 плагинов.
Здесь сложно кого-то удивить. В доках все есть. Есть только несколько моментов, о которых я хотел рассказать.
Все плагины были написаны на чистом яваскрипт. Но я приступил к переписыванию на coffeescript, ибо поддерживать и понимать исходный код с кофе гораздо легче. Я за кофе с сахаром. Создание нового виджетаДальше пошла матчасть, поэтому если вы не собираетесь делать виджеты для себя или не хотите добавить в репозиторий maxmertkit, можно и не читать. Предупрежу, что над пунктом 9 еще можно поработать, ибо добавление новых виджетов, на мой взгляд, можно еще упростить. Но на данный момент я имею только такой вариант. Разберем на примере кнопки. Новый виджет кладется в папку widgets, название файла начинается с подчеркивания (для предотвращения самостоятельной компиляции). Сначала пишутся все стили, не касающиеся модификаторов, уникальные для этого виджета.
@extend %__object – наследование от класса объект, о котором многократно говорилось выше. Это дает возможность хорошо применять модификаторы для этого виджета. Все переменные, конечно же, берутся из файла темы. Далее самое интересное. Мы должны указать, что к виджету “кнопка” применимы определенные модификаторы. Причем когда один из модификаторов применяется к виджету, он не обязательно меняет в нем все от цвета текста до тени, он может поменять в нем только маленькую часть (например при добавлении модификатора -error- к кнопке поменять только цвет текста, а фон и все остальное не трогать). В нашем случае
$__inheritance: object – класс объекта-родителя (можно задать другой, но об этом немного позже) $__before-object и $__after-object – о них чуть ниже (но их обязательно указывать даже пустые). $__object – здесь в кавычках через пробелы или табы указываются объекты, к которым непосредственно будут применяться модификаторы (то есть на которые будут навешиваться классы модификаторов) @ include set_modificator($mod__status, color-invert, border-color, gradient-vertical, text-shadow) – функция, устанавливающая для виджета модификаторы статуса $mod__status (это те самые столбцы из файла темы), причем при применении одного из модификаторов устанавливаются только инвертированный цвет текста, цвет границ, вертикальный градиент и тень для текста. Попробуем изменять кнопку, когда пользователь наводит на нее курсор:
Как вы заметили, здесь вместо обычного списка используется функция append-list, которая просто добавляет ‘:hover’ в конец каждого элемента списка. Мы могли бы не использовать ее, а просто написать
Кроме того компоненты модификаторов, которые использовались ранее, больше не указываются, указываются только новые компоненты, или компоненты, которые переопределят старые (в нашем случае в кнопке с псевдоклассом :hover компонент gradient-vertical-darken переопределит старый gradient-vertical) То же самое для :active
Если вам лень писать список в $__object, можно написать вот так:
Вы, конечно, заметили, что блок
многократно повторяется. Его можно написать один раз до объявления кнопки. То же самое без лишнего кода:
А что же делать, если виджет кнопка лежит внутри другого виджета? Вот здесь нам пригодится $__before-object и $__after-object:
Это значит, что модификаторы теперь будут применятся к группе, так как $__object теперь группа, но внешне будет изменяться все, что находится в $__after-object. То есть в результате компиляции мы получим что-то вроде
Если же мы будем использовать $__before-object,
то получим нечто похожее на
Последний не рассмотренный вопрос: что делать, если для данного элемента применимы не все модификаторы (то есть нам нужно исключить из списка $mod__status некоторые из них)?
@ include set_modificator(exclude-items($mod__status,$mod__status__disabled, default), loading) – исключает из списка $mod__status статусы disabled и default. То есть когда вы поставите модификатор loading отдельной кнопке внутри группы, он не будет применяться, если у кнопки нет никакого статуса или если статус disabled. Аналогично работает only-items @ include set_modificator(only-items($mod__status,$mod__status__disabled, default), loading-dark) – оставляет из списка $mod__status только указанные статусы. Компоненты, доступные для $mod__status:
Это значит что любой из них вы можете использовать следующим образом
Компоненты, доступные для $mod__size:
Используется так
Даже если вы укажете компонент padding, размер объекта будет меняться в зависимости от модификатора размера, но бывают случаи, когда padding меняться должен, но он должен быть маленьким или большим и меняться незначительно. Именно поэтому появляются компоненты padding-small и padding-big. В качестве послесловияСайт – maxmert.com Github – https://github.com/maxmert/maxmertkit Мой английский без практики стал совсем русским, поэтому на сайте вы можете встретить ошибки, неправильные обороты или времена. Очень прошу помочь мне и сообщить, если вы увидите такую бяку. Для этого просто выделяете кусок текста и нажимаете на кнопку «Report an error» в левом плавающем меню. Заранее благодарен. Я достаточно долго тестировал maxmertkit, но все же если вы заметите баги в верстке, напишите issue в github'е. Благодарю читателей и всех, кто будет использовать этот фреймворк. Надеюсь облегчить нелегкую работу frontend-разработчиков. Обновление:
Жду предложений, например, какие виджеты вы бы еще хотели? Ну и, конечно, информацию об обнаруженных ошибках в github'e. Дата публикации: 2013-01-14 |