Сначала библиотека шаблонов: подход к управлению CSS

Опубликовано: 2022-03-10
Краткий обзор ↬ CSS может быть сложным в управлении проектом, особенно когда вам нужно включить медиа-запросы для различных точек останова и резервных вариантов для старых браузеров. В этой статье мы рассмотрим использование Fractal для управления компонентами, использующими CSS Grid.

В этой статье, основанной на докладе, который я сделал на Smashing Conference в Торонто, я собираюсь описать метод работы, который я принял за последние два года, который помогает мне управлять CSS в моих проектах.

Я покажу вам, как использовать инструмент библиотеки паттернов Fractal, чтобы управлять вашим CSS покомпонентно, позволяя вам использовать инструменты, с которыми вы уже знакомы. Хотя это служит введением в Fractal и тем, почему мы выбрали именно эту библиотеку шаблонов, вполне вероятно, что этот способ работы будет перенесен в другие решения.

Наши проекты

У моей компании есть несколько продуктов — Perch и Perch Runway CMS, а также Notist, программное обеспечение как сервисное приложение для ораторов. Эти продукты совершенно разные, особенно с учетом того, что Perch — это система с собственным хостингом, а Notist — SaaS, однако у них обоих есть много пользовательских интерфейсов для разработки. У нас также есть все связанные веб-сайты и документация для этих продуктов, а также другие вещи, над которыми мы работаем, например веб-сайт 24 Ways. После открытия Fractal два года назад мы переносили каждый новый проект — большой и маленький — во Fractal.

Проблемы, которые мы хотели решить

Я начал исследовать решения библиотеки шаблонов два года назад, когда начал работу по перестройке пользовательского интерфейса Perch для версии 3. Особенность Perch заключается в том, что шаблоны, которые вы создаете для вывода контента на своем веб-сайте, становятся схемой пользовательского интерфейса администратора. Это означает, что любой тип поля, используемый в шаблоне, должен существовать вместе с любым другим типом поля. Мы не знаем, как наши клиенты могут их комбинировать, и существует огромное количество возможных комбинаций. Это также не «веб-сайт», и я не хотел пытаться превратить библиотеку шаблонов во что-то, предназначенное для организации шаблонов веб-сайта.

Поскольку Perch размещается самостоятельно — люди загружают его и размещают на своих серверах — нам нужно использовать максимально простой технический стек, чтобы не создавать дополнительных барьеров для входа перед людьми, многие из которых плохо знакомы с использованием CMS. Чтобы добавить дополнительный уровень удовольствия, мы поддерживаем Internet Explorer 9, но я намеревался использовать много Flexbox — как это было до появления Grid Layout.

Еще после прыжка! Продолжить чтение ниже ↓

Я также стремился избегать использования инструментов, которые потребовали повторного изучения того, как мы работали, и полного изменения нашего процесса. Любой дополнительный инструмент или изменение способа работы над вашими проектами приносит с собой новые трения. Вы можете решить одну проблему, но привнести целый ряд новых проблем, если внесете серьезные изменения в то, как вы работаете. В нашем случае мы использовали Sass довольно ограниченно и обрабатывали это с помощью Gulp. Ни один из наших проектов не использует фреймворк Javascript, мы просто пишем HTML, CSS и JavaScript.

Fractal идеально подходит для наших нужд. Он не зависит от того, как вы разрабатываете или какие инструменты вы хотите использовать. Что важно для наших целей, это не предполагало, что мы создаем веб-сайт. Эксперимент оказался настолько успешным, что мы использовали Fractal для каждого проекта, большого или малого, поскольку он значительно упрощает процесс работы с CSS. Даже небольшие сайты, которые я создаю самостоятельно, часто начинают жизнь во Fractal, потому что в работе с библиотекой шаблонов больше преимуществ, чем вы думаете, и многие из этих преимуществ имеют такое же значение для команды из одного человека, как и для большой команды. .

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

Начало работы с фракталом

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

Установив новый проект, в командной строке перейдите в папку, которую вы только что создали, и выполните команду:

 fractal start --sync

Это запустит небольшой сервер на порту 3000, поэтому вы сможете перейти на https://localhost:3000 в веб-браузере и увидеть свой проект.

Теперь, когда ваш проект запущен и работает, откройте папку проекта в своем любимом текстовом редакторе и найдите пример компонента в components/example . Вы найдете файл конфигурации и файл с именем example.hbs . Шаблон example.hbs — это HTML-код вашего компонента, вы можете добавить к нему еще HTML-код, и Fractal автоматически перезагрузит и отобразит его. Измените файл на:

 <h1>This is my heading</h1> <p>{{ text }}</p>

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

 title: Example component context: text: This is an example component! heading: My heading

Теперь измените файл example.hbs , чтобы он читался в этом тексте.

 <h1>{{ heading }}</h1> <p>{{ text }}</p>

Добавление дополнительных компонентов

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

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

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

Добавление рабочего процесса CSS

На данный момент мы можем создавать HTML-компоненты в виде шаблонов рулей и файл конфигурации для вставки данных, однако мы не добавили никакого CSS. В идеале мы хотим добавить CSS для каждого компонента в ту же папку, что и остальные файлы компонентов, а затем объединить все вместе.

Я упомянул, что Fractal делает очень мало предположений о вашем рабочем процессе; из-за этого он делает гораздо меньше из коробки, чем мог бы, если бы заставлял вас работать определенным образом. Тем не менее, мы можем довольно легко заставить Fractal работать с настройкой Gulp.

Сочетание Fractal, Sass и Gulp

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

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

  1. Внутри общей папки вашей установки Fractal добавьте папку с именем css .
  2. В корневой папке вашего Fractal установите папку assets , внутри которой находится папка scss . Создайте в этой папке файл Sass с именем global.scss . Внутри этого файла добавьте следующую строку:
     @import "../../components/**/*.scss";
  3. Создайте файл с именем example.scss в каталоге компонентов вашего example .
  4. Создайте gulpfile.js в корне вашего проекта Fractal и добавьте приведенный ниже код.
 'use strict'; const gulp = require('gulp'); const fractal = require('./fractal.js'); const logger = fractal.cli.console; const sass = require('gulp-sass'); const sassGlob = require('gulp-sass-glob'); const plumber = require('gulp-plumber'); const notify = require('gulp-notify'); const path = require('path'); gulp.task('sass',function() { return gulp.src('assets/scss/**/*.scss') .pipe(customPlumber('Error running Sass')) .pipe(sassGlob()) .pipe(sass()) .pipe(gulp.dest('public/css')) }); gulp.task('watch', ['sass'], function() { gulp.watch([ 'components/**/*.scss', 'assets/scss/**/*.scss' ], ['sass']); }); function customPlumber(errTitle) { return plumber({ errorHandler: notify.onError({ title: errTitle || "Error running Gulp", message: "Error: <%= error.message %>", }) }); } gulp.task('fractal:start', function(){ const server = fractal.web.server({ sync: true }); server.on('error', err => logger.error(err.message)); return server.start().then(() => { logger.success(`Fractal server is now running at ${server.url}`); }); }); gulp.task('default', ['fractal:start', 'sass', 'watch']);

Затем я устанавливаю зависимости, перечисленные в верхней части файла. Если бы вы установили их в командной строке, вы бы запустили:

npm install gulp gulp-sass gulp-sass-glob gulp-plumber gulp-notify

Функция sass компилирует Sass из ассетов в один файл и выводит в папку в public .

 gulp.task('sass',function() { return gulp.src('src/assets/scss/**/*.scss') .pipe(customPlumber('Error running Sass')) .pipe(sassGlob()) .pipe(sass()) .pipe(gulp.dest('public/css')) });

Затем я создаю функцию watch , которая будет следить за моим Sass в assets , а также в отдельных компонентах и ​​компилировать их в папку для всех.

 gulp.task('watch', ['sass'], function() { gulp.watch([ 'components/**/*.scss', 'assets/scss/**/*.scss' ], ['sass']); });

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

 gulp.task('fractal:start', function(){ const server = fractal.web.server({ sync: true }); server.on('error', err => logger.error(err.message)); return server.start().then(() => { logger.success(Fractal server is now running at ${server.url}); }); });

Наконец, мне нужно убедиться, что сборка Sass и запуск Fractal запускаются, когда я запускаю gulp и командную строку:

gulp.task('default', 'fractal:start', 'sass', 'watch');

Это мой готовый gulpfile.js . Если вы добавите это в свой проект Fractal по умолчанию, убедитесь, что папки соответствуют указанным путям. Вы должны иметь возможность перейти в командную строку, запустить gulp , и Fractal запустится.

Вывод командной строки
Запуск фрактала с помощью gulp (Посмотреть большую версию)

Мы можем протестировать наш Sass, добавив переменную в файл global.scss ; вам нужно будет добавить это над строкой, которая включает компоненты, чтобы переменная была доступна для этих компонентов.

 $color1: rebeccapurple;

Затем в example.scss добавьте правило для заголовка уровня 1, которое мы добавили ранее:

 h1 { color: $color1; }

Если все настроено правильно, вы должны найти файл .css в public/css, который содержит правило:

 h1 { color: rebeccapurple; }

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

Внутри папки компонентов создайте файл с именем _preview.hbs .

Файл предварительного просмотра, по сути, представляет собой HTML-документ со ссылками на наш CSS и все остальное, что вам нужно включить. В теле есть тег {{ yield }} , и именно здесь будет размещен компонент.

 <!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Preview Layout</title> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link rel="stylesheet" href="{{ path '/css/global.css' }}"> </head> <body> {{{ yield }}} </body> </html>

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

Библиотека паттернов как источник истины

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

Мы создаем все во Fractal, а затем копируем эти общедоступные ресурсы на действующие сайты для развертывания. Помимо предотвращения дрейфа между системами, это также значительно упрощает управление CSS в системе контроля версий. Когда несколько человек работают над одним файлом CSS, справиться с конфликтами слияния может быть достаточно сложно. С людьми, работающими над отдельными компонентами в библиотеке шаблонов, вы обычно можете избежать одновременной фиксации изменений двумя людьми в одном и том же файле, и если они это сделают, это будет только небольшой файл для сортировки, а не весь ваш CSS.

Использование библиотеки шаблонов первого подхода для управления откатами

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

Мы можем рассмотреть простой пример компонента медиа-объекта, чтобы увидеть, как это может работать. Чтобы продолжить, создайте папку media внутри компонентов во Fractal и добавьте файлы media.hbs и media.scss .

Начните с хорошей разметки

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

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

Поэтому мой компонент имеет следующую разметку, которую я добавляю в media.hbs .

 <div class="media"> <div class="img"> <img src="/img/placeholder.jpg" alt="Placeholder"> </div> <h2 class="title">This is my title</h2> <div class="content"> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis vehicula vitae ligula sit amet maximus. Nunc auctor neque ipsum, ac porttitor elit lobortis ac. Vivamus ultrices sodales tellus et aliquam. Pellentesque porta sit amet nulla vitae luctus. Praesent quis risus id dolor venenatis condimentum.</p> </div> <div class="footer"> An optional footer goes here. </div> </div>

Вы можете видеть, как это отображается внутри Fractal:

Фрактальный интерфейс с добавленным компонентом
Мой компонент после добавления разметки. (Посмотреть большую версию)

Как только у меня будет нужная разметка, я буду работать над отображением рабочего стола, которое я имею в виду. Я собираюсь использовать CSS Grid Layout и метод grid-template-areas для этого. Добавьте следующее в media.scss .

 img { max-width: 100%; } .media > .title { grid-area: title; } .media > .img { grid-area: img; } .media > .content { grid-area: bd; } .media > .footer { grid-area: ft; } .media { margin-bottom: 2em; display: grid; grid-column-gap: 20px; grid-template-columns: 200px 3fr; grid-template-areas: "img title" "img bd" "img ft"; }

Теперь у нас есть простой макет медиа-объекта:

Макет в два столбца, изображение слева, текст справа
Макет медиа-объекта. (Посмотреть большую версию)

Кое-что, что вы можете сделать во Fractal, это добавить вариации компонента. Возможно, вы захотите перевернуть медиа-объект так, чтобы изображение оказалось справа.

Теперь добавьте CSS в media.scss , чтобы перевернуть макет:

 .media.media-flip { grid-template-columns: 3fr 200px ; grid-template-areas: "title img" "bd img" "ft img"; }

Существует два способа создания вариантов: на основе файлов и на основе конфигурации. Файловый вариант самый простой, а также полезен, если ваш вариант имеет другую разметку. Чтобы создать файловый вариант, сделайте копию вашего компонента в папке media с именем media --flip.hbs (это два дефиса в имени файла).

Этот компонент должен иметь идентичную разметку с классом media-flip , добавленным в первую строку, и тогда вы сможете увидеть обе версии.

 <div class="media media-flip">
Макет в два столбца, изображение справа, текст слева.
Перевернутая версия. (Посмотреть большую версию)

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

Если вы хотите сделать это, удалите файл вариантов и вместо этого добавьте файл конфигурации с именем media.config.json , содержащий следующий код:

 { "title": "Media Object", "context": { "modifier": "default" }, "variants": [ { "name": "Flipped", "context": { "modifier": "flip" } } ] }

Затем измените первую строку media.hbs следующим образом:

<div class="media media-{{ modifier }}">

Примечание . Вы можете добавить столько вариантов, сколько хотите (дополнительную информацию см. в документации по вариантам).

Теперь мы можем подумать о добавлении CSS для изменения макета в зависимости от размера экрана. Обертывание макета, который мы создали, в медиа-запросе, а также создание макета с одним столбцом для небольших устройств.

 img { max-width: 100%; } .media > .title { grid-area: title; } .media > .img { grid-area: img; } .media > .content { grid-area: bd; } .media > .footer { grid-area: ft; } .media { display: grid; grid-column-gap: 20px; grid-template-areas: "title" "img" "bd" "ft"; } @media (min-width: 600px) { .media { margin-bottom: 2em; display: grid; grid-column-gap: 20px; grid-template-columns: 200px 3fr; grid-template-areas: "img title" "img bd" "img ft"; } .media.media-flip { grid-template-columns: 3fr 200px ; grid-template-areas: "title img" "bd img" "ft img"; } }
Макет с одной колонкой
Объект для мобильных устройств. (Посмотреть большую версию)

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

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

Просто внутри медиа-запроса добавьте следующий CSS:

 .media:after { content: ""; display: table; clear: both; } .media > .media { margin-left: 160px; clear: both; } .media .img { float: left; margin: 0 10px 0 0; width: 150px; } .media.media-flip .img { float: right; margin: 0 0 0 10px; } .media > * { margin: 0 0 0 160px; } .media.media-flip > * { margin: 0 160px 0 0; }

Это должно отсортировать отображение в браузерах без сетки. Для браузеров, которые поддерживают сетку, вам не нужно беспокоиться о плавающих элементах, т. е. когда плавающий элемент становится элементом сетки, плавающий элемент удаляется. Что будет проблемой, так это любые наценки. Макет в браузерах, поддерживающих сетку, теперь будет растянут из-за дополнительных полей.

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

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

 @supports(display: grid) { .media > *, .media.media-flip > * { margin: 0; } .media .img, .media.media-flip .img { width: auto; margin: 0; } .media:after { content: none; } }

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

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

Первая разработка сокращенного тестового примера

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

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

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

Именно из-за простоты организации нашего кода Fractal имеет смысл даже в небольших проектах. Учитывая, что мы в любом случае склонны использовать Gulp и Sass (даже в небольших проектах), добавление Fractal в смесь не требует больших затрат. Нам не нужно рассматривать это только для наших больших проектов, поскольку даже на небольшом сайте может быть разумное количество CSS.

См. Кодекс

Я создал проект GitHub, в котором есть весь код, упомянутый в статье. Я бы предложил настроить Fractal, как описано в статье, а затем взять любые фрагменты, такие как gulpfile или макет предварительного просмотра, из моего репозитория.

В качестве дополнительной справки и для просмотра некоторых опубликованных проектов Fractal у нас есть опубликованная версия библиотеки образцов окуня, а также библиотека образцов для 24 способов (создана Полом Робертом Ллойдом), с которой вы можете ознакомиться. Это хорошие примеры библиотеки шаблонов не для веб-сайта и более традиционной библиотеки, используемой для сайта.

Как вы управляете CSS?

Мне очень нравится этот способ работы; это позволяет мне писать CSS простым, постепенно совершенствуемым способом. В зависимости от проекта мы можем включить гораздо больше инструментов и обработки файлов. Или я могу создать простой сайт, и в этом случае настройка будет примерно такой, как мы видели в этой статье — с небольшой обработкой Sass. Тот факт, что Fractal означает, что у нас может быть один и тот же процесс для больших и малых сайтов, для веб-приложений или веб-сайтов. Это означает, что мы всегда можем работать привычным способом.

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