Рука помощи
Вёрстка и скриптинг лендинга для частной клиники в Ульяновске
Инструменты
При вёрстке сайтов я использую такой стек — gulp + sass + nunjucks + postcss плагины + browsersync, на мой взгляд — это оптимальная подборка инструментов. Подключил также webpack + babel — жир конечно для лендинга, но очень уж сильно мне нравится es2015 — на nodejs проектах уже активно использую новые возможности Javascript. Разумеется, в проекте используются оптимизаторы изображений — gulp–image или gulp–tinypng, а также плагин usemin, который я использую для финальной обработки и оптимизации js/css/html.
Webpack vs Yandex Metrika
Столкнулся с одной сложностью, связанной с яндекс.метрикой. В связи с тем, что в Webpack модулях по умолчанию не доступен объект window, пришлось пойти на некоторые ухищрения. В частности, заюзал секцию external:
/* ... */
'webpack' : {
'externals' : {
'window' : 'window'
},
/* ... */
}
/* ... */
Это позволяет импортировать объект window как модуль:
import $ from 'jquery';
import 'window';
const initGoalManager = () => {
window.yaCounterXXXXX.reachGoal('some-goal-name');
}
$(() => {
$(document).on('yacounterXXXXXinited', initGoalManager);
});
Особенности
На самом деле, сверстать подобный сайт можно было–бы и за полдня (имея на руках настроенную рабочую среду и набор необходимых ассетов), но я столкнулся с такими вот приколами:
Конечно, можно было бы воспользоваться фотошопом и наложить эти дуги на изображения, или сделать элемент с background из дуги с прозрачным вырезом, но мозг упорно требовал лучшего решения — как никак, 2017 на дворе! Тем более подобные решения невозможно будет переиспользовать в будущем.
В ходе исследований вопроса постепенно пришёл к слудующим способам реализации:
1. Вытянутый элемент (эллипс) с border-radius 100%
Это первое что выстрелило в моём мозгу при взгляде на первую дугу:
Ок, реализация не такая уж сложная, однако этот вариант пришлось отбросить по двум причинам:
- Адский рендеринг — прямо глаз режут эти рваные переходы линии, но страшнее то, что видны переходы, от размытых разрывов к черезчур четкой линии (вероятно скриншоты не очень хорошо передают суть, но в браузере это хорошо заметно и сильно бесит)
- Невозможность отрисовки рамки внутрь (не сразу увидел блоки с дугой внутри)
* * *
Кстати, если применить к элементу css тени:
…то разрывы становятся менее заметными.
* * *
2. Элемент SVG
Мысль об использовании SVG пришла с ответом на вопрос — что может отрисовывать кривые без искажений? Ответ напрашивался сам собой — конечно же вектор!
Благо, в основе формата лежит пресловутый XML, так что можно программно отрисовать всё что угодно, без использования векторных графических редакторов (конкретно в моём случае там всего–то кубическая кривая Безье).
Разница на лицо — использование Inline SVG позволило избавиться от проблемы «дёрганных» переходов рамки. Таким образом реализовал все 4 возможных варианта дуги (с отрисовкой фона внутри и снаружи). Всё это сложил в отдельные nunjucks шаблоны и закинул в личную библиотечку njk сниппетов – авось пригодится когда–нибудь, а управление CSS свойствами реализовал в виде Sass миксина.
Вторая хитрость этого лендинга — адаптивные стрелки:
Тут тоже было два варианта. Первый вариант (использовал border-image и подготовленный спрайт) нормально работал только в Chrome и Firefox (на остальных либо палочки, либо пустота), поэтому пришлось отбросить его.
Второй вариант основан на использовании двойного background, тут есть один минус – спрайт пришлось разделить на две отдельные составляющие (т.е. страдает микрооптимизация), однако этот вариант корректно работает на всех современных браузерах.
li
&:after
// какой-то код
background-image: url("#{$rp-base-path}/img/arrow-sprite/triangle.png"), url("#{$rp-base-path}/img/arrow-sprite/pipe.png")
background-position-y: 100%, 0
background-repeat: no-repeat, repeat-y
background-size: 1em, .4em
background-position-x: 0, 0.31em
Всё остальное было реализовано поверх sass bootstrap, поэтому не вызывало особых сложностей. К примеру, для этого проекта сгенерировал набор колонок, работающих при определённой ориентации экрана:
// классы грида для стилизации в альбомном режиме
@media(max-width: $screen-xs-max) and (orientation: landscape)
+loop-grid-columns($grid-columns, 'rp-landscape-xs', width)
+loop-grid-columns($grid-columns, 'rp-landscape-xs', offset)