Карандашик
Инструкция

Инструкция

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

Старый и новый сайт бюро

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

Если страницу сайта можно редактировать с помощью карандашика, в её правом верхнем углу будет стоять иконка . На телефоне эта иконка будет стоять в левом нижнем углу:

При нажатии на иконку карандашика открывается редактор кода текущей страницы.

Если у вас нет доступа к Карандашику, то вы не увидите иконку. Доступ к Карандашику привязан к Бюросфере. Доступ автоматически получают все бюрошники, а остальные — по предварительному согласованию с бюро. Иными словами, если вы бюрошник и у вас ещё нет доступа, то напишите в сапорт: support@bureau.ru. А если вы не бюрошник, но считаете, что вам полагается доступ, то обсудите это с кем‑то из бюрошников.

Основы

Как создать новую страницу

В адресную строку впишите адрес, по которому будет открываться страница, и припишите в конце «/new». Например, «bureau.ru/projects/playstation‑site/new». Создастся новая страница и откроется её редактор.

Как устроен редактор кода

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

Как посмотреть черновик и опубликовать страницы

Чтобы посмотреть, что у вас получается, откройте черновик страницы (он же — драфт). Для этого или нажмите на окошко предпросмотра, или допишите в адресной строке браузера /draft после адреса страницы. Например, bureau.ru/projects/playstation‑site/draft. Всё, что вы делаете в Карандашике, поначалу не видно никому, кроме тех, у кого есть доступ к Карандашику — при попытке открыть страницу или черновик, и сама страница, и черновик будут выдавать ошибку 404.

Чтобы сделанная вами страница открывалась у кого угодно, её нужно опубликовать — нажать на жёлтую кнопку Publish. Если страница уже опубликована, а вы хотите на ней что‑то изменить, то эти изменения опять же никто не увидит, пока вы снова не нажмёте Publish. Если вы опубликовали страницу по ошибке или передумали, то после публикации в кнопке Publish появится выпадушка с пунктом Unpublish.

Как загружать файлы и картинки

Перейдите во вкладку Files и просто перетащите изображение в окно файлового менеджера.

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

Как устроен синтаксис

Страницы собираются с помощью специального кода для компилятора «Паг». Компилятор преобразовывает этот код в ХТМЛ и ЦСС. Первое слово на каждой строке воспринимается как тег, остальные — как содержимое тега. Например, напишем код заголовка, списка и двух абзацев:

div
  h1 Заголовок второго уровня
  p Абзац текста. Дальше идёт рыбный текст. Изменение глобальной стратегии сознательно индуцирует конвергентный нестандартный подход. До недавнего времени считалось, что провоцирование на рынке.
  ul
    li Первый пункт списка
    li Второй пункт списка
  p Абзац текста. Дальше идёт рыбный текст. Изменение глобальной стратегии сознательно индуцирует конвергентный нестандартный подход. До недавнего времени считалось, что провоцирование на рынке.

В браузере это превратится в чистый ХТМЛ:

<div>
  <h1>Заголовок первого уровня</h1>
  <p>Абзац текста. Дальше идёт рыбный текст. Изменение глобальной стратегии сознательно индуцирует конвергентный нестандартный подход. До недавнего времени считалось, что провоцирование на рынке.</p>
  <ul>
    <li>Первый пункт списка</li>
    <li>Второй пункт списка</li>
  <p>Абзац текста. Дальше идёт рыбный текст. Изменение глобальной стратегии сознательно индуцирует конвергентный нестандартный подход. До недавнего времени считалось, что провоцирование на рынке.</p>
</div>

В отличие от ХТМЛ, в Паге нет закрывающих тегов. Поэтому в коде жизненно важно следить за вложенностью элементов. В ХТМЛ вы можете написать вот так:

<div><h1>Заголовок на плашке</h1></div>

Благодаря закрывающим тегам браузер поймёт, что заголовок сидит внутри дива.

А в Паге надо будет написать вот так:

div
  h1 Заголовок второго уровня

Вложенность элементов определяется отступами от левого края. Отступ задаётся двумя пробелами. Очень удобно менять отступ сочетанием клавиш: увеличить отступ ⌘ + ] на Маке и Ctrl + ] на Винде, уменьшить ⌘ + [ на Маке и Ctrl + [ на Винде. Чтобы изменить отступ сразу у нескольких строк, выделите их и нажимайте те же сочетания клавиш:

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

Примеры модулей: +module, +cols, +rows, +caption, +image, +liftOut, +video, +fotorama. Примеры использования и синтаксис всех модулей будут описаны ниже.

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

Любые надбавки к модулю указываются внутри фигурно‑скобочной композиции ({ }), которая следует сразу за названием модуля. Модификатор mod задаёт простые свойства по принципу «есть — нет»: например рамка или отсутствие полей. Посмотрим, как это работает. Вот для начала у нас есть простой модуль:

+module
По умолчанию модуль прозрачный

Это просто пустой прямоугольник, который в соответствии со стилями сайта стремится занять всю доступную ему ширину и вытягивается по высоте своего содержимого. Это стандартное поведение модуля +modulе.

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

+module({mod:'bordered'})

Свойства перечисляются в произвольном порядке через пробел. Например, уменьшим ширину модуля до половины ширины текстовой колонки. Для этого добавим ещё модификатор halfTextWidth:

+module({mod: 'bordered halfTextWidth'})

А теперь мы хотим сделать три модуля с различными фиксированными пропорциями. Для этого необходимо назначить модулям атрибут fitToProportion с разными значениями:

+module({mod:'bordered halfTextWidth', fitToProportion: '12:1'})
+module({mod:'bordered halfTextWidth', fitToProportion: '3:1'})
+module({mod:'bordered halfTextWidth', fitToProportion: '1:1'})

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

Теперь мы хотим, чтобы эти модули стали красными. Для этого назначим им стили:

+module({mod:'bordered halfTextWidth', fitToProportion: '12:1', style:'background:red'})
+module({mod:'bordered halfTextWidth', fitToProportion: '3:1', style:'background:red'})
+module({mod:'bordered halfTextWidth', fitToProportion: '1:1', style:'background:red'})

В стилях используется чистый и всем известный ЦСС: background, width, height, margin, padding, font‑family, color и так далее. Но мы рекомендуем не злоупотреблять использованием стилей, потому что это ведёт к нестандартному поведению элементов и мусорному неразборчивому коду. Стили нужно и можно использовать, когда для модуля нет подходящего стандартного модификатора. В идеале любая страница должна быть собрана без использования стилей.

Есть элементы, которые не являются модулями, и в силу особенностей Паге им нельзя назначить модификаторы. Например, заголовок первого уровня h1, заголовок второго уровня h2 и абзац p. Для изменения их внешнего вида и поведения используются стандартные классы. Стандартные классы будут описаны ниже, а всё, что нужно знать сейчас, — классы назначаются вот так:

p.xxxl Огромный заголовок первого уровня

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

Ошибки в коде

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

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

Комментарии в коде

Комментарии добавляются двумя слешами с дефисом //‑ или сочетанием клавиш Ctrl + /.

//- Комментарий в коде

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

Обёртка и стили страницы

В начале кода любой страницы будет жить несколько строк специальных обязательных заклинаний:

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

  • block vars — обёртка для всякой метаинформации:

    • title — заголовок страницы, а также заголовок для соцсетей и поисковиков. Если нужны отдельные заголовки для соцсетей и поисковиков, используйте ogTitle и SEOTitle. Если title не указан, в качестве него используется содержимое <h1> со страницы.

    • ogTitle — заголовок для соцсетей.

    • SEOTitle — заголовок для поисковиков.

    • description — описание страницы для соцсетей и поисковиков. Если нужны отдельные описания, используйте ogDescription и SEODescription. Если description не указан, в качестве него используется содержимое <h1> или первый абзац лида +lead со страницы.

    • ogDescription — описание страницы для соцсетей.

    • SEODescription — описание страницы для поисковиков.

    • ogImage — ссылка на превью для соцсетей. ogImage лучше не указывать, а просто загружать на страницу файлы с такими названиями: _cover.jpg или _cover.png. Сайт автоматически будет отдавать их соцсетям, как обложки страниц.

  • block content — обёртка для содержания страницы, в ней живут стили и вёрстка.

  • block sсripts — обёртка для кастомных скриптов.

  • +webpage — контейнер страницы ниже шапки и выше подвала. У модуля есть специфичные для него атрибуты:

    • type — вид страницы, влияет на поведение элементов.

    • categories, description и product — рубрика, описание проекта и его принадлежность к тому или иному продукту в бюрошном портфолио.

По умолчанию страница красится в фирменные цвета бюро: белый фон, красные акценты, синие ссылки, чёрный текст. Если нужно, эти цвета можно переопределить для каждой отдельной страницы. Для этого укажите стили внутри block content:

block content
  style.
    :root {
      --backgroundColor: #000;  /* Фон */
      --textColor: #fff; /* Текст */
      --linkColor: #FFFF00; /* Ссылки */
      --linkUnderlineColor: rgba(255, 255, 0, .3);/* Подчёркивание ссылок */
      --keyColor: #00ffff; /* Акценты */
      --keyUnderlineColor: rgba(0, 255, 255, .3); /* Подчёркивание акцентных ссылок */
    }

  +webpage
Эта страница со стилями из кода выше

Десктопная и мобильная версии

Всё, что вы сверстаете, будет видно на устройстве любой ширины. Если нужно, чтобы что‑то отображалось только на телефоне или только на широких экранах, используйте атрибут device со значениями desktop, laptop и mobile:

  • desktop — показывает что‑то при ширине от 1400 пк,

  • laptop — от 961 до 1399 пк,

  • mobile — меньше 960 пк.

Модуль будет виден только при ширине от 1400 пк:

+module({device: 'desktop'})
  +image({src: 'image.png'})

Модуль будет виден только при ширине меньше 960 пк:

+module({device: 'mobile'})
  +image({src: 'image.png'})
'mobile.png' not found

Можно применить два значения одновременно. Например, desktop и laptop, тогда модуль будет виден при ширине 961 пк и больше:

+module({device: 'desktop laptop'})
  +image({src: 'image.png'})

Если хотите, чтобы модуль был виден везде, не используйте device.

Элементы

+module

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

По умолчанию модули встают друг под другом. То есть следующий код будет выглядеть как на картинке:

+module({mod:'bordered'}) 
+module({mod:'bordered'})

Модификаторы

Все модификаторы базового модуля +module можно применять в любом специальном, например +cols или +caption, но не наоборот.

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

Все модификаторы базового модуля +module можно применять в любом специальном, например +cols или +caption, но не наоборот.

textWidth — уменьшает ширину модуля до ширины текстовой колонки, 11 колонок сетки.

lessThanTextWidth — уменьшает ширину модуля до 8 колонок сетки.

halfTextWidth — уменьшает ширину модуля до половины ширины текстовой колонки, 5 колонок сетки.

В коде:

+module({mod:'textWidth', style:'height:50px; background:red'})
+module({mod:'lessThanTextWidth', style:'height:50px; background:red'})
+module({mod:'halfTextWidth', style:'height:50px; background:red'})

fitToProportion задаёт пропорции модуля. Высота модуля вычисляется пропорционально его ширине.

+module({fitToProportion: '3:1', style:'background-color:yellow;'})
fitToProportion со значением 3:1 задаёт пропорции модуля в соотношении 3 к 1

mod: 'boxed' ставит модуль на серую плашку с следующими отступами: по бокам — 9 пк, сверху — 36 пк и снизу — 72 пк.

p Этот вариант — большая удача:
+module({mod: 'boxed textWidth'})
  +cols
    +module
      p Продукт как можно раньше начинает работать, выполнять своё полезное действие, зарабатывать деньги, расширять аудиторию.
      p Чем больше функций, тем больше их пересечений, а значит мест для ошибки. Поэтому отказ от функции помогает уменьшить количество узких мест и повысить качество первой версии.
      p Открытый вовремя продукт помогает быстрее узнать правду о продукте: изучить мнение пользователей и проверить гипотезы. Возможно, убранная функция никогда и не понадобится, и силы будет лучше потратить на другую.
    +module
      p Новый продукт с небольшим числом функций легче объяснить пользователям. Только мы знаем о том, что часть идей не реализовали. Пользователям они бы только добавили сложностей.
      +liftOut Когда отложенная функция добавится во второй версии, будет кого ей порадовать. Кроме того, новая функция — это информационный повод, лишняя причина рассказать о продукте.


bleedBackground:'sides' растягивает модуль на всю ширину браузера и выравнивает содержимое по сетке сайта.

+module({mod: 'boxed noMargins', bleedBackground: 'sides', style:'background-color:#FFFF00;'})
  h2 Модуль на всю ширину экрана
  p Абзац текста. Дальше идёт рыбный текст. Изменение глобальной стратегии сознательно индуцирует конвергентный нестандартный подход. До недавнего времени считалось, что провоцирование на рынке.

bleed:'sides' растягивает модуль на всю ширину экрана со всем его содержимым. Вот так будет выглядеть модуль с текстом на всю ширину экрана:

+module({bleed: 'sides', style:'background-color:#99FFFF;'})
  h2 Модуль на всю ширину экрана
  p Абзац текста. Дальше идёт рыбный текст. Изменение глобальной стратегии сознательно индуцирует конвергентный нестандартный подход. До недавнего времени считалось, что провоцирование на рынке.
Текст внутри модуля прилип сверху, снизу и слева

Скорее всего, текст на всю ширину вам ставить не придётся, а картинку — да. Вот как это будет выглядеть:

p В 2021 году «Деликат» откроет 30 новых магазинов в миниформате. Чтобы покупатели увидели, что это тот самый «Деликат», но маленький, в бюро для маленьких магазинов придумали собственный логотип.

+module({bleed: 'sides'})
  +image({src: '/projects/code-guide/files/delikat-mini.jpg'})
Картинка на всю ширину экрана

mod: 'maxWidthOnDesktop' ограничивает максимальную ширину модуля шириной сайта с полями.

p В 2021 году «Деликат» откроет 30 новых магазинов в миниформате. Чтобы покупатели увидели, что это тот самый «Деликат», но маленький, в бюро для маленьких магазинов придумали собственный логотип.

+module({mod: 'maxWidthOnDesktop', bleed: 'sides'})
  +image({src: 'delikat-mini.jpg'})
Максимальная ширина картинки равна максимальной ширине сайта с полями

Чтобы лучше понять, как boxed, bleedBackground, bleed и maxWidthOnDesktop работают вместе друг с другом, посмотрите картинку:

Кейс

Этаж на всю ширину
p Кажется очевидным, но обычно люди не собирают данные. Просто приходят к боссу, мол, «дайте нам больше людей». А сколько именно? Каких? К чему это приведёт? Почему нужно выделять дополнительные двести‑триста тысяч рублей, если и так всё нормально работает?

+module({mod: 'boxed', bleedBackground: 'sides', style:'background-color:#FFFF99;'})
  h2 Опасность
  p Может оказаться, что скорость для компании не в приоритете и руководителю нормально, что задачи висят подолгу. Или что руководитель считает, что редакторы недогружены. Может быть, он не в курсе, как долго пишутся тексты и какими жертвами. Или босс уверен, что если вы ни о чём не говорите, то у вас всё в порядке.

p У меня был случай — он не связан напрямую с вашим вопросом, но по сути близок, — мы делали проект с клиентом. Мне казалось, что проект подыхает от безумного количества правок. Я был уверен, что их там сотни, и я просто из‑под них не вылезу. Я позвал на помощь директора со стороны нашего предприятия, мол, помоги вразумить клиента. Он пришёл, очень аккуратно поговорил с клиентом, объяснил серьёзность ситуации. И дальше передал слово мне, мол, покажи, какие страшные у тебя замечания.

Кажется очевидным, но обычно люди не собирают данные. Просто приходят к боссу, мол, «дайте нам больше людей». А сколько именно? Каких? К чему это приведёт? Почему нужно выделять дополнительные двести‑триста тысяч рублей, если и так всё нормально работает?

Опасность

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

У меня был случай — он не связан напрямую с вашим вопросом, но по сути близок, — мы делали проект с клиентом. Мне казалось, что проект подыхает от безумного количества правок. Я был уверен, что их там сотни, и я просто из‑под них не вылезу. Я позвал на помощь директора со стороны нашего предприятия, мол, помоги вразумить клиента. Он пришёл, очень аккуратно поговорил с клиентом, объяснил серьёзность ситуации. И дальше передал слово мне, мол, покажи, какие страшные у тебя замечания.

noMargins удаляет внешние отступы:

+module({mod: 'boxed noMargins', bleedBackground: 'sides', style:'background-color:#FFFF99;'})
  h2 Модуль на всю ширину экрана
  p Абзац текста. Дальше идёт рыбный текст. Изменение глобальной стратегии сознательно индуцирует конвергентный нестандартный подход. До недавнего времени считалось, что провоцирование на рынке.

+module({mod: 'boxed noMargins', bleedBackground: 'sides', style:'background-color:#99FFFF;'})
  h2 Модуль на всю ширину экрана
  p Абзац текста. Дальше идёт рыбный текст. Изменение глобальной стратегии сознательно индуцирует конвергентный нестандартный подход. До недавнего времени считалось, что провоцирование на рынке.
У модулей нет внешних отступов и они склеились

layoutLayer добавляет вокруг модуля стандартные межэтажные расстояния в 72 пк.

p Пример использования модификатора layoutLayer, который добавляет вокруг модуля стандартные межэтажные расстояния в 72 пк.
+module({ mod: 'layoutLayer' })
  +image({src: 'screen-geopotential.jpg'})
  +caption Верхний и нижний отступы равны 72 пк
p Отступ до этого абзаца — 72 пк. Дальше идёт рыбный текст. Изменение глобальной стратегии сознательно индуцирует конвергентный нестандартный подход. До недавнего времени считалось, что провоцирование на рынке.

href делает ссылкой любой модуль:

+module({href: 'https://bureau.ru/projects/gismeteo/'})
  p Веб-система визуализации и обработки метеорологических данных на карте в реальном времени

positionOrigin позволяет дочерним элементам модуля, которые позиционируются абсолютно, позиционироваться относительно модуля. По сути, в ЦСС‑стилях модуля появляется строчка position:relative.

top, bottom, left, right — сдвигают модуль в соответствующем направлении на определённое количество пикселей или %. При использовании любого из этих модификаторов модуль будет позиционироваться абсолютно.

/* Пример. Для меню справа на этой странице сначала добавлен родительский модуль с positionOrigin, а затем дочерний спозиционирован абсолютно при помощи left и bottom. */

+module({mod:'positionOrigin'})
  +module({top:'0', bottom:'0'})
    div(style="position: sticky; top:18px")        
      +caption <a href="#basics">Основы</a>
      +caption <a href="#elements">Элементы</a>
      +caption <a href="#mixins">Миксины</a>
      +caption <a href="#animation">Анимация</a>

animation — задаёт анимацию при прокрутке. Про анимацию см. раздел Анимация.

animationBase — назначает верхний край модуля точкой отсчёта анимации для всех дочерних элементов модуля, у которых есть анимация. По умолчанию точкой отсчёта анимации при прокрутке является начало страницы.

+rows

Модуль, дочерние элементы которого встают строго по вертикали на одинаковых расстояниях друг от друга. Стандартное расстояние — 72 пк.

+rows
  +module
    p Андрей
  +module
    p Костя
Стандартный отступ между строками — 72 пк

gutter меняет отступы между строками.

+rows({gutter:'36px'})
  +module
    p Андрей
  +module
    p Костя
Отступ между строками уменьшился до 36 пк

Лучше указывать значения не в пикселях, а переменными paragraph, p и caption.

paragraph и p делают отступ равным стандартному отступу между абзацами, а caption — делает отступ равным отступу до подписи:

+rows
  +rows({gutter:'p'})
    p Первая строка. Стандартные отступы между абзацами.
    p Вторая строка со стандартным отступом между абзацами.

  +rows({gutter:'caption'})
    p Первая строка. Отступы до подписи.
    p Вторая строка с отступом до подписи.

+cols

Модуль, дочерние элементы которого выравниваются строго по горизонтали на одинаковых расстояниях друг от друга. Стандартное расстояние — 18 пк.

По умолчанию колс занимает всю доступную ему ширину, а его дочерние колонки делятся на равные части. Ширина колонок одинакова в независимости от того, что внутри этих колонок находится.

Кейс

Две картинки в колонках
+cols
  +image({src: 'logo1.jpg'})
  +image({src: 'logo2.jpg'})
Два абзаца
+cols
  +module
    p Это абзац рыбного текста, чтобы показать текст в две колонки. Такое понимание ситуации восходит к Эл Райс. При этом ретроконверсия национального наследия тормозит социометрическое формирование имиджа. Построение бренда, вопреки мнению П. Друкера, недостижимо.
  +module
    p Это абзац рыбного текста, чтобы показать текст в две колонки. Чтобы текст был энергичным, он должен быть ёмким. В предложении не должно быть ненужных слов, в абзаце — ненужных предложений, так же, как и на картине не должно быть ненужных штрихов.

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

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

По умолчанию все колонки в мобильной версии перестраиваются в строки с вертикальными отступами 36 пк:

+cols
  +module
    h3 Нужно
    p 13.3.1. Вывод необязательных данных таблицы за её пределы
    p 13.3.2. Распределение подлежащих между боковиком, головкой и прографкой
    p 13.3.3. Объединение одинаковых таблиц, стоящих рядом
    p 13.3.4. Устранение лишних граф
    p 13.3.5. Сдваивание, страивание и т. д. таблиц
    p 13.3.6. «Перевёртывание» таблиц
    p 13.3.7. Деление таблицы на несколько самостоятельных
    p 13.3.8. Объединение граф

  +module
    h3 Обязательно
    p 13.7.1. Устранение повтора тематического заголовка
    p 13.7.2. Вынос повторяющихся элементов в верхний ярус или в тематический заголовок таблицы
    p 13.7.3. Устранение необязательных ярусов
    p 13.7.4. Перенос части многословных заголовков граф в тематический заголовок, основной текст или подтабличное примечание
    p 13.7.5. Устранение лишних слов
    p 13.7.6. Перевод числительных в цифровую или смешанную форму
    p 13.7.7. Замена словесных заголовков граф символическими буквенными обозначениями
    p 13.7.8. Объединение двух граф в одну для нормального расположения заголовков граф

Кейс

Таблица
+cols
  +module
    h3 Нельзя
    p Сайт о пользе вегетарианства для здоровья
    p Сервис подбора гомеопатического средства
    p Биохакинг
    p Как родить дома

  +module
    h3 Можно
    p Сайт рецептов вегетарианских блюд
    p Сайт о бесполезности гомеопатии
    p Лайфхаки
    p Гимнастика после родов (с гинекологом)

Нельзя

Сайт о пользе вегетарианства для здоровья

Сервис подбора гомеопатического средства

Биохакинг

Как родить дома

Можно

Сайт рецептов вегетарианских блюд

Сайт о бесполезности гомеопатии

Лайфхаки

Гимнастика после родов (с гинекологом)

Таблица с одинаковой высотой строк
+cols
  +module
    h3 Плотоядные
    p Нет пор на коже, тело охлаждается через язык
  +module
    h3 Человек
    p Много пор на коже, потоотделение
+cols
    p Острые резцы для разрывания мяса
    p Тупые резцы
+cols
    p Неразвитые слюн&#173;ные железы для пред&#173;вари&#173;тель&#173;ного пере&#173;вари&#173;вания
    p Хорошо развитые слюн&#173;ные железы для пред&#173;вари&#173;тель&#173;ного пере&#173;вари&#173;вания
+cols
    p Кислая слюна без птиалина
    p Щелочная слюна с птиалином для переваривания злаков и фруктов
+cols
    p Нет плоских задних зубов
    p Есть плоские задние зубы для пережевывания
+cols
    p Сильная соляная кислота в желудке для переваривания мяса животных
    p Соляная кислота в желудке в 10 раз слабее, чем у плотоядных
+cols
    p Длина желудочно-кишечного тракта в 3 раза больше длины тела для быстрого вывода гниющего мяса
    p Длина кишечника в 6 раз больше длины тела

Плотоядные

Нет пор на коже, тело охлаждается через язык

Человек

Много пор на коже, потоотделение

Острые резцы для разрывания мяса

Тупые резцы

Неразвитые слюн­ные железы для пред­вари­тель­ного пере­вари­вания

Хорошо развитые слюн­ные железы для пред­вари­тель­ного пере­вари­вания

Кислая слюна без птиалина

Щелочная слюна с птиалином для переваривания злаков и фруктов

Нет плоских задних зубов

Есть плоские задние зубы для пере­же­вы­ва­ния

Сильная соляная кислота в желудке для переваривания мяса животных

Соляная кислота в желудке в 10 раз слабее, чем у плотоядных

Длина желу­доч­но‑кишеч­ного тракта в 3 раза боль­ше длины тела для быстро­го вывода гниющего мяса

Длина кишечника в 6 раз больше длины тела

divisionProportions делит ширину колонок в заданных пропорциях.

h2 Интерактивная книга для компании
+cols({divisionProportions: '12:4'})
  +module
    p «Книга кассира» создана на движке Издательства бюро. Интерактивный формат позволяет принципиально по‑новому взглянуть на подачу теории и сделать её более наглядной и запоминающейся. Благодаря закладкам и поиску книгой удобно пользоваться как справочником.
    p Сотрудники компании получают индивидуальный доступ к книге по электронной почте. Доступом книге управляет ответственный менеджер компании. Для чтения нужен компьютер, планшет или телефон с интернетом и любым современным браузером.
  +liftOut В справочнике разобраны 32 ситуации, с которыми может столкнуться кассир.
divisionProportions: '12:4' делит колонки в соотношении 12 к 4

divisionPortion — модификатор для одной колонки. Если нужно, чтобы одна колонка была шире остальных, то можно только ей и назначить нужную долю, а остальные подстроятся:

+cols
  +module({divisionPortion: 3})
    h3 Этап
    p 1. Структура номера (cостав книжек, положение главных статей, основные рубрики, новые одностраничные рубрики, предварительный план рекламы)
  +module
    h3 Срок, раб. дней
    p 5 дней, 10—14 мар
  +module
    h3 Стоимость, ₽
    p 10 000
+cols
  +module({divisionPortion: 3})
    p 2. Общее визуальное решение журнала, поиск стиля иллюстраций нового макета, согласование структуры номера
  p 5 дней, 17—21 мар
  p 20 000
+cols
  +module({divisionPortion: 3})
    p 3. Одностраничные текстовые рубрики, согласование ОВР
  p 5 дней, 24—28 мар
  p 30 000
+cols
  +module({divisionPortion: 3})
    p 4. Рубрики «Номер одним взглядом» и «Оформление документа», тестовая итерация с агентством иллюстраторов, согласование одностраничных текстовых рубрик
  p 5 дней, 31 мар — 4 апр
  p 40 0001 мар — 4 апр
  p 40 000
Первая колонка заняла большую ширину, а остальные распределились равномерно

noTransposeOnMobile запрещает переносить колонки друг под друга в мобильной версии:

+rows
  +cols({mod:'noTransposeOnMobile'})
    +module
      +image({ src: 'rocket1.png' })
      +caption Прошёл 15 минут
    +module
      +image({ src: 'rocket2.png' })
      +caption Прошёл 30 минут
    +module
      +image({ src: 'rocket3.png' })
      +caption Прошёл 45 минут
  +cols({mod:'noTransposeOnMobile'})
    +module
      +image({ src: 'Star1.png' })
      +caption Сделал 2000 шагов
    +module
      +image({ src: 'Star2.png' })
      +caption Сделал 10000 шагов
    +module
      +image({ src: 'Star3.png' })
      +caption Сделал 15000 шагов
  +cols({mod:'noTransposeOnMobile'})
    +module
      +image({ src: 'Medal1.png' })
      +caption Проходил 3 часа
    +module
      +image({ src: 'Medal2.png' })
      +caption Проходил 6 часов
    +module
      +image({ src: 'Medal3.png' })
      +caption Проходил 12 часов

+image

Модуль изображения. По умолчанию занимает всю доступную ширину и принимает пропорции назначенного ему изображения:

+image({src: 'screen-geopotential.jpg'})

bordered задаёт стандартную тонкую рамку:

+image({src: 'tram.jpg', mod: 'bordered'})

Кейс

Картинки в две колонки

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

+cols
  +module
    +image({src: 'picture_1.jpg'})
  +module
    +image({src: 'picture_2.jpg'})

Технически +image такой же модуль как и обычный. В очень многих простых ситуациях его не нужно ничем специально дополнять. Правильно сделать так:

+cols
  +image({src: 'picture_1.jpg'})
  +image({src: 'picture_2.jpg'})

А вот если вам нужно сделать две картинки с подписями, то без обёртки вам уже не обойтись:

+cols
  +module
    +image({src: '/projects/code-guide/files/picture_1.jpg'})
    +caption
  +module
    +image({src: '/projects/code-guide/files/picture_2.jpg'})
    +caption
Непревзойдённый оригинал
Жалкая подделка
Картинка в картинке

Так как технически +image это тоже модуль только с картинкой, можно в него встраивать другие модули. Например, расположить ещё одну картинку сверху в указанном месте:

+image({src: '/projects/code-guide/files/screen-geopotential.jpg'})
  +image({src: '/projects/code-guide/files/screen-geopotential-2.png', top:'9px', right:'7px', style:'width:200px'})

Повесить беджик:

+image({src: 'photo.jpg'})
  +image({src: 'label.png', bottom:'-6%', left:'-5%', style:'width:22%'})

+caption

Подпись к изображению или другому элементу.

+image({src: 'screen-geopotential.jpg'})
+caption Веб‑система Гисметео
Веб‑система Гисметео

Кейс

Одна ссылка у картинки и у подписи

Если у вас есть картинка, которая является ссылкой и у неё есть подпись, у которой та же ссылка, навесьте на них класс doubleHover, чтобы при наведении на картинку ссылка в подписи подсвечивалась:

+image({src: 'screen-geopotential.jpg', href:'/projects/gismeteo/', class:'doubleHover'})
+caption <a href="/projects/gismeteo/" class="doubleHover">Веб‑система Гисметео</a>

+browser

Оборачивает изображение в окно браузера.

+browserScreenshot
  +image({src: 'screenshot.png'})

+iphoneScreenshot

Оборачивает изображение в пятый айфон.

+iphoneScreenshot({src: 'screenshot_pencil-mobile.png'})

+liftOut

Вынос. По умолчанию красится в keyColor:

p Выстраивать конфликты в интервью интересно, потому что есть настоящий, живой герой со своими суждениями, мотивами, оценками. Раскрыть личность героя помогают три вида конфликта: внутренний, межличностный, внешний.

+liftOut Конфликт — это центр и движущая сила истории. На конфликте завязаны действия героев, к нему приковано внимание читателя.

p Допустим, наш герой — женщина по имени Анна. У неё своя компания, штат подчинённых, известность, репутация и хорошо налаженный прибыльный бизнес. Читатель заскучает, если это будет интервью о том, как Анна планомерно выстраивала бизнес, в каких таск‑менеджерах вела работу и как постепенно пришла к успеху. Зато, если построить интервью на конфликтах, появится драма.

L делает вынос крупнее и красит его в textColor:

p Выстраивать конфликты в интервью интересно, потому что есть настоящий, живой герой со своими суждениями, мотивами, оценками. Раскрыть личность героя помогают три вида конфликта: внутренний, межличностный, внешний.

+liftOut({mod:'L'}) Конфликт — это центр и движущая сила истории. На конфликте завязаны действия героев, к нему приковано внимание читателя.

p Допустим, наш герой — женщина по имени Анна. У неё своя компания, штат подчинённых, известность, репутация и хорошо налаженный прибыльный бизнес. Читатель заскучает, если это будет интервью о том, как Анна планомерно выстраивала бизнес, в каких таск‑менеджерах вела работу и как постепенно пришла к успеху. Зато, если построить интервью на конфликтах, появится драма.

+sidenote

Подпись, которая встаёт справа от абзаца. Для этого в коде +sidenote необходимо поставить перед родительским абзацем:

+sidenote «Джипег» — картинка, нарисованная на скорую руку

p Абзац, напротив которого появится заметка. Дальше идёт рыбный текст. Типографы веками искали закономерности и связи между элементами набора.         

Кейс

Вынос справа от абзацев
+sidenote
  +liftOut
    p <i>Элемент дизайна</i> проходит через стадии:
    p <i>эскиз</i> — картинка, описывающая идею;
    p <i>макет</i> — конечный файл для типографии, <span class="smallcapitals">ХТМЛ</span>-код, чертёж для производства;
    p <i>реализация</i> — воплощение в жизнь продукта, разработка и запуск сайта, печать книжки, производство и монтаж вывески.

p Элемент дизайна — дизайн отдельного объекта, указанного в Задании, например: отдельной страницы сайта, экрана пользовательского интерфейса, рекламного банера, логотипа и элементов фирменного стиля, слайдов электронной презентации, бумажного буклета или флаера, указателя навигации в общественном месте, рекламной полосы в журнале.
p Эскиз элемента дизайна — упрощённое графическое изображение Элемента дизайна, демонстрирующее его идею, сценарий использования, проект визуального решения, текстового наполнения либо отличительные особенности внешней формы.
p Макет элемента дизайна — электронный файл в формате, предусмотренном Договором, содержащий точное описание внешнего вида элемента, пригодный для воспроизведения на целевом носителе с точностью и при условиях, предусмотренных Заданием. Примеры файлов макетов в зависимости от типа элемента: файлы гипертекста <span class="smallcapitals">HTML</span>, печатные файлы <span class="smallcapitals">EPS</span>, файлы изображений <span class="smallcapitals">PNG</span>, презентация <span class="smallcapitals">PPT</span> и любые другие форматы в соответствии с Заданием.
p Реализация элемента дизайна — программирование, обработка текстовых, графических и иных Информационных материалов, предоставляемых Клиентом или специально создаваемых Бюро, наполнение Информационными материалами, тестирование, печать в типографии, производство вывесок и указателей или другие работы, необходимые для подготовки к эксплуатации Элемента дизайна. В соответствии с Заданием Реализацию элемента дизайна выполняет Бюро, Клиент или третье лицо.

footnote ставит заметку после абзаца, а не справа от него. Пока используется для постскриптумов:

p Придумывать конфликт в инструкциях необязательно, это выбор автора. Можно и просто начать статью словами «Мы подготовили обзор новых способов наладить работу бухгалтерии». Статья потеряет в драме, но не в содержании. В то же время, если во введении есть конфликт, он создаёт для читателя дополнительную мотивацию прочитать статью и может вовлечь даже тех, кто изначально не собирался её читать.

+sidenote({mod: 'footnote'}) P. S. Это был воскресный совет об информационном стиле и редактуре текста. <a href="/bb/soviet/ask/">Присылайте вопросы</a>

+rule

Крупный курсивный текст, выровненный по центру текстовой колонки.

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

+rule План «Б» — это путь к провалу

p Давайте на примере. Клиент хочет фирстиль и сайт для своей компании по торговле украшениями. Вы начинаете составлять детальное коммерческое предложение — всё «под ключ» за пятьсот тысяч рублей. Это ваш план «А».

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

+example

Пример. По умолчанию текст красится в keyColor. Чаще всего используется в советах.

p Теперь синтаксис. В тексте есть подлежащие и сказуемые вроде «проблема», «незнание», «отсутствие». Вместо них должны появиться люди, которые будут совершать действия: 

+example Когда сотрудник только устраивается на работу, он может не знать принципов работы компании, в том числе в базовых организационно-бытовых вопросах. Когда коллеги знают такие вещи, а новый сотрудник нет, он чувствует себя беспомощным, а мотивация снижается.
Пример с несколькими абзацами
p Просто прочитайте вслух и послушайте, насколько естественно звучит текст с «я» и без «я». Если ломается язык, сделайте так, чтобы не ломался. Дело может быть не только в «я», но и в других местоимениях и словах. 

+example
  p Пишу, сокращаю статьи, пресс-релизы, рекламу, промостраницы, тексты для «Инстаграма», в блоги, для изданий, курсовые, дипломные, свадьбы, юбилеи, похороны. Помогу за неделю.
  p Я работаю с текстами в разных жанрах: статьи, пресс-релизы, реклама и промостраницы, тексты для «Инстаграма» и блога. Ещё пишу курсовые и дипломные, свадебные тосты, речи для юбилеев и похорон. Обычно делаю текст за неделю.

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

Пишу, сокращаю статьи, пресс‑релизы, рекламу, промостраницы, тексты для «Инстаграма», в блоги, для изданий, курсовые, дипломные, свадьбы, юбилеи, похороны. Помогу за неделю.

Я работаю с текстами в разных жанрах: статьи, пресс‑релизы, реклама и промостраницы, тексты для «Инстаграма» и блога. Ещё пишу курсовые и дипломные, свадебные тосты, речи для юбилеев и похорон. Обычно делаю текст за неделю.

Таблица‑пример
+example
  +cols
    +module
      h3 Нельзя
      p Сайт о пользе вегетарианства для здоровья
      p Сервис подбора гомеопатического средства
      p Биохакинг
      p Как родить дома
    +module
      h3 Можно
      p Сайт рецептов вегетарианских блюд
      p Сайт о бесполезности гомеопатии
      p Лайфхаки
      p Послеродовая гимнастика (с консультантом-гинекологом)

Нельзя

Сайт о пользе вегетарианства для здоровья

Сервис подбора гомеопатического средства

Биохакинг

Как родить дома

Можно

Сайт рецептов вегетарианских блюд

Сайт о бесполезности гомеопатии

Лайфхаки

Послеродовая гимнастика (с консультантом‑гинекологом)

+linkWithArrow

Ссылка со стрелочкой.

+linkWithArrow({text: 'Все курсы бюро для компании', href: '/educenter/business/'})

h2 делает ссылку заголовком второго уровня:

+linkWithArrow({mod:'h2', text: 'Лекции', href: '/lectures/'})

+factoid

Фактоид. Состоит из числа и подписи к нему.

+factoid({ number: '1 400' }) engineers split up into 24 teams

highlighted красит фактоид в ключевой цвет, sans меняет число на гротеск. Вот фактоиды с этими модификаторами:

+factoid({ number: '1 400' }) engineers split up into 24 teams
+factoid({ mod: 'highlighted', number: '973' }) prototypes of new 1UZ-FE engine
+factoid({ mod: 'sans highlighted', number: '973' }) prototypes of new 1UZ-FE engine

Число в фактоиде бывает нескольких размеров. Размеры назначаются при помощи модификаторов xs, s, m, l, xl, xxl, xxxxl. Если не задать модификатор, то размер фактоида будет соответствовать m. Размера xxxl пока не существует. Примеры фактоидов разных размеров.

+price

Ценник. Всегда состоит из числа и единицы измерения.

+image({src: '/projects/code-guide/files/book-ui-mobile.png'})
h3 Самое полное и современное руководство по интерфейсу 

+price({amount: '1490', units: '₽'})

+linkWithArrow({text: 'Купить книгу', href: 'https://bureau.ru/projects/book-ui/'})

+code

Пример кода.

+code
  :escape
    p Абзац текста

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

p <span class="code">divisionPortion</span> — модификатор для одной колонки. Если нужно, чтобы одна колонка была шире остальных, то можно только ей и назначить нужную долю, а остальные подстроятся:

+code
  :escape
    +cols
      +module({divisionPortion: 3})
        h3 Этап
        p 1. Структура номера (cостав книжек, положение главных статей, основные рубрики, новые одностраничные рубрики, предварительный план рекламы)
      +module
        h3 Срок, раб. дней
        p 5 дней, 10—14 мар
      +module
        h3 Стоимость, ₽
        p 10 000
    +cols
      +module({divisionPortion: 3})
        p 2. Общее визуальное решение журнала
        p.margin-list Поиск стиля иллюстраций нового макета
        p.margin-list Согласование структуры номера
      p 5 дней, 17—21 мар
      p 20 000

preWrap включает перенос строк, и горизонтальная прокрутка не появится:

p <span class="code">divisionPortion</span> — модификатор для одной колонки. Если нужно, чтобы одна колонка была шире остальных, то можно только ей и назначить нужную долю, а остальные подстроятся:

+code({mod: 'preWrap'})
  :escape
    +cols
      +module({divisionPortion: 3})
        h3 Этап
        p 1. Структура номера (cостав книжек, положение главных статей, основные рубрики, новые одностраничные рубрики, предварительный план рекламы)
      +module
        h3 Срок, раб. дней
        p 5 дней, 10—14 мар
      +module
        h3 Стоимость, ₽
        p 10 000
    +cols
      +module({divisionPortion: 3})
        p 2. Общее визуальное решение журнала
        p.margin-list Поиск стиля иллюстраций нового макета
        p.margin-list Согласование структуры номера
      p 5 дней, 17—21 мар
      p 20 000

wide убирает ограничение в ширину текстовой колонки:

p <span class="code">divisionPortion</span> — модификатор для одной колонки. Если нужно, чтобы одна колонка была шире остальных, то можно только ей и назначить нужную долю, а остальные подстроятся:

+code({mod: 'wide'})
  :escape
    +cols
      +module({divisionPortion: 3})
        h3 Этап
        p 1. Структура номера (cостав книжек, положение главных статей, основные рубрики, новые одностраничные рубрики, предварительный план рекламы)
      +module
        h3 Срок, раб. дней
        p 5 дней, 10—14 мар
      +module
        h3 Стоимость, ₽
        p 10 000
    +cols
      +module({divisionPortion: 3})
        p 2. Общее визуальное решение журнала
        p.margin-list Поиск стиля иллюстраций нового макета
        p.margin-list Согласование структуры номера
      p 5 дней, 17—21 мар
      p 20 000

+timer

Таймер обратного отсчета. Всегда имеет дату окончания.

+timer({till: '22 авг'})

+video

Модуль видео. По умолчанию занимает всю доступную ширину и принимает пропорции назначенного ему видео:

+video({src: 'steve-vision.mp4', cover: 'steve-vision.jpg'})

muted отключает звук:

+video({mod:'muted', src: 'steve-vision.mp4', cover: 'steve-vision.jpg'})

autoplay автоматически начинает проигрывать видео. Работает только вместе с muted:

+video({mod:'autoplay muted', src: 'steve-vision.mp4', cover: 'steve-vision.jpg'})

loop проигрывает видео по кругу:

+video({mod:'loop', src: 'steve-vision.mp4', cover: 'steve-vision.jpg'})

noControls отключает панель управления:

+video({mod:'noControls', src: 'steve-vision.mp4', cover: 'steve-vision.jpg'})

Кейс

Зацикленное видео
+video({mod:'autoplay loop noControls muted', src: 'steve-vision.mp4', cover: 'steve-vision.jpg'})

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

+video({mod:'playInView', src: 'steve-vision.mp4', cover: 'steve-vision.jpg'})

+youtubeVideo

Видео из Ютуба.

+youtubeVideo({src: 'https://www.youtube.com/watch?v=h_D3VFfhvs4'})
'_cover.jpg' not found

+vimeoVideo

Видео из Вимео.

+vimeoVideo({src: 'https://vimeo.com/293288488'})
'_cover.jpg' not found

p

Абзац текста.

p Абзац текста.

h1

Заголовок первого уровня.

h1 Заголовок первого уровня.

Имеет несколько размеров, которые назначаются при помощи классов m, l, xl, xxl, xxxl, xxxxl:

h1.m h1.m 36 пк
h1.l h1.l 43 пк 
h1.xl h1.xl 54 пк
h1.xxl h1.xxl 65 пк
h1.xxxl h1.xxxl 72 пк
h1.xxxxl h1.xxxl 85 пк

h1.m 36 пк

h1.l 43 пк

h1.xl 54 пк

h1.xxl 65 пк

h1.xxxl 72 пк

h1.xxxxl 85 пк

h2

Заголовок второго уровня.

h2 Заголовок второго уровня.

h3

Заголовок третьего уровня.

h3 Заголовок третьего уровня.

h4

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

p <h4>Выделение полужирным начертанием.</h4> Выделение полужирным начертанием используется для того, чтобы обозначить основную тему какого-либо фрагмента текста. По сути, это равносильно использованию еще одного заголовка.

+product

Переключалка между проектами для одного клиента в карточках проектов или видами курсов на странице курсов.

+product({name: 'Деликат'})
  +productMenuItem({link: '/projects/delikat-cashier-guidelines/'}) Стандарты кассира
  +productMenuItem({link: '/projects/delikat-cashier-book/'}) Книга кассира
  +productMenuItem({link: '/projects/delikat-cashier-training'}) Обучение кассира
  +productMenuItem({link: '/projects/delikat-identity/'}) Логотип и фирстиль
  +productMenuItem({isActive: true, link: '/projects/delikat-merchandising/'}) Мерчендайзинг
  +productMenuItem({link: '/projects/delikat-mini-exterior/'}) Фасады

small скрывает заголовок меню:

+product({name: 'Деликат', mod: 'small'})
  +productMenuItem({link: '/projects/delikat-cashier-guidelines/'}) Стандарты кассира
  +productMenuItem({link: '/projects/delikat-cashier-book/'}) Книга кассира
  +productMenuItem({link: '/projects/delikat-cashier-training'}) Обучение кассира
  +productMenuItem({link: '/projects/delikat-identity/'}) Логотип и фирстиль
  +productMenuItem({isActive: true, link: '/projects/delikat-merchandising/'}) Мерчендайзинг
  +productMenuItem({link: '/projects/delikat-mini-exterior/'}) Фасады

+productMenuItem

Пункт меню в переключалке +product.

isActive: true выделяет активный пункт меню и делает его не кликабельным.

+product({name: 'Деликат'})
  +productMenuItem({link: '/projects/delikat-cashier-guidelines/'}) Стандарты кассира
  +productMenuItem({link: '/projects/delikat-cashier-book/'}) Книга кассира
  +productMenuItem({link: '/projects/delikat-cashier-training'}) Обучение кассира
  +productMenuItem({link: '/projects/delikat-identity/'}) Логотип и фирстиль
  +productMenuItem({isActive: true, link: '/projects/delikat-merchandising/'}) Мерчендайзинг
  +productMenuItem({link: '/projects/delikat-mini-exterior/'}) Фасады

+projectMeta

Дата публикации страницы и ссылка на проект, если она есть.

h1 Онлайн-гейминг
p Ворлд Чесс организует и транслирует турниры по шахматам. В 2020 году компания запустила онлайн-гейминг с официальным рейтингом <span class=smallcapitals>ФИДЕ</span>. Теперь можно даже получить титул <nohyphen>онлайн-гроссмейстера</nohyphen>, не выходя из дома. В бюро спроектировали интерфейс игры и лобби.

+projectMeta({
  favicon: 'favicon-inv.png',
  href: 'https://arena.myfide.net/singlegames',
  linkText: 'worldchess.com/arena',
  publishDate: '18 июня 2020'
})

+thumbnail

Превьюшки карточки портфолио для главной страницы и раздела с проектами.

+thumbnail({fitsTo: '1', fitToProportion: '880:639', })
  +image({src: 'cover_full-width.jpg'})

+thumbnail({fitsTo: '7:8', fitToProportion: '767:639', }) 
  +image({src: 'cover_three-quarter.jpg'})

+thumbnail({fitsTo: '1:2', fitToProportion: '430:432', })
  +image({src: 'cover_half.jpg'})

Подробнее о вёрстке превьюшек см. Как сделать карточку проекта.

Миксины

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

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

Как сделать и применить миксин

Миксин задаётся тегом mixin и его названием через пробел. Весь вложенный код станет миксином:

mixin projectDescription
  p Ворлд Чесс организует и транслирует турниры по шахматам. В 2020 году компания запустила онлайн‑гейминг с официальным рейтингом ФИДЕ. Теперь можно даже получить титул онлайн-гроссмейстера, не выходя из дома. В бюро спроектировали интерфейс игры и лобби.

Миксин встаёт в вёрстку как модуль со своим названием.

h1 Онлайн-гейминг

+projectDescription

+projectMeta({
  favicon: 'favicon-inv.png',
  href: 'https://arena.myfide.net/singlegames',
  linkText: 'worldchess.com/arena',
  publishDate: '18 июня 2020'
})

Когда использовать миксины

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

Так выглядит кусок кода без миксинов:

А так с миксинами:

Повторяющиеся куски кода записаны в миксинах и применяются несколько раз

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

Паршиалы

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

Например, мы хотим использовать в карточках портфолио этаж «Сделано Карандашиком». Мы создаём новую страницу в разделе projects с названием partials через адресную строку bureau.ru/projects/partials/new/. Пишем в ней миксины и публикуем.

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

https://bureau.ru/projects/partials/edit/

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

include ../partials/index.pug

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

Анимация

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

У любого анимируемого объекта есть родитель, относительно положения которого и будет рассчитываться анимация. По умолчанию родителем для всех анимируемых объектов является +webpage. Соответственно, их анимация будет рассчитываться в зависимости от того, на каком расстоянии находится верх +webpage относительно верха окна браузера.

Родителем можно сделать любой элемент. Тогда анимация объекта будет рассчитываться относительно него.

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

Чтобы назначить какой бы то ни было элемент родителем, добавьте ему модификатор animationBase.

+module({mod:'animationBase'})
  +image({src: 'image.png'})

А чтобы назначить и настроить анимацию объекту, добавьте ему атрибут animation.

+module({mod:'animationBase'})
  +image({src: 'image.png', animation: {
    '0%': 'opacity:1',
    '100%': 'opacity:0', 
    fromPosition: '0', 
    tillPosition: '100',}})

Для непривычного человека код анимации выглядит как заклинание. Давайте разберёмся, что означает каждая из строчек этого заклинания.

'0%': 'opacity:1' — состояние объекта в самом начале анимации. Вместо opacity можно использовать любые ЦСС свойства: left, right, top, bottom, transform, color, background‑color и другие.

'100%': 'opacity:0' — состояние объекта в конце анимации. Чтобы объект корректно анимировался, все указанные в '0%' свойства должны быть перечислены и в '100%'.

fromPosition — на каком расстоянии родителя от верха окна браузера начинает анимироваться объект. tillPosition — на каком расстоянии заканчивает анимироваться объект. fromPosition и tillPosition по умолчанию задаются в пикселях, их можно не указывать. Единицами измерения ещё могут быть проценты высоты окна браузера vh и проценты родителя %. Значения могут быть отрицательными и положительными.

Например, если вы напишете fromPosition: '‑1000' и tillPosition: '‑300', объект начнёт анимироваться, когда верх родителя окажется на 1000 пк ниже верха окна браузера, а закончит анимироваться, когда верх родителя окажется на 300 пк ниже верха окна браузера:

+module({mod:'animationBase'})
  +image({src: 'image.png', animation: {
    '0%': 'opacity:1',
    '100%': 'opacity:0', 
    fromPosition: '-1000', 
    tillPosition: '-300',}})

Если вы напишете fromPosition: '500' и tillPosition: '300', объект начнёт анимироваться, когда верх родителя окажется на 100 пк выше верха окна браузера, а закончит анимироваться, когда верх родителя окажется на 500 пк выше верха окна браузера:

+module({mod:'animationBase'})
  +image({src: 'image.png', animation: {
    '0%': 'opacity:1',
    '100%': 'opacity:0', 
    fromPosition: '50', 
    tillPosition: '300',}})

Довольно часто нужно, чтобы объект закончил анимироваться в тот момент, когда родитель появится на экране целиком. Вот как это делается — fromPosition: '‑500' и tillPosition: '0':

+module({mod:'animationBase'})
  +image({src: 'image.png', animation: {
    '0%': 'opacity:1',
    '100%': 'opacity:0', 
    fromPosition: '-500', 
    tillPosition: '0',}})
Объект начнёт анимироваться, когда верх родителя окажется на 500 пк ниже верха окна браузера, а закончит анимироваться, когда верх родителя достигнет верха окна браузера

fromPosition: '0%' и tillPosition: '100%':

+module({mod:'animationBase'})
  +image({src: 'image.png', animation: {
    '0%': 'opacity:1',
    '100%': 'opacity:0', 
    fromPosition: '0%', 
    tillPosition: '100%',}})
Объект начнёт анимироваться, когда верх родителя достигнет верха окна браузера, а закончит анимироваться, когда низ родителя достигнет верха окна браузера

fromPosition: '‑100%' и tillPosition: '50%':

+module({mod:'animationBase'})
  +image({src: '/projects/code-guide/files/image.png', animation: {
    '0%': 'opacity:1',
    '100%': 'opacity:0', 
    fromPosition: '-100%', 
    tillPosition: '50%',}})
Объект начнёт анимироваться, когда расстояние между верхом родителя и верхом окна браузера будет равным высоте родителя, а закончит анимироваться, когда середина высоты родителя достигнет верха окна браузера

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

+module({mod:'animationBase'})
  +image({src: '/projects/code-guide/files/image.png', animation: {
    '0%': 'opacity:1',
    '25%': 'opacity:0',
    '50%': 'opacity:1',
    '75%': 'opacity:0',
    '100%': 'opacity:1', 
    fromPosition: '-800', 
    tillPosition: '-200',}})
В соответветствии с кодом изображение два раза меняет свою прозрачность с 1 до 0 и обратно

Добавим к изменению прозрачности ещё и изменение цвета:

+module({mod:'animationBase'})
  +image({src: 'image-red.png', animation: {
    '0%': 'opacity:1; filter: grayscale(1);',
    '25%': 'opacity:0; filter: grayscale(1);',
    '26%': 'opacity:0; filter: grayscale(0);',
    '50%': 'opacity:1; filter: grayscale(0);',
    '75%': 'opacity:0; filter: grayscale(0);',
    '76%': 'opacity:0; filter: grayscale(1);',
    '100%': 'opacity:1; filter: grayscale(1);',  
    fromPosition: '-800', 
    tillPosition: '-200',}})
В соответветствии с кодом изображение два раза меняет свою прозрачность и один раз меняет свой цвет

Теперь вы знаете основы. Вот ещё несколько примеров, что можно делать.

Перемещение по горизонтали

+module({ mod:'animationBase'})
  +module({
    animation: {
    '0%': 'transform: translateX(-100%);',
    '100%': 'transform: translateX(-1%) translateY(0%);',   
    fromPosition: '-1000',
    tillPosition: '-500', 
    }})
    h1 Появление              
  +module({
    animation: {
    '0%': 'transform: translateX(100%);',
    '100%': 'transform: translateX(19%) translateY(0%);',    
    fromPosition: '-900',
    tillPosition: '-500', 
    }})
    h1 заголовка

Появление

заголовка

Паралакс

+module({mod:'animationBase', style:'overflow:hidden'})
  +module({style:'background: linear-gradient(to top, #00aae3, #044587)', mod: 'textWidth', fitToProportion:'1:1.25'})
    +image({src: 'cloud_3.png', top:'-100px', left:'0', style:'width:180%', animation: {
    '0%': 'transform: translateY(0);',
    '100%': 'transform: translateY(120vh);', 
    fromPosition: '-1000', 
    tillPosition: '1500',}})
    +image({src: 'balloon.png', top:'-100px', right:'33%', style:'width:33%', animation: {
    '0%': 'transform: translateY(0);',
    '100%': 'transform: translateY(200vh);', 
    fromPosition: '-1000', 
    tillPosition: '2200',}})
    +image({src: 'cloud_1.png', top:'300px', right:'-40%', style:'width:100%', animation: {
    '0%': 'transform: translateY(0);',
    '100%': 'transform: translateY(80vh);', 
    fromPosition: '-1000', 
    tillPosition: '2000',}})
    +image({src: 'cloud_4.png', top:'100px', right:'0', style:'width:120%', animation: {
    '0%': 'transform: translateY(0);',
    '100%': 'transform: translateY(20vh);', 
    fromPosition: '-1000', 
    tillPosition: '2000',}})

Поворот по кругу

+module({mod:'animationBase'})
  +image({src: 'spectrum.png',  animation: {
  '0%': 'transform:rotate(0deg);',
  '100%': 'transform:rotate(360deg);', 
  fromPosition: '-1000', 
  tillPosition: '1000',}})

Вращение с поворотом

+module({mod:'animationBase'})
  +image({src: 'spectrum.png', animation: {
  '0%': 'transform: rotate(0deg) rotate3d(0,0,0,0deg);',
  '100%': 'transform: rotate(2000deg) rotate3d(3,2,1,1080deg);'
  fromPosition: '-1000', 
  tillPosition: '1000',}})  
Отправить
Поделиться
Запинить