Редизайн популярного сайта — всегда большая и сложная задача, где в миллионе вопросов всё может пойти не так. А когда речь о Smashing Magazine, всё становится ещё интереснее: какие решения приняли создатели сайта, который рассказывает миллионам читателей как раз о возможных веб-решениях?
Сооснователь Smashing Magazine Виталий Фридман рассказал об этом на нашей конференции HolyJS подробнейшим образом, начав с общего дизайнерского подхода, продолжив деталями реализации фронтенда и в итоге дойдя до бэкенда. А теперь в ожидании следующей HolyJS, где Виталий выступит с новыми темами, мы сделали для вас текстовую версию этого доклада, переведя всё с английского на русский.
Получился подробнейший текст с 70 иллюстрациями (осторожно, трафик). А на случай, если вы предпочитаете смотреть англоязычный оригинал или если в нашем переводе какие-то места окажутся неясными, прикладываем и видеозапись:
Я расскажу об изменениях, произошедших со Smashing Magazine за последние два с половиной года. Раньше я никогда не участвовал в проекте, который занял бы такое время, пусть и не фуллтаймовой работы. Стоило довольно больших усилий перейти от этого варианта:
![](https://habrastorage.org/webt/tv/ob/03/tvob03_jm8e3ynmlxpadcnazquw.jpeg)
К этому:
![](https://habrastorage.org/webt/uq/qe/ge/uqqegexqeuhmggf67spi2xcbdsy.jpeg)
Если вам не нравится красный (хотя для России, наверное, такое нетипично), его можно отключить.
Сегодня я хочу осветить и дизайн, и фронтенд, и бэкенд. Знаю, что большинство из вас разработчики, но некоторые темы из дизайна будут важны. Они объясняют, почему определённые вещи мы делали определённым образом. А затем уже перейдём к фронтенду и бэкенду.
Для начала отвечу на вопрос «о чём вы только думали». Потому что этот вопрос я получал очень много раз. Я получал кучу писем, авторы которых были в недоумении, или озлоблены, или раздражены, а порой писали совершенно безжалостные вещи. Поэтому хочется прояснить некоторые вещи.
На мой взгляд, в случае с дизайном есть важная проблема в том, как мы понимаем креативность, рабочий процесс, взаимодействие друг с другом. Проблема заключается в нехватке индивидуальности, но не нас самих, а в индивидуальности того, что мы совместно создаём. Можете ли вы припомнить какой-либо сайт (кроме тех, которые вы сами разработали), который был бы настолько запоминающимся, что вы до сих пор о нём думаете?
Поставим вопрос шире: должны ли вообще сайты быть запоминающимися? Почему большинство из нас не помнят сайты, которые мы посещаем? Разве они не важны? Разве мы просто занимаемся созданием невидимых артефактов, не играющих какой-либо значимой роли? Я думаю, что процесс созидания (включая и собственно дизайн, и разработку) крайне сложный и странный, потому что он постоянно имеет дело с людьми и системами, а они очень часто сложные и странные.
![](https://habrastorage.org/webt/gt/_d/xs/gt_dxsretmcss-p3dony3qszeyu.jpeg)
Часто на творческий процесс смотрят так (не важно, о чём речь — дизайне, разработке, или ещё чем-то): вы начинаете в определенной точке, затем продолжаете, иногда достаточно запутанно, пока не дойдете до финишной прямой.
![](https://habrastorage.org/webt/im/_u/rb/im_urbboib72sbt3fo-kmzdkxgu.jpeg)
Но для людей, которые сами этим процессом занимаются, дело выглядит совсем иначе. Из каждой точки, в которой вы начинаете, исходят много различных возможностей, которые вы исследуете, пока не дойдете до точки, в которой ощущаете «о, это выглядит многообещающе», из которой вновь открывается пучок возможностей и т. п.
![](https://habrastorage.org/webt/5h/5a/kc/5h5akcuodhu_y57w5rthth7gffg.jpeg)
Многие возможности оказываются тупиками, из которых надо выбираться, на это теряется время. Магистральный путь к финишной черте неочевиден.
Поэтому мы обычно предпочитаем пользоваться вещами, которые уже проверены и работают. Вы могли видеть этот твит с вопросом: разработкой какого из этих двух сайтов вы заняты сейчас? Сайтом слева или справа? Потому что других вариантов-то и нет. Разве что может быть отличие в расположении карусели, иногда сверху, иногда снизу.
Мы, в особенности дизайнеры, очень сильно повернуты на пикселях. Кто из вас участвовал в спорах: давайте поменяем border-radius с 14 на 12 пикселей? А через месяц решают, что все-таки лучше 13. Имеет ли это реальное значение? Не теряем ли мы за этим перспективы?
Если мы посмотрим на эволюцию интерфейса, представленную на экране, то увидим, что за 30 чертовых лет практически ничего не поменялось, кроме border-radius и нескольких иконок тут и там.
![](https://habrastorage.org/webt/lj/wd/wh/ljwdwhjow-p7xy197hbgwe32nhw.jpeg)
Может, нам нужны более серьезные изменения? Говорят о 67 оттенках синего у Google, как там тестируют разные цвета ссылок, чтобы понять какой отклик они вызывают у пользователей. А у приложений Facebook вообще 228 вариаций значков. И у них есть традиция вводить новый тип чуть ли не каждый день и смотреть, какие результаты он дает.
![](https://habrastorage.org/webt/vn/pm/wd/vnpmwdtjztygqi-9qkywos-owbw.jpeg)
Мне очень не нравится A/B-тестирование, куда больше мне нравится тестирование A/Z, когда сравниваются принципиально разные вещи. Наверное, детали вроде порядка слов тоже надо тестировать, но при этом нельзя терять из виду перспективы. Иногда это доходит до абсурда.
Часто мы чрезмерно следуем моде. У кого из вас был следующий диалог с дизайнером: из-за iPhone Х нам крышка. Эта штуковина наверху порушит нам все, она в корне поменяет то, как люди смотрят сайты. Но на самом деле эта проблема не имеет никакого значения, поскольку 98% людей на айфонах читают страницы в интернете вертикально, а не горизонтально.
Нам очень нравятся данные. Сколько приложений люди скачивают в месяц? Почти половина — ни одного. Сколько приложений вы лично скачали в этом месяце и реально используете? Тоже, наверное, не пять?
Вот еще статистика: специализированной кнопкой «поделиться» пользуется 2 из 1000 пользователей мобильных телефонов. То же касается остальных кнопок для сайтов — «понравилось», «tweet», «LinkedIn» и так далее. И при этом люди спрашивают: а почему у вас нет специальных кнопок для социальных сетей? Поэтому как раз и нет, люди ими не пользуются.
![](https://habrastorage.org/webt/9z/yu/dx/9zyudxlww-vncrevqgh0w39hsaw.jpeg)
Или другая статистика, 90% запросов на предоставление разрешения (на пользование историей пользователя, положением и т. п.) пользователи отклоняют либо игнорируют, даже не читая. Скорее всего, большинство из вас тоже так поступает. Действительно, кому хочется делиться своей личной информацией?
Итак, нам нравятся данные, нам нравятся вещи, уже достоверно работающие. Я спросил себя: а где здесь есть место индивидуальности? Когда мы только начинали работать, мы поставили себе вопрос: не просто «что сделает нас отличными от других», а что может нам дать голос в сообществе? Я не хотел, чтобы мы были нейтральными, хотел вызывать какую-то эмоцию — быть любимыми или ненавидимыми.
![](https://habrastorage.org/webt/k3/fx/lw/k3fxlwor6qbzyowda3uzsrtns_o.jpeg)
Датский дизайнер Моуэнс Мюллер (Mogens Moller) сказал на одной из конференций несколько месяцев назад вещь, которую, в общем-то, говорят на всех конференциях. Поскольку у нас всех достаточно высокий уровень, нам всем надо выделяться на общем уровне. Нужна индивидуальность, дизайн должен быть запоминающимся, внимание к мелочам должно быть непревзойденным.
Когда я это слышу, я думаю о сайтах вроде dada-data.net, посвященном дадаизму. Сколько бы времени, ресурсов вам понадобилось на разработку этого сайта? Сколько итераций пришлось бы пройти, каким должен был бы быть бюджет? Думаю, все согласятся, что у сайта есть индивидуальность, но лично мне он не по карману. За выходные нечто подобное не собрать.
![](https://habrastorage.org/webt/cq/hy/h9/cqhyh9yy-yfdeoz4k38hxpm2-hk.jpeg)
Дальше Мюллер сказал, что надо обещать малое и давать многое, захватывать и искусно удерживать внимание, и в конечном итоге все сводится к искусству повествования, полагающемуся на выдающуюся режиссуру.
На мой взгляд, есть принципиальное различие между приложениями типа Uber и типа MailChimp. Я спросил себя: почему у меня нет совершенно никакой привязанности к Uber? Если бы появился сервис на 10 центов дешевле, я моментально бы на него перешел. Но чтобы я перестал пользоваться MailChimp, кому-то пришлось бы напрямую заплатить мне деньги. К MailChimp у меня привязанность значительно больше.
![](https://habrastorage.org/webt/ex/ld/t7/exldt7pbqn1vufylhnx0j8bw7ne.jpeg)
Я, как мне кажется, неглупый человек, я понимаю, что обезьянка здесь — это чистый маркетинг, и все же это маркетинг весьма человеческий, близкий, мне нравится индивидуальность этой компании. И этой индивидуальностью и человечностью проникнут их продукт. На мой взгляд, это крайне важно. Поэтому они создают, например, раскраски для детей и дарят их. У них нет кнопки «привет, мы прекрасная и замечательная служба электронной почты», потому что электронная почта — это скучно, если продавать только ее, никто не станет ее покупать. А в другой упаковке оно будет выглядеть значительно интереснее.
В этой раскраске, на мой взгляд, прекрасное оформление и выбор слов. «Привет! Меня зовут Фредди. Быть мной весело! А тобой?» Как можно на это ответить негативно? «Я скучен, я самый ужасный человек в мире?» Там много ещё, и последний рисунок: «Мне нравится быть мной. Тебе нравится быть тобой?» Я сам себя ненавижу, каждый день, с утра с момента как проснусь.
Другая история, которую я хочу вам рассказать, касается Tijuana Flats, сети мексиканских ресторанов в США. Вот пример их интерьера:
![](https://habrastorage.org/webt/s2/hj/hw/s2hjhwfhuofua_cvknpvjjdpjb4.jpeg)
Независимо от того, нравятся они вам или нет, я думаю, вы согласитесь, что с этой зомби-стилистикой у них есть индивидуальность. У них высокие потолки и высокие стены, и каждые четыре месяца они нанимают новых художников, которые рисуют им новые граффити. Что говорит о степени их внимания к интерьеру. Похожий стиль у них и в меню, и таким же образом был оформлен их сайт:
![](https://habrastorage.org/webt/cl/ig/rt/cligrt3vo8z00xyvnws62w0t-f0.jpeg)
Однако, как мы все знаем, параллакс и веб-шрифты — это зло, текстуры при рендеринге — зло, производительность имеет значение, и, вообще, сайт должен работать быстро и при этом поблескивать. Руководствуясь этими стандартными для нас установками, они создали для своего сайта новый дизайн, в котором, на мой взгляд, очень многое утеряно. Первоначальный вариант мне нравится больше, поскольку он отражал их индивидуальность.
![](https://habrastorage.org/webt/kx/uu/du/kxuuduytvjy6iuyezmavvivuxh4.jpeg)
На своем опыте этот урок очень хорошо усвоила компания Bloomberg. Они наняли дизайнеров и дали им полную свободу действий. Получившийся продукт можно очень много ругать, тем не менее, он прекрасен, и выполняет свою работу: билеты стали продаваться значительно быстрее, чем в предыдущий год. Когда последний раз вы пользовались тегом <marquee>?
![](https://habrastorage.org/webt/ku/ii/pr/kuiiprwehjquq1pudngwljfbtiw.jpeg)
Советуем перейти по ссылке, скриншотом это не передать
Нет ответа. Хорошо, мы работаем в JavaScript, нам этот тег не нужен. Но в целом, почему бы не пользоваться разными безумными вещами, хотя бы просто чтобы попробовать? И многими другими вещами, которыми, как считается, пользоваться «не стоит».
Взгляните на другой материал Bloomberg, который вы никогда не забудете. Зафиксируйте сейчас дату, потому что это изменит вашу жизнь. Это материал, посвященный проектам Илона Маска.
Он отматывает время в прошлое чуть ли не вплоть до 1998 года, где всё было не так, как должно быть. Сейчас можно услышать от дизайнеров, что мы живем в эпоху «брутализма» в дизайне, когда все выглядит жутким и сломанным, потому что поломанные вещи в моде. На мой взгляд, это просто отчаянные попытки различных компаний выглядеть оригинально на общем фоне, потому что иначе никто не обратит на них внимания.
А в этом проекте про Илона Маска ещё много всего, поисследуйте его самостоятельно. Ему самое место в музее.
И я задал себе вопрос: что это все означает для Smashing Magazine? Такой «сломанный» дизайн я создавать не хочу. Но мне пришли в голову несколько вариантов. Давайте возьмем что-то самое скучное или самое раздражающее всех. Скажем, кому нравятся всплывающие окна? Кажется, одному человеку в зале, и, возможно, еще кому-то, кто не готов публично в этом признаваться.
Но если вдуматься, то что в них плохого? Да, это реклама, но оформить ее можно по-разному. Представляю вам всплывающее окно с volkshotel.nl: самое раздражающее и самое прекрасное в мире всплывающее окно.
![](https://habrastorage.org/webt/za/a7/sx/zaa7sx9_lf66j5idbipqzrp1f1o.png)
Я бы хотел, чтобы у всех сайтов до единого такое было. Он такой раздражающий, что не могу прекратить его использовать! И это прекрасно сочетается с общим духом сайта, уверен, что конверсия тоже высокая.
Другой пример. Возьмем нечто крайне скучное, например, окно выбора формы обращения «мистер/миссис/мисс». Мы все знаем, зачем оно нужно на самом деле — для целевой рассылки спама по полу. Давайте попробуем поменять это окно, например, вместо свободного выбора сделать закрытый, но очень длинный список. С вариантами вроде «ваше превосходительство» и «тов. лейтенант». Этого может быть достаточно, чтобы поменять всю индивидуальность вашего сайта.
![](https://habrastorage.org/webt/jm/v5/v_/jmv5v_mgeuqdqj5ifjdblhrexi8.gif)
Или другой пример, здесь сова закрывает глаза крыльями, когда вы начинаете вводить пароль. Это мило, и иногда этого может быть вполне достаточно. Когда мы начинали свою работу, мы думали о том, как сделать такой подход к индивидуальности частью нашего сообщества.
Проблемой, с которой мы с самого начала столкнулись, были блокировщики рекламы. Если я сейчас сделаю опрос, скорее всего окажется, что 80% пользуются ими, а 20% врут в опросах. Я блокировщиком тоже пользуюсь, считаю их полезными, и вам советую, если вы его еще не установили.
Тем не менее, для нашей компании блокировщики стали проблемой, поскольку стали падать доходы от рекламы. Последние 5 лет каждый год они падали в 2 раза. Во время последней смены дизайна где-то у 12% наших пользователей были установлены блокировщики, а сейчас — у 66%. У нас аудитория из людей вроде вас, конечно, вы используете блокировщики рекламы, вы же не дураки!
Но это означает, что наша прибыль составляет 1/16 от того, что было пять лет назад. То есть возникла проблема, требующая решения. Проблема в самой рекламе, она не работает и, в любом случае, я не верю в традиционную «медийную рекламу». Нам нужно было найти другой подход, представить новый продукт, который должен стать центром всей нашей деятельности. Не хочу говорить слишком подробно, но суть в том, что это подписка, дающая доступ к Smashing TV, вебинарам и тому подобным вещам. И доступ должен происходить ко всему этому сразу.
На тот момент наша система состояла из следующих составляющих. Журнал уже работал к тому времени ни много ни мало 10 лет под старым добрым WordPress с большим количеством добавлений. Помимо этого был онлайн-магазин, работавший поначалу на Magento и затем перешедший на Shopify. Он неплохо работал, но его сложно было связать с журналом на WordPress, пока не появился плагин для Shopify. Кроме того, мы пользовались Kirby для создания статичных сайтов для Smashing.com и еще на Ruby-приложении был основан сайт с вакансиями. Все вместе связать было достаточно сложно. Чтобы создать проект, объединяющий все эти элементы, он с ними должен быть связан. Например, вы осуществляете вход один раз и затем получаете скидку в системах на WordPress, Magento, Ruby и т. п., не создавая при этом отдельного аккаунта на каждой платформе. Этот проект нам надо было написать с нуля.
![](https://habrastorage.org/webt/uw/r6/z7/uwr6z7urzz4v7ppxbhhatb0u0pg.jpeg)
Мы собрали команду, и, несмотря на то, что презентую я этот проект в одиночку, работа перечисленных на экране людей была по-настоящему важна, заняла много времени и сил. Большая часть CSS была написана Сарой Суедан (Sara Soueidan), большая часть JavaScript — Ильей Пухальским. Тут работало много людей, включая «кошачьего иллюстратора» — скоро поймёте, что это значит. И, кроме того, мы использовали Netlify в этом проекте. Проект оказался дорогим, и изначально мы хотели запустить всё к 10-летию с появления Smashing Magazine, затем к 11-летию, завершили только несколько недель тому назад. Я хочу рассказать вам о том, как мы действовали и почему.
Мы начали с текста, с названий компонентов. Это было одной из главных вещей. Мы начали с того, что посмотрели на интерфейс вот так:
![](https://habrastorage.org/webt/zc/te/h2/zcteh2oc4zl4f2c4vennkwluk0y.jpeg)
Это был мой первый набросок. Вы думаете о том, какие компоненты нужны странице или сайту, записываете их все. Он определяет то, как вы будете строить ваше взаимодействие с клиентами. У меня здесь есть прототипы микровзаимодействий: «Вы действительно хотите удалить этот файл?» Ещё не надо ничего воплощать, но надо продумать, что вам нужно, и дать этому названия. И, в частности, я с самого начала думал над сообщениями об ошибках:
![](https://habrastorage.org/webt/7i/ax/cs/7iaxcsvzp5siji2os2qnzuwyfac.jpeg)
Вне контекста это выглядит странновато, но если вы в контексте, все становится на свои места. Мне хотелось найти индивидуальность приложения. Мне хотелось, чтобы при столкновении с ошибкой вы могли улыбнуться, и превратить этот опыт в позитивный.
Затем мы перешли к выбору шрифта. Тот вариант, который мы выбрали для заголовков — я его терпеть не могу. Однако когда мы стали спрашивать у людей, с чем для них ассоциируется Smashing, то оказалось, что не с уважаемыми и профессиональными публикациями, а, например, с кошками. А мне не хотелось, чтобы моим наследием остались кошки. Поднимите руки, кому из вас нравятся кошки? А собаки? Ух ты, наверное, это единственная страна, где кошек любят больше. Обычно 40% собачников, 30% кошатников, а оставшимся наплевать на тех и других.
![](https://habrastorage.org/webt/e8/rq/sr/e8rqsrpxz3ipcs5nl_kk58h9ka0.jpeg)
Дело в том, что мы пять раз в год организуем конференции, и у каждой есть изображение кошки. Мне лично кошки совершенно не нравятся, но когда при организации первой конференции в 2012-м иллюстратор спросил меня «не нарисовать ли нам кошку», я ответил «почему бы и нет» — первая конференция, кому какое дело. А затем на второй конференции их было уже больше, пошло-поехало, и теперь все в кошках. Печально, или радостно, в зависимости от того, кошатник ли вы.
![](https://habrastorage.org/webt/lx/tn/aj/lxtnajltuqngzp50yjhtxxhbtdw.jpeg)
Я решил, что тут важнее не мои предпочтения, а то, как нас воспринимают люди. Сейчас у нас этих кошек 68 штук в разных местах в интерфейсе. Если вам удастся найти их все, я обещаю, что оплачу вам поездку в бизнес-классе на любую из наших конференций в любой точке мира, с учетом проживания, еды и чего бы вы ни захотели. Всех их вам не найти. У меня есть знакомые, которые, когда я предложил им это пари, сказали «ты не знаешь, с кем связался», и написали алгоритм с машинным обучением, который пытался искать эти картинки. Им можно только пожелать удачи, поскольку некоторые из картинок написаны в ASCII, а некоторые — в print.css.
Нам было важно взглянуть на вещи под правильным углом — причем в буквальном смысле слова. Мы экспериментировали с вёрсткой, дошли до возможности поворота и посмотрели на свой логотип, который уже был под углом. Раньше этот угол составлял 10.6 градусов, а при редизайне стал 11 градусов. Большой шаг для нас! А это значит, что все остальное также должно быть под углом в 11 градусов, как видно в нашем стайлгайде; у нас все на основе компонентов.
![](https://habrastorage.org/webt/-u/en/2b/-uen2bbof55z6u5z2tbzg-heniq.jpeg)
Небольшое отступление. На меня производит большее впечатление Airbnb. Я понимаю, что у них все совсем иначе, но мне важно то, насколько далеко они провели эту идею библиотеки шаблонов стиля. Они создали своего рода поисковый механизм для разработчиков и дизайнеров. Если вам нужен определенный рабочий процесс, тестирование определенных компонентов, вы просто набираете его, выбираете платформу и другие настройки. И вам демонстрируют, например, варианты форм логина для iPhone 6, с видом всех компонентов и обзором интерфейсов.
Затем они развили эту идею еще дальше, и назвали ее air/shots. Наверняка многие из вас видели созданную ими связку между Sketch и React. По словам Бенджамина Уокинза, они решили, что если машинное обучение может отличить друг от друга сложные, написанные от руки изображения (вроде китайских иероглифов), то наверняка можно научить ее распознавать каждый из 150 компонентов нашей системы.
![](https://habrastorage.org/webt/ud/ou/2m/udou2maagwpapbv6hfmqqevgy5a.jpeg)
Теперь можно нарисовать компонент от руки, и, проанализировав изображение, машина выдаст соответствующий React-компонент из заранее заданного набора. Меня этот подход впечатляет до крайности. Представьте, как процесс будет выглядеть в будущем.
До этого мы, конечно не дошли, но в основе нашей работы тоже лежали отдельные компоненты. Перед вами пример нашего дизайна, как видите — все под наклоном.
Другая идея, которая может, на мой взгляд, помочь уловить нашу индивидуальность. Чтобы быть последовательными, я изначально хотел использовать в коде эмодзи котов, но оказалось, что таких эмодзи слишком много и они не единообразные. Это затрудняло отладку, и идея не прошла. Но могли бы!
Мы много внимания уделили вещам вроде Print Style Sheet. Я человек ленивый, поэтому мне это казалось значительно проще, чем заниматься генерацией .pdf. Вот пример чека, сделанного таким образом, и не нужны никакие расширения. То же самое и со статьями. Мы занимались созданием электронных книг, а в них часто есть статьи. Я решил, что надо один раз потратить достаточно времени на создание Print Style Sheet, который объединял бы несколько статей в один документ, и на выходе создавалась бы книга, прилично оформленная, со ссылками и прочим.
Перейдем к фронтенду. Мы начали работу над ним в декабре 2015-го и посмотрели, какими браузерами пользовалась аудитория:
![](https://habrastorage.org/webt/k_/8p/kc/k_8pkccca1j_aljwcasiesnm_y8.jpeg)
Большая часть из них хорошие, поскольку на сайт к нам приходят посетители вроде вас — вам ведь не придет в голову пользоваться IE 8, правильно? С тех пор Firefox опустился до 7%, а Chrome только набрал популярности до 66% — то есть люди переходят с IE не на Edge или Firefox, а на Chrome. Edge даже упал в популярности, с 1.2 до 0.6%. Кто из вас пользуется Edge? 0.0%? Это немного грустно. Данные немного сбивает тот факт, что раз в два года на сайт заходит пользователь с user-agent IE 666. Это, конечно, мило.
![](https://habrastorage.org/webt/1r/ht/jb/1rhtjbbztkqhbmys7r9c5ylpxri.jpeg)
Когда мы начали писать компоненты, мы следовали определенной пирамиде. Знакомы ли вы с пирамидой потребностей Маслоу? Пэтти Толанд и FilamentGroup в Бостоне пришли идея применить принцип этой пирамиды к responsive design. Самый нижний уровень — это скорость, о ней нужно думать в первую очередь при написании любой страницы или компонента. Затем идет доступность, масштабирование, и, наконец, стиль (логотипы, цвета, шрифты, анимации и т. п.).
CSS мы писали, руководствуясь этим принципом, идя снизу вверх. Мы старались не пользоваться фреймворками, не потому, что принципиально против них, а потому, что в конкретных ситуациях в них не было смысла. При использовании фреймворков слишком многое остается за кадром. Мы не хотели пользоваться чем-то избыточно большим. Нам значительно удобнее было пользоваться меньшими по размеру библиотеками. Изначально мы планировали использовать React, но затем остановились на Preact, небольшой библиотеке, имитирующей React. Возможно, скоро придется переходить на React. Причина в том, что нам пришлось написать значительно больше собственных вещей на Preact, чем мы планировали. Каждой вещью приходится заниматься отдельно, что несколько печально.
Кроме того, мы не хотели пользоваться медиа-запросами. Вы небось думаете «А с ними-то что не так?» Не то бы с ними «что-то не так», но их поддержкой достаточно сложно заниматься. Когда все рассчитано для двух разных экранов, маленького мобильного и большого компьютерного, сложности возникают посередине.
![](https://habrastorage.org/webt/68/em/q2/68emq2g4klwvyedgdcn2n2xtv0w.jpeg)
Если взять обычное приложение и сузить окно, оказавшись между двух поддерживаемых разрешений, то мы сразу увидим, как возникают «поломки», в особенности посередине страницы.
Для борьбы с этим можно добавить точку прерывания (breakpoint). А потом ещё одну. А потом ещё. А в итоге получается страшная возня при переменах в структуре страницы. Конечно, мы пользуемся вещами вроде Sass и Less, но всё равно приходится проходить по медиа-запросам и чинить их, а я не люблю заниматься починкой.
Так мы пришли к мысли о необходимости гибких размеров (fluid sizing) для всех компонентов. Как эффективно изменять размеры любого элемента UI (хоть слайдера, хоть календаря) с сохранением пропорций, но без обращений к их параметрам широты и высоты напрямую? С помощью небольшого трюка, о котором вы уже можете знать.
![](https://habrastorage.org/webt/xq/vj/x5/xqvjx5n9fgl6glydn-k-8jpr3ru.jpeg)
Есть ваш компонент. Есть размер шрифта body. Есть единица rem, она завязана на корневой элемент (body или html). 1 rem всегда равен размеру шрифта body. Если размер шрифта у компонента выставить в единицах rem, а все остальное — в единицах em, то при увеличении окна всё вырастет. Вместо того, чтобы менять все в медиа-запросе, вам просто надо указать, что мы перейдём от размера шрифта 75% к 125%. Все внутри элемента вырастет соответственно.
Но это — только первый шаг. Нам не нужно, чтобы компонент рос таким образом:
![](https://habrastorage.org/webt/ko/1q/br/ko1qbr2veometmli-z6i5r3qjnw.jpeg)
Нам не подойдёт, если элемент будет размером в 1 пиксель на небольшом экране и 500 пикселей на крупном. Рост должен быть контролируемым, он должен начинаться и прекращаться в определенных точках:
![](https://habrastorage.org/webt/wm/9o/ku/wm9okusxzmdqxvob5agtgjcrs2a.jpeg)
Попробуем сделать график, на котором по вертикальной оси будут указаны размеры шрифтов, а по горизонтальной — ширина viewport. Тогда мы сможем выстроить точки прерывания в линию. Она не будет прямой:
![](https://habrastorage.org/webt/w6/cv/rz/w6cvrz-l6r2hbk7i-9zjrpzxpbm.jpeg)
Поскольку нам всем нравится математика, эту зависимость можно описать уравнением y = mx3 + mx2 + mx + b.
В CSS такого, конечно же, никак не сделать. Может быть, это возможно в JavaScript, но все равно это абсурд. Но важна сама идея: представьте, что у каждого компонента была бы функция, определяющая его поведение. Вместо бесконечного написания точек прерывания можно один раз описать компонент, и он будет правильно отображаться на любых экранах, хоть на телевизионных. Даже если это будет приближением, оно будет достаточно точным. Можно разбить кривую на несколько прямых, каждая из которых будет определена как y = mx + b. В итоге приходишь к такому:
![](https://habrastorage.org/webt/yo/4c/9v/yo4c9vjkopiuf4jtjd7jmlbrtpy.jpeg)
Но реализовывать такое в CSS или JavaScript у вас желания, скорее всего, не возникает, не правда ли? Ну, у меня оно возникло, но делать этого действительно не стоило. В конечном итоге, нам нужно достаточно простое поведение: чтобы с определённой точки элемент начинал расти, а после определенной — переставал расти. В CSS этот принцип можно реализовать при помощи формулы:
![](https://habrastorage.org/webt/dw/i5/z2/dwi5z2bsaoflrygiqsg1rwg0_o8.jpeg)
В CSS calc позволяет совершать базовые арифметические операции. В начале формулы 16 пикселей — это минимальный размер шрифта. Затем ищется разница между максимальным и минимальным размерами. Затем идет диапазон, в котором еще может продолжаться рост, и, наконец, разница между максимальным и минимальным размерами экрана. Вот и все, что вам необходимо. И получаете что-то вроде codepen.io/MadeByMike/pen/VvwqvW.
Добавлю на всякий случай, что популярные браузеры поддерживают это, нет причин не использовать:
![](https://habrastorage.org/webt/zc/hh/er/zchherljx0c_qhmwllgre8rip8w.jpeg)
Мы подумали: почему бы не использовать этот метод вообще везде: с границами, отступом, шириной, вплоть до высоты строк. В последнем случае, опять-таки, речь идет не о неконтролируемом росте, а об изменении между 1.3 и 1.5. Принцип тут тот же, надо только пересчитать формулу.
![](https://habrastorage.org/webt/tl/ha/xm/tlhaxmsrah89ncskrrhphdmwrba.jpeg)
Есть два способа достичь этих результатов. Можно просто выставить динамический размер шрифта на элементе HTML в CSS.
![](https://habrastorage.org/webt/6n/yg/pv/6nygpv1n6hnhhevpguhf7m-uauk.jpeg)
И тогда, в зависимости от viewport, все внутренние элементы автоматически будут приведены к масштабу. Если же вам нужен контейнер фиксированного размера, вы можете просто определить fixed-container с размером шрифта в пикселях и размером внутренних компонентов в em.
Либо, наоборот, можно включать гибкое поведение для отдельного контейнера, а все остальное оставлять фиксированного размера.
На этом варианте мы в итоге и остановились. Если откроете Smashing Magazine и начнёте менять ширину окна, увидите, что все составляющие меняются: ширина, высота, межстрочный интервал, размер шрифта, SVG-логотип в углу и так далее.
Конечно, для этого нужно много «волшебных» чисел в CSS. Но всё это делается через calc. Другим свойствам, возможно, несколько грустно от этого, но calc у нас — самое используемое.
Нам очень помогло организовать наше пространство имён. Вот цитата из Гарри Робертса: «Я не знаю, какая у этого функция. Я не знаю, где это еще используется. Я не знаю, можно ли это стереть, изменить, или использовать еще где-либо. Я вообще об этом ничего не знаю!» Каждый из нас сталкивался с такой ситуацией, когда вы, будучи дизайнером или разработчиком, обращаетесь к CSS и JavaScript и не понимаете, что к чему. В итоге мы стали использовать много приставок для различных компонентов, например, таких:
![](https://habrastorage.org/webt/np/59/yb/np59ybcbmslkcx_tzms2kdviycc.jpeg)
Это очень сильно помогает, когда читаешь код, сразу понятно, что к чему. Надо только понять, на каких уровнях находятся компоненты.
Конечно, мы так же пользовались BEM, для определения связей. Я предполагаю, что в России о BEM слышали. Хоть, возможно, его и не уважают из-за настойчивости, с какой его рекламирует Яндекс. Мне, кстати, эта политика непонятна, поскольку, как мне кажется, в Европе и в США BEM достаточно хорошо известен, нет нужды так агрессивно его продвигать.
Другая важная тема — это отзывчивые суффиксы, с которыми можно сделать что-то такое:
![](https://habrastorage.org/webt/r8/hi/qd/r8hiqdhlxy1oo_o3s8b5vxb37nc.jpeg)
Цель такая: из кода должно быть ясно, что он делает, без необходимости заглядывать в CSS или JavaScript. Если в классе написано «c-image-list@small-screen c-carousel@large-screen», то мне сразу становится ясно, что тут к чему. Все, что остается сделать в CSS — это поставить символ “\” перед “@”.
Некоторая часть из этого кода написана другими людьми, некоторая часть — мной.
Классы, по которым планируется провести рефакторинг, или по которым он уже проведен, мы называем с префиксом .rf-*. Благодаря этому можно, например, выделить зелёным цветом на интерфейсе все элементы, уже прошедшие рефакторинг, а красным — те, которым рефакторинг еще предстоит. Это очень удобно.
![](https://habrastorage.org/webt/y6/xt/hq/y6xthqvfnc1vyuix_-hetvvse5y.jpeg)
Другая крайне полезная вещь — это модульная сетка в CSS, то есть Grid Layout. Кто из вас о ней слышал? Оказывается, все. А кто пытался с ней поиграть? Давайте посмотрим, что при её помощи можно сделать.
Когда её пытаются рекламировать (непонятно, зачем, она и так прекрасна), зачастую показывают следующую картинку:
![](https://habrastorage.org/webt/x-/8n/wt/x-8nwtgtpgzoaugmzejfnwpimwi.jpeg)
Но это — самое жуткое введение в модульную сетку, какое только можно придумать. Оно сложное. Но сетка совершенно не обязана быть сложной. При помощи неё можно создавать и простые вещи, например, такой вот необычный дизайн:
![](https://habrastorage.org/webt/ya/d2/op/yad2opfkt1plrup4q3dzoxulria.jpeg)
Сделать его крайне просто, буквально пять минут. У Джен Симмонс на сайте есть ещё другие примеры использования Grid. И, кстати говоря, с точки зрения поддержки браузерами тут тоже не о чем беспокоиться.
Несколько вещей, которые надо знать при её использовании. Есть линии сетки, которые могут быть горизонтальными и вертикальными. Между этими линиями — дорожки сетки, на пересечении горизонтальных и вертикальных линий — ячейки сети, а несколько ячеек вместе составляют зону сети.
![](https://habrastorage.org/webt/n9/6l/-w/n96l-wct5qn9irrwteejikqri34.jpeg)
Сеть определяется через задание шаблонных столбцов grid-template-columns, и для этого можно использовать различные нотации. Например, при помощи ключевого слова repeat() можно создать несколько дорожек с одинаковыми параметрами.
![](https://habrastorage.org/webt/uj/jy/qo/ujjyqok6ov2gfv9f3tvboe23km0.jpeg)
Другая полезная функция — minmax(), позволяющая расти между двумя значениями. Предположим, у нас есть контейнер с содержимым, и есть нечто, выходящее за рамки этого контейнера.
![](https://habrastorage.org/webt/6o/z2/z1/6oz2z1fsvrmzkxs15ucm_o4gsnu.jpeg)
У нас есть простой пример построения такого контейнера:
![](https://habrastorage.org/webt/cr/fm/ca/crfmcatzpzueujploimidv6gg2a.jpeg)
Ленивый разработчик закроет контейнер, подключит изображение, снова откроет контейнер, на этом успокоится и пойдет выпить.
![](https://habrastorage.org/webt/lt/ke/5r/ltke5rooouawfg45ukyozmcv3yw.jpeg)
Пожалуйста, не поступайте так. Есть значительно лучший способ.
Саму проблему стоит представить несколько иначе. Предположим, что у нас три столбца в модульной сетке, один справа, один слева, и посередине столбец с содержимым.
![](https://habrastorage.org/webt/q7/gz/yt/q7gzytloiu_s58frairqnj43ud4.jpeg)
Первое, что мы добавляем — это supports. Если вдруг вы не знаете, это функция для определения возможностей в CSS. Ее можно использовать вместо Modernizr. Загвоздка только в том, что у supports не всё хорошо с браузерным, так сказать, support. Зато у любого браузера с суппортом supports будет и суппорт «display: grid».
![](https://habrastorage.org/webt/th/ms/3t/thms3trhftvm0nlpmip4tztxe_k.jpeg)
Далее, мы определяем столбцы сетки, и присваиваем имена линиям разделения: “full-start”, “main-start”, “main-end”, “full-end”. Этих линий всегда будет на одну больше, чем столбцов. У каждой линии может быть несколько имён.
![](https://habrastorage.org/webt/io/y5/hg/ioy5hgg0ozsxc9-r5q3vxdp7sne.jpeg)
Теперь осталось только указать: всё, что находится в контейнере, необходимо поместить в столбец main. Затем, если надо вывести что-либо за пределы контейнера, указывается “grid-column: full”, и содержимое занимает все три столбца.
Преимущество такого подхода в отсутствии медиа-запросов и, соответственно, ссылок на окно просмотра. Благодаря этому такой контейнер можно поместить внутрь другого, добавив, например, ещё и боковое меню:
![](https://habrastorage.org/webt/z0/ak/zr/z0akzrjdeuob3npsgjottn-9eua.jpeg)
Дизайнерам почему-то очень нравится идея «вертикального ритма». Я задался вопросом, как его можно реализовать. Представим структуру страницы с заголовками, текстом, изображениями, в которой все элементы должны быть выровнены по правильным линиям. На экране из двух примеров это выполнено правильно в том, который справа.
![](https://habrastorage.org/webt/1l/az/vf/1lazvf3qpochfefpkr-pxhk36cs.jpeg)
Сделать это, на самом деле, достаточно просто.
![](https://habrastorage.org/webt/jg/lq/ih/jglqihw_au88evbnj9sbnmm5ahm.jpeg)
Здесь есть тег figure, который выводится за рамки родительского контейнера (“breaks out”). Извините, что так много CSS, уж очень мне это дело нравится.
![](https://habrastorage.org/webt/1k/1p/st/1k1pst9u2oskrlajvp0ourk0tuq.jpeg)
Для body можно выставить свойство calc, затем для root выставить свойство --gutter, которое определит зазор между строками.
![](https://habrastorage.org/webt/i6/sm/g5/i6smg5jng8cfat65zu0qxtejcdg.jpeg)
И, наконец, осталось передать в grid-row-gap то значение, которое мы определили для gutter в root.
Интересно, что я тут использую единицу измерения ch, «символьную», которой редко пользуются. Достаточно часто у дизайнеров есть требование, согласно которому в каждой строке должно быть, например, 60 или 70 символов. И получается 12 дорожек по 4,85 символа.
Единица ch (character unit) основана на ширине символа «0» в данном шрифте. Лия поправит меня, если я ошибаюсь. (Голос Лии Веру из зала: «Правильно»).
Сравним два варианта:
![](https://habrastorage.org/webt/g0/yy/y0/g0yyy0fewsxw4_55h-etpm34tms.jpeg)
Из них второй, очевидно, более читаемый. На всякий случай добавлю, что, конечно же, ch уже давно поддерживается в браузерах.
Итак, структура страницы оказалась достаточно короткой. CSS стал невероятно простым. Или сложным, зависит от того, как посмотреть. Кроме того, вам, конечно же, нужно будет использовать селектор “*”.
![](https://habrastorage.org/webt/hh/db/pe/hhdbpefudw2ihxqltx0bmiqd-sm.jpeg)
Он замечателен. Вот пример его использования: элементы, попадающие под правило “* + *”, получат свойство margin: 0, и содержимое будет ограничено центральным столбцом. Все, больше ничего делать не надо. Никаких медиа-запросов не происходит. И с точки зрения гибкости и топографии, у нас все построено именно таким образом.
Выйдем на наш сайт, прокрутим страницу немного вниз… Небольшое отступление: вот мы видим кнопку, на которой написано, что она «ничего не делает».
![](https://habrastorage.org/webt/z8/r3/02/z8r302ljpqnjzgookj-2dmesybc.png)
Это тоже часть индивидуальности, которую мы пытаемся придать нашему сайту. Так вот, именно на эту кнопку чаще всего нажимают! Что не так с людьми?
Вернёмся к теме. У нас всё реализовано так, как я рассказал, и с этим подходом есть сложность. Существуют браузеры, которые поддерживают supports, но при этом достаточно плохо поддерживают модульную сетку. Например, в Edge 13 код, который я только что вам показывал, интерпретируется весьма оригинально:
![](https://habrastorage.org/webt/6i/16/vj/6i16vj4sa-mnjegqi6lhz-kre2s.jpeg)
Поэтому в коде надо заменить display: grid на grid-gap: 0, не спрашивайте почему. Потребовалось много времени, чтобы выяснить, чем это обусловлено. Сумасшествие.
Под конец я хочу поговорить о бэкенде. Крайне важная тема, особенно, я думаю, для вас. Кто-то, возможно, слышал о JAM Stack. Один человек. Хм, я этого не ожидал. Ничего страшного.
Я рассказывал о том, как мы делали наш журнал на основе WordPress, все было на PHP (кроме частей на Ruby). В 2012 году я встретил Мэтта, впоследствии ставшего одним из основателей Netlify. Это платформа для автоматизации веб-проектов, использующая CDN вместо традиционных серверов, и в эту CDN они как следует вложились. Когда меня заинтересовало их творение, Мэтт продемонстрировал перенос наших ресурсов на CDN Netlify, благодаря чему производительность возрастала в три раза (при том, что мы уже на тот момент потратили много усилий для оптимизации нашего процесса на WordPress).
Этот проект занял у нас целых два года из-за того, что у нас было много параллельной с ним активности. Хотя задействовано было много людей, большая часть — это наша с Ильей работа на CSS и JavaScript. Иногда говорят, что мы ненавидим WordPress. Это не совсем так. Я его не ненавижу. Просто не особо люблю! Ну, вообще он норм — инструмент, как любой другой. Просто в определенный момент он перестал нам подходить. Мы перешли к системе на основе генераторов статичных сайтов, которую также часто называют «JavaScript, API и разметка» или JAM Stack (разметка — markup). Как она устроена?
![](https://habrastorage.org/webt/z9/hn/0i/z9hn0i6r4zx0epuprhk7yg9fzjw.jpeg)
Мы все знаем, что интерес к FTP падает и он медленно умирает, а интерес к Git растет. Кроме того, конечно, растут Gulp, Grunt и подобные им инструменты. Наконец, для них есть очень много различных API.
Вспомним историю. Изначально у нас были только взаимодействующие браузер и сервер. Затем кто-то сказал «нет, надо ещё программу для интерактивных вещей на cgi-bin и Perl». После этого сказали «и этого недостаточно», добавили базы данных на серверах, на PHP, MySQL и Apache. Но и этого оказалось недостаточно, для увеличения производительности нам нужно кэширование. Когда это было реализовано, решили, что нам нужно что? Правильно, CDN. Всё это привело к колоссальному росту числа взаимодействующих сущностей в системе:
![](https://habrastorage.org/webt/so/14/rd/so14rdxxigwalzjb_x1j3_no30w.jpeg)
И тогда-то возникла идея: возможно, нам следует вернуться к максимально простой схеме. Сделаем просто «браузер и CDN».
Работает это следующим образом. У нас есть система, которая скорее всего, присутствует также у всех вас, из Git, средств сборки и API. Код подаётся в средства сборки. Каждая статья, каждый комментарий, каждый автор, каждая вакансия записываются как файл markdown. Далее из всего этого создается HTML, добавляются CSS и JavaScript. Это затем отправляется на CDN, где к этому получает доступ пользователь. Интерактивные вещи вроде поиска и комментариев делаются при помощи JavaScript поверх всей этой системы.
Мы пользовались Preact, что часто вызывало вопрос: не возникает ли проблем с временем загрузки? Не возникает, поскольку это не одностраничное приложение, а набор одностраничных приложений. Благодаря этому для того, чтобы начать отображать наши страницы или читать статьи, JavaScript не нужен вообще. У нас нет ни единого блокирующего запроса, поскольку вы просто заходите на страницу и загружаете критический CSS наверху. Для разных страниц у нас пять или шесть блоков критических CSS. И, конечно, наше приложение является PWA («прогрессивное веб-приложение»), хотя по большому счету других сегодня, скорее всего, уже и нет.
![](https://habrastorage.org/webt/ds/lx/d8/dslxd8emb2bjwha5453lsyydcok.jpeg)
Перед нами стек, в нем ничего сложного. У нас достаточно много микросервисов и API, но ничего особо сложного не происходит. Конечно, есть проверка наличия подписки и подобные вещи. Для оплаты используется Stripe. Для «бэк-офиса» в бэкенде используется система на Go.
На меня большое впечатление произвела скорость этой системы. Скорее всего, мы были одним из первых проектов такого масштаба, перешедших на JAM Stack. Я не ожидал, что у нас это получится, и был рад ошибиться. Если интересно, мы используем Hugo в качестве генератора статических сайтов, и мы используем Webpack. А также Gulp и Grunt, поскольку нам нужные разные плагины.
За два года было создано множество вещей. Netlify сделали для нас CMS, GoTell для комментариев, GoTrue для аутентификации, GoJoin для подписки на Stripe, GoCommerce взамен Shopify, и Gotiator, также для аутентификации. Это был большой путь для нас.
Многие думают, что из-за такого подхода у нас возникает множество зависимостей. На самом деле, это не так. Все доступно и без использования JavaScript.
![](https://habrastorage.org/webt/t8/ot/vn/t8otvnzxxbevjqapzhybn4ud01c.jpeg)
Если по какой-то причине вы не можете или не хотите пользоваться JavaScript, для всех действий есть запасные механизмы (ну, комментарии пока недоступны, это нам еще предстоит исправить). Например, в поиске как запасной вариант мы просто используем Google, и затем на него накладывается JavaScript.
С точки зрения производительности нам больше всего помогло наше решение с веб-шрифтами, о котором я говорил во вчерашнем докладе. На одном этом нам удалось сэкономить 600 миллисекунд.
![](https://habrastorage.org/webt/vr/3u/gv/vr3ugv9zai_7wvfjqmgymfte_u0.jpeg)
Для отзывчивых изображений мы в устаревших статьях используем элемент picture, но также у нас работает служба Cloudinary. Кроме того, у нас работают Preload, Zopfli/Brotli и gzip. Мы используем критические CSS, а не загрузку по инициативе сервера. В развёртывании у нас пока один бандл, мы планируем перейти к 8 или 10.
![](https://habrastorage.org/webt/h4/tw/_d/h4tw_dov0wuqhujcvs22k2fmwyo.jpeg)
Попробую продемонстрировать. Перед вами — то, как выглядит CMS. Это похоже на WordPress, но, конечно, гораздо хуже. Тем не менее, с нашими задачами справляется. Лучше всего то, что всё находится в одном и том же месте, и у нас тут кастомно сделанные авторы, вакансии, события, выступления и т. Д.
![](https://habrastorage.org/webt/n-/oh/bc/n-ohbckb5igea21awkqure3yxfy.jpeg)
Производительность была невероятной. Вот вы видите результаты полугодичной давности, до того, как мы занялись оптимизациями. К примеру, мы еще ничего не сделали с веб-шрифтами. Изначально отрисовка начиналась у нас на 700 миллисекундах, сейчас, при стабильном подключении — до 0.5 секунды. Попробуйте добиться такого с любой базой данных под WordPress. Просто не получится.
Ещё остаётся много работы, но система уже работает, можете сами всё посмотреть. Людям не нравится красный цвет, можно об этом поговорить отдельно.
В качестве заключения поделюсь с вами небольшим секретом, который позволит вам сэкономить. Попробуем, например, заказать книгу на нашем сайте. Там есть окно для ввода кода купона, который даст скидку. Если же такого кода нет, а скидку хочется, что мы делаем? Правильно, мы начинаем искать код в Google. Кто из вас так делает? (Поднимаются руки). Мы в России, конечно, мы так делаем.
Я много работал в коммерции, занимался тестированием вещей, связанных с этими кодами. Как улучшить конверсию? Мы знаем по опыту, что при использовании кода «из Гугла» он будет работать в меньшинстве случаев, соответственно, будет много ошибочных вводов. К чему я всё это рассказываю? Если мы попытаемся ввести случайный купонный код в нашем окне, оно сообщит нам, что код выглядит «fishy» («подозрительно»), и предложит вместо этого ввести «FISH». А этот код уже даст нам скидку на 1%.
![](https://habrastorage.org/webt/5c/eo/od/5ceoodlq2dqvqpo3cxvcrj4-exo.png)
И пользователь, увидев это, дальше купит книгу в любом случае, даже если ему придётся для этого одолжить кредитную карту у соседа. Потому что неизвестно, что произойдёт дальше — на сайте ведь есть много ничего не значащих вещей, например, поле для галочки с подписью «мне просто нравится ставить галочки». Мы теряем здесь 1% от цены, но это куда менее обычных кодов со скидками вроде $10.
Есть еще много вещей, о которых мы могли бы поговорить позже. В целом, большую часть времени над этим проектом мы провели с удовольствием, потому что мы разбирали, как работают наиболее продвинутые на сегодняшний день технологии, и комбинировали их друг с другом. Стоит помнить о том, в каком замечательном мире мы живем, и наслаждаться им. На этой ноте я хотел бы сказать «мяу» и поблагодарить всех за участие.
![](https://habrastorage.org/webt/by/ep/7r/byep7rmfyw8qdnmc3w8dhaswemg.jpeg)
Сооснователь Smashing Magazine Виталий Фридман рассказал об этом на нашей конференции HolyJS подробнейшим образом, начав с общего дизайнерского подхода, продолжив деталями реализации фронтенда и в итоге дойдя до бэкенда. А теперь в ожидании следующей HolyJS, где Виталий выступит с новыми темами, мы сделали для вас текстовую версию этого доклада, переведя всё с английского на русский.
Получился подробнейший текст с 70 иллюстрациями (осторожно, трафик). А на случай, если вы предпочитаете смотреть англоязычный оригинал или если в нашем переводе какие-то места окажутся неясными, прикладываем и видеозапись:
Я расскажу об изменениях, произошедших со Smashing Magazine за последние два с половиной года. Раньше я никогда не участвовал в проекте, который занял бы такое время, пусть и не фуллтаймовой работы. Стоило довольно больших усилий перейти от этого варианта:
![](https://habrastorage.org/webt/tv/ob/03/tvob03_jm8e3ynmlxpadcnazquw.jpeg)
К этому:
![](https://habrastorage.org/webt/uq/qe/ge/uqqegexqeuhmggf67spi2xcbdsy.jpeg)
Если вам не нравится красный (хотя для России, наверное, такое нетипично), его можно отключить.
Сегодня я хочу осветить и дизайн, и фронтенд, и бэкенд. Знаю, что большинство из вас разработчики, но некоторые темы из дизайна будут важны. Они объясняют, почему определённые вещи мы делали определённым образом. А затем уже перейдём к фронтенду и бэкенду.
Дизайн
Для начала отвечу на вопрос «о чём вы только думали». Потому что этот вопрос я получал очень много раз. Я получал кучу писем, авторы которых были в недоумении, или озлоблены, или раздражены, а порой писали совершенно безжалостные вещи. Поэтому хочется прояснить некоторые вещи.
На мой взгляд, в случае с дизайном есть важная проблема в том, как мы понимаем креативность, рабочий процесс, взаимодействие друг с другом. Проблема заключается в нехватке индивидуальности, но не нас самих, а в индивидуальности того, что мы совместно создаём. Можете ли вы припомнить какой-либо сайт (кроме тех, которые вы сами разработали), который был бы настолько запоминающимся, что вы до сих пор о нём думаете?
Поставим вопрос шире: должны ли вообще сайты быть запоминающимися? Почему большинство из нас не помнят сайты, которые мы посещаем? Разве они не важны? Разве мы просто занимаемся созданием невидимых артефактов, не играющих какой-либо значимой роли? Я думаю, что процесс созидания (включая и собственно дизайн, и разработку) крайне сложный и странный, потому что он постоянно имеет дело с людьми и системами, а они очень часто сложные и странные.
![](https://habrastorage.org/webt/gt/_d/xs/gt_dxsretmcss-p3dony3qszeyu.jpeg)
Часто на творческий процесс смотрят так (не важно, о чём речь — дизайне, разработке, или ещё чем-то): вы начинаете в определенной точке, затем продолжаете, иногда достаточно запутанно, пока не дойдете до финишной прямой.
![](https://habrastorage.org/webt/im/_u/rb/im_urbboib72sbt3fo-kmzdkxgu.jpeg)
Но для людей, которые сами этим процессом занимаются, дело выглядит совсем иначе. Из каждой точки, в которой вы начинаете, исходят много различных возможностей, которые вы исследуете, пока не дойдете до точки, в которой ощущаете «о, это выглядит многообещающе», из которой вновь открывается пучок возможностей и т. п.
![](https://habrastorage.org/webt/5h/5a/kc/5h5akcuodhu_y57w5rthth7gffg.jpeg)
Многие возможности оказываются тупиками, из которых надо выбираться, на это теряется время. Магистральный путь к финишной черте неочевиден.
Поэтому мы обычно предпочитаем пользоваться вещами, которые уже проверены и работают. Вы могли видеть этот твит с вопросом: разработкой какого из этих двух сайтов вы заняты сейчас? Сайтом слева или справа? Потому что других вариантов-то и нет. Разве что может быть отличие в расположении карусели, иногда сверху, иногда снизу.
Мы, в особенности дизайнеры, очень сильно повернуты на пикселях. Кто из вас участвовал в спорах: давайте поменяем border-radius с 14 на 12 пикселей? А через месяц решают, что все-таки лучше 13. Имеет ли это реальное значение? Не теряем ли мы за этим перспективы?
Если мы посмотрим на эволюцию интерфейса, представленную на экране, то увидим, что за 30 чертовых лет практически ничего не поменялось, кроме border-radius и нескольких иконок тут и там.
![](https://habrastorage.org/webt/lj/wd/wh/ljwdwhjow-p7xy197hbgwe32nhw.jpeg)
Может, нам нужны более серьезные изменения? Говорят о 67 оттенках синего у Google, как там тестируют разные цвета ссылок, чтобы понять какой отклик они вызывают у пользователей. А у приложений Facebook вообще 228 вариаций значков. И у них есть традиция вводить новый тип чуть ли не каждый день и смотреть, какие результаты он дает.
![](https://habrastorage.org/webt/vn/pm/wd/vnpmwdtjztygqi-9qkywos-owbw.jpeg)
Мне очень не нравится A/B-тестирование, куда больше мне нравится тестирование A/Z, когда сравниваются принципиально разные вещи. Наверное, детали вроде порядка слов тоже надо тестировать, но при этом нельзя терять из виду перспективы. Иногда это доходит до абсурда.
Часто мы чрезмерно следуем моде. У кого из вас был следующий диалог с дизайнером: из-за iPhone Х нам крышка. Эта штуковина наверху порушит нам все, она в корне поменяет то, как люди смотрят сайты. Но на самом деле эта проблема не имеет никакого значения, поскольку 98% людей на айфонах читают страницы в интернете вертикально, а не горизонтально.
Нам очень нравятся данные. Сколько приложений люди скачивают в месяц? Почти половина — ни одного. Сколько приложений вы лично скачали в этом месяце и реально используете? Тоже, наверное, не пять?
Вот еще статистика: специализированной кнопкой «поделиться» пользуется 2 из 1000 пользователей мобильных телефонов. То же касается остальных кнопок для сайтов — «понравилось», «tweet», «LinkedIn» и так далее. И при этом люди спрашивают: а почему у вас нет специальных кнопок для социальных сетей? Поэтому как раз и нет, люди ими не пользуются.
![](https://habrastorage.org/webt/9z/yu/dx/9zyudxlww-vncrevqgh0w39hsaw.jpeg)
Или другая статистика, 90% запросов на предоставление разрешения (на пользование историей пользователя, положением и т. п.) пользователи отклоняют либо игнорируют, даже не читая. Скорее всего, большинство из вас тоже так поступает. Действительно, кому хочется делиться своей личной информацией?
Итак, нам нравятся данные, нам нравятся вещи, уже достоверно работающие. Я спросил себя: а где здесь есть место индивидуальности? Когда мы только начинали работать, мы поставили себе вопрос: не просто «что сделает нас отличными от других», а что может нам дать голос в сообществе? Я не хотел, чтобы мы были нейтральными, хотел вызывать какую-то эмоцию — быть любимыми или ненавидимыми.
![](https://habrastorage.org/webt/k3/fx/lw/k3fxlwor6qbzyowda3uzsrtns_o.jpeg)
Датский дизайнер Моуэнс Мюллер (Mogens Moller) сказал на одной из конференций несколько месяцев назад вещь, которую, в общем-то, говорят на всех конференциях. Поскольку у нас всех достаточно высокий уровень, нам всем надо выделяться на общем уровне. Нужна индивидуальность, дизайн должен быть запоминающимся, внимание к мелочам должно быть непревзойденным.
Когда я это слышу, я думаю о сайтах вроде dada-data.net, посвященном дадаизму. Сколько бы времени, ресурсов вам понадобилось на разработку этого сайта? Сколько итераций пришлось бы пройти, каким должен был бы быть бюджет? Думаю, все согласятся, что у сайта есть индивидуальность, но лично мне он не по карману. За выходные нечто подобное не собрать.
![](https://habrastorage.org/webt/cq/hy/h9/cqhyh9yy-yfdeoz4k38hxpm2-hk.jpeg)
Дальше Мюллер сказал, что надо обещать малое и давать многое, захватывать и искусно удерживать внимание, и в конечном итоге все сводится к искусству повествования, полагающемуся на выдающуюся режиссуру.
На мой взгляд, есть принципиальное различие между приложениями типа Uber и типа MailChimp. Я спросил себя: почему у меня нет совершенно никакой привязанности к Uber? Если бы появился сервис на 10 центов дешевле, я моментально бы на него перешел. Но чтобы я перестал пользоваться MailChimp, кому-то пришлось бы напрямую заплатить мне деньги. К MailChimp у меня привязанность значительно больше.
![](https://habrastorage.org/webt/ex/ld/t7/exldt7pbqn1vufylhnx0j8bw7ne.jpeg)
Я, как мне кажется, неглупый человек, я понимаю, что обезьянка здесь — это чистый маркетинг, и все же это маркетинг весьма человеческий, близкий, мне нравится индивидуальность этой компании. И этой индивидуальностью и человечностью проникнут их продукт. На мой взгляд, это крайне важно. Поэтому они создают, например, раскраски для детей и дарят их. У них нет кнопки «привет, мы прекрасная и замечательная служба электронной почты», потому что электронная почта — это скучно, если продавать только ее, никто не станет ее покупать. А в другой упаковке оно будет выглядеть значительно интереснее.
В этой раскраске, на мой взгляд, прекрасное оформление и выбор слов. «Привет! Меня зовут Фредди. Быть мной весело! А тобой?» Как можно на это ответить негативно? «Я скучен, я самый ужасный человек в мире?» Там много ещё, и последний рисунок: «Мне нравится быть мной. Тебе нравится быть тобой?» Я сам себя ненавижу, каждый день, с утра с момента как проснусь.
Другая история, которую я хочу вам рассказать, касается Tijuana Flats, сети мексиканских ресторанов в США. Вот пример их интерьера:
![](https://habrastorage.org/webt/s2/hj/hw/s2hjhwfhuofua_cvknpvjjdpjb4.jpeg)
Независимо от того, нравятся они вам или нет, я думаю, вы согласитесь, что с этой зомби-стилистикой у них есть индивидуальность. У них высокие потолки и высокие стены, и каждые четыре месяца они нанимают новых художников, которые рисуют им новые граффити. Что говорит о степени их внимания к интерьеру. Похожий стиль у них и в меню, и таким же образом был оформлен их сайт:
![](https://habrastorage.org/webt/cl/ig/rt/cligrt3vo8z00xyvnws62w0t-f0.jpeg)
Однако, как мы все знаем, параллакс и веб-шрифты — это зло, текстуры при рендеринге — зло, производительность имеет значение, и, вообще, сайт должен работать быстро и при этом поблескивать. Руководствуясь этими стандартными для нас установками, они создали для своего сайта новый дизайн, в котором, на мой взгляд, очень многое утеряно. Первоначальный вариант мне нравится больше, поскольку он отражал их индивидуальность.
![](https://habrastorage.org/webt/kx/uu/du/kxuuduytvjy6iuyezmavvivuxh4.jpeg)
На своем опыте этот урок очень хорошо усвоила компания Bloomberg. Они наняли дизайнеров и дали им полную свободу действий. Получившийся продукт можно очень много ругать, тем не менее, он прекрасен, и выполняет свою работу: билеты стали продаваться значительно быстрее, чем в предыдущий год. Когда последний раз вы пользовались тегом <marquee>?
![](https://habrastorage.org/webt/ku/ii/pr/kuiiprwehjquq1pudngwljfbtiw.jpeg)
Советуем перейти по ссылке, скриншотом это не передать
Нет ответа. Хорошо, мы работаем в JavaScript, нам этот тег не нужен. Но в целом, почему бы не пользоваться разными безумными вещами, хотя бы просто чтобы попробовать? И многими другими вещами, которыми, как считается, пользоваться «не стоит».
Взгляните на другой материал Bloomberg, который вы никогда не забудете. Зафиксируйте сейчас дату, потому что это изменит вашу жизнь. Это материал, посвященный проектам Илона Маска.
Он отматывает время в прошлое чуть ли не вплоть до 1998 года, где всё было не так, как должно быть. Сейчас можно услышать от дизайнеров, что мы живем в эпоху «брутализма» в дизайне, когда все выглядит жутким и сломанным, потому что поломанные вещи в моде. На мой взгляд, это просто отчаянные попытки различных компаний выглядеть оригинально на общем фоне, потому что иначе никто не обратит на них внимания.
А в этом проекте про Илона Маска ещё много всего, поисследуйте его самостоятельно. Ему самое место в музее.
И я задал себе вопрос: что это все означает для Smashing Magazine? Такой «сломанный» дизайн я создавать не хочу. Но мне пришли в голову несколько вариантов. Давайте возьмем что-то самое скучное или самое раздражающее всех. Скажем, кому нравятся всплывающие окна? Кажется, одному человеку в зале, и, возможно, еще кому-то, кто не готов публично в этом признаваться.
Но если вдуматься, то что в них плохого? Да, это реклама, но оформить ее можно по-разному. Представляю вам всплывающее окно с volkshotel.nl: самое раздражающее и самое прекрасное в мире всплывающее окно.
![](https://habrastorage.org/webt/za/a7/sx/zaa7sx9_lf66j5idbipqzrp1f1o.png)
Я бы хотел, чтобы у всех сайтов до единого такое было. Он такой раздражающий, что не могу прекратить его использовать! И это прекрасно сочетается с общим духом сайта, уверен, что конверсия тоже высокая.
Другой пример. Возьмем нечто крайне скучное, например, окно выбора формы обращения «мистер/миссис/мисс». Мы все знаем, зачем оно нужно на самом деле — для целевой рассылки спама по полу. Давайте попробуем поменять это окно, например, вместо свободного выбора сделать закрытый, но очень длинный список. С вариантами вроде «ваше превосходительство» и «тов. лейтенант». Этого может быть достаточно, чтобы поменять всю индивидуальность вашего сайта.
![](https://habrastorage.org/webt/jm/v5/v_/jmv5v_mgeuqdqj5ifjdblhrexi8.gif)
Или другой пример, здесь сова закрывает глаза крыльями, когда вы начинаете вводить пароль. Это мило, и иногда этого может быть вполне достаточно. Когда мы начинали свою работу, мы думали о том, как сделать такой подход к индивидуальности частью нашего сообщества.
Проблемой, с которой мы с самого начала столкнулись, были блокировщики рекламы. Если я сейчас сделаю опрос, скорее всего окажется, что 80% пользуются ими, а 20% врут в опросах. Я блокировщиком тоже пользуюсь, считаю их полезными, и вам советую, если вы его еще не установили.
Тем не менее, для нашей компании блокировщики стали проблемой, поскольку стали падать доходы от рекламы. Последние 5 лет каждый год они падали в 2 раза. Во время последней смены дизайна где-то у 12% наших пользователей были установлены блокировщики, а сейчас — у 66%. У нас аудитория из людей вроде вас, конечно, вы используете блокировщики рекламы, вы же не дураки!
Но это означает, что наша прибыль составляет 1/16 от того, что было пять лет назад. То есть возникла проблема, требующая решения. Проблема в самой рекламе, она не работает и, в любом случае, я не верю в традиционную «медийную рекламу». Нам нужно было найти другой подход, представить новый продукт, который должен стать центром всей нашей деятельности. Не хочу говорить слишком подробно, но суть в том, что это подписка, дающая доступ к Smashing TV, вебинарам и тому подобным вещам. И доступ должен происходить ко всему этому сразу.
На тот момент наша система состояла из следующих составляющих. Журнал уже работал к тому времени ни много ни мало 10 лет под старым добрым WordPress с большим количеством добавлений. Помимо этого был онлайн-магазин, работавший поначалу на Magento и затем перешедший на Shopify. Он неплохо работал, но его сложно было связать с журналом на WordPress, пока не появился плагин для Shopify. Кроме того, мы пользовались Kirby для создания статичных сайтов для Smashing.com и еще на Ruby-приложении был основан сайт с вакансиями. Все вместе связать было достаточно сложно. Чтобы создать проект, объединяющий все эти элементы, он с ними должен быть связан. Например, вы осуществляете вход один раз и затем получаете скидку в системах на WordPress, Magento, Ruby и т. п., не создавая при этом отдельного аккаунта на каждой платформе. Этот проект нам надо было написать с нуля.
![](https://habrastorage.org/webt/uw/r6/z7/uwr6z7urzz4v7ppxbhhatb0u0pg.jpeg)
Мы собрали команду, и, несмотря на то, что презентую я этот проект в одиночку, работа перечисленных на экране людей была по-настоящему важна, заняла много времени и сил. Большая часть CSS была написана Сарой Суедан (Sara Soueidan), большая часть JavaScript — Ильей Пухальским. Тут работало много людей, включая «кошачьего иллюстратора» — скоро поймёте, что это значит. И, кроме того, мы использовали Netlify в этом проекте. Проект оказался дорогим, и изначально мы хотели запустить всё к 10-летию с появления Smashing Magazine, затем к 11-летию, завершили только несколько недель тому назад. Я хочу рассказать вам о том, как мы действовали и почему.
Мы начали с текста, с названий компонентов. Это было одной из главных вещей. Мы начали с того, что посмотрели на интерфейс вот так:
![](https://habrastorage.org/webt/zc/te/h2/zcteh2oc4zl4f2c4vennkwluk0y.jpeg)
Это был мой первый набросок. Вы думаете о том, какие компоненты нужны странице или сайту, записываете их все. Он определяет то, как вы будете строить ваше взаимодействие с клиентами. У меня здесь есть прототипы микровзаимодействий: «Вы действительно хотите удалить этот файл?» Ещё не надо ничего воплощать, но надо продумать, что вам нужно, и дать этому названия. И, в частности, я с самого начала думал над сообщениями об ошибках:
![](https://habrastorage.org/webt/7i/ax/cs/7iaxcsvzp5siji2os2qnzuwyfac.jpeg)
Вне контекста это выглядит странновато, но если вы в контексте, все становится на свои места. Мне хотелось найти индивидуальность приложения. Мне хотелось, чтобы при столкновении с ошибкой вы могли улыбнуться, и превратить этот опыт в позитивный.
Затем мы перешли к выбору шрифта. Тот вариант, который мы выбрали для заголовков — я его терпеть не могу. Однако когда мы стали спрашивать у людей, с чем для них ассоциируется Smashing, то оказалось, что не с уважаемыми и профессиональными публикациями, а, например, с кошками. А мне не хотелось, чтобы моим наследием остались кошки. Поднимите руки, кому из вас нравятся кошки? А собаки? Ух ты, наверное, это единственная страна, где кошек любят больше. Обычно 40% собачников, 30% кошатников, а оставшимся наплевать на тех и других.
![](https://habrastorage.org/webt/e8/rq/sr/e8rqsrpxz3ipcs5nl_kk58h9ka0.jpeg)
Дело в том, что мы пять раз в год организуем конференции, и у каждой есть изображение кошки. Мне лично кошки совершенно не нравятся, но когда при организации первой конференции в 2012-м иллюстратор спросил меня «не нарисовать ли нам кошку», я ответил «почему бы и нет» — первая конференция, кому какое дело. А затем на второй конференции их было уже больше, пошло-поехало, и теперь все в кошках. Печально, или радостно, в зависимости от того, кошатник ли вы.
![](https://habrastorage.org/webt/lx/tn/aj/lxtnajltuqngzp50yjhtxxhbtdw.jpeg)
Я решил, что тут важнее не мои предпочтения, а то, как нас воспринимают люди. Сейчас у нас этих кошек 68 штук в разных местах в интерфейсе. Если вам удастся найти их все, я обещаю, что оплачу вам поездку в бизнес-классе на любую из наших конференций в любой точке мира, с учетом проживания, еды и чего бы вы ни захотели. Всех их вам не найти. У меня есть знакомые, которые, когда я предложил им это пари, сказали «ты не знаешь, с кем связался», и написали алгоритм с машинным обучением, который пытался искать эти картинки. Им можно только пожелать удачи, поскольку некоторые из картинок написаны в ASCII, а некоторые — в print.css.
Нам было важно взглянуть на вещи под правильным углом — причем в буквальном смысле слова. Мы экспериментировали с вёрсткой, дошли до возможности поворота и посмотрели на свой логотип, который уже был под углом. Раньше этот угол составлял 10.6 градусов, а при редизайне стал 11 градусов. Большой шаг для нас! А это значит, что все остальное также должно быть под углом в 11 градусов, как видно в нашем стайлгайде; у нас все на основе компонентов.
![](https://habrastorage.org/webt/-u/en/2b/-uen2bbof55z6u5z2tbzg-heniq.jpeg)
Небольшое отступление. На меня производит большее впечатление Airbnb. Я понимаю, что у них все совсем иначе, но мне важно то, насколько далеко они провели эту идею библиотеки шаблонов стиля. Они создали своего рода поисковый механизм для разработчиков и дизайнеров. Если вам нужен определенный рабочий процесс, тестирование определенных компонентов, вы просто набираете его, выбираете платформу и другие настройки. И вам демонстрируют, например, варианты форм логина для iPhone 6, с видом всех компонентов и обзором интерфейсов.
Затем они развили эту идею еще дальше, и назвали ее air/shots. Наверняка многие из вас видели созданную ими связку между Sketch и React. По словам Бенджамина Уокинза, они решили, что если машинное обучение может отличить друг от друга сложные, написанные от руки изображения (вроде китайских иероглифов), то наверняка можно научить ее распознавать каждый из 150 компонентов нашей системы.
![](https://habrastorage.org/webt/ud/ou/2m/udou2maagwpapbv6hfmqqevgy5a.jpeg)
Теперь можно нарисовать компонент от руки, и, проанализировав изображение, машина выдаст соответствующий React-компонент из заранее заданного набора. Меня этот подход впечатляет до крайности. Представьте, как процесс будет выглядеть в будущем.
До этого мы, конечно не дошли, но в основе нашей работы тоже лежали отдельные компоненты. Перед вами пример нашего дизайна, как видите — все под наклоном.
Другая идея, которая может, на мой взгляд, помочь уловить нашу индивидуальность. Чтобы быть последовательными, я изначально хотел использовать в коде эмодзи котов, но оказалось, что таких эмодзи слишком много и они не единообразные. Это затрудняло отладку, и идея не прошла. Но могли бы!
Мы много внимания уделили вещам вроде Print Style Sheet. Я человек ленивый, поэтому мне это казалось значительно проще, чем заниматься генерацией .pdf. Вот пример чека, сделанного таким образом, и не нужны никакие расширения. То же самое и со статьями. Мы занимались созданием электронных книг, а в них часто есть статьи. Я решил, что надо один раз потратить достаточно времени на создание Print Style Sheet, который объединял бы несколько статей в один документ, и на выходе создавалась бы книга, прилично оформленная, со ссылками и прочим.
Фронтенд
Перейдем к фронтенду. Мы начали работу над ним в декабре 2015-го и посмотрели, какими браузерами пользовалась аудитория:
![](https://habrastorage.org/webt/k_/8p/kc/k_8pkccca1j_aljwcasiesnm_y8.jpeg)
Большая часть из них хорошие, поскольку на сайт к нам приходят посетители вроде вас — вам ведь не придет в голову пользоваться IE 8, правильно? С тех пор Firefox опустился до 7%, а Chrome только набрал популярности до 66% — то есть люди переходят с IE не на Edge или Firefox, а на Chrome. Edge даже упал в популярности, с 1.2 до 0.6%. Кто из вас пользуется Edge? 0.0%? Это немного грустно. Данные немного сбивает тот факт, что раз в два года на сайт заходит пользователь с user-agent IE 666. Это, конечно, мило.
![](https://habrastorage.org/webt/1r/ht/jb/1rhtjbbztkqhbmys7r9c5ylpxri.jpeg)
Когда мы начали писать компоненты, мы следовали определенной пирамиде. Знакомы ли вы с пирамидой потребностей Маслоу? Пэтти Толанд и FilamentGroup в Бостоне пришли идея применить принцип этой пирамиды к responsive design. Самый нижний уровень — это скорость, о ней нужно думать в первую очередь при написании любой страницы или компонента. Затем идет доступность, масштабирование, и, наконец, стиль (логотипы, цвета, шрифты, анимации и т. п.).
CSS мы писали, руководствуясь этим принципом, идя снизу вверх. Мы старались не пользоваться фреймворками, не потому, что принципиально против них, а потому, что в конкретных ситуациях в них не было смысла. При использовании фреймворков слишком многое остается за кадром. Мы не хотели пользоваться чем-то избыточно большим. Нам значительно удобнее было пользоваться меньшими по размеру библиотеками. Изначально мы планировали использовать React, но затем остановились на Preact, небольшой библиотеке, имитирующей React. Возможно, скоро придется переходить на React. Причина в том, что нам пришлось написать значительно больше собственных вещей на Preact, чем мы планировали. Каждой вещью приходится заниматься отдельно, что несколько печально.
Кроме того, мы не хотели пользоваться медиа-запросами. Вы небось думаете «А с ними-то что не так?» Не то бы с ними «что-то не так», но их поддержкой достаточно сложно заниматься. Когда все рассчитано для двух разных экранов, маленького мобильного и большого компьютерного, сложности возникают посередине.
![](https://habrastorage.org/webt/68/em/q2/68emq2g4klwvyedgdcn2n2xtv0w.jpeg)
Если взять обычное приложение и сузить окно, оказавшись между двух поддерживаемых разрешений, то мы сразу увидим, как возникают «поломки», в особенности посередине страницы.
Для борьбы с этим можно добавить точку прерывания (breakpoint). А потом ещё одну. А потом ещё. А в итоге получается страшная возня при переменах в структуре страницы. Конечно, мы пользуемся вещами вроде Sass и Less, но всё равно приходится проходить по медиа-запросам и чинить их, а я не люблю заниматься починкой.
Так мы пришли к мысли о необходимости гибких размеров (fluid sizing) для всех компонентов. Как эффективно изменять размеры любого элемента UI (хоть слайдера, хоть календаря) с сохранением пропорций, но без обращений к их параметрам широты и высоты напрямую? С помощью небольшого трюка, о котором вы уже можете знать.
![](https://habrastorage.org/webt/xq/vj/x5/xqvjx5n9fgl6glydn-k-8jpr3ru.jpeg)
Есть ваш компонент. Есть размер шрифта body. Есть единица rem, она завязана на корневой элемент (body или html). 1 rem всегда равен размеру шрифта body. Если размер шрифта у компонента выставить в единицах rem, а все остальное — в единицах em, то при увеличении окна всё вырастет. Вместо того, чтобы менять все в медиа-запросе, вам просто надо указать, что мы перейдём от размера шрифта 75% к 125%. Все внутри элемента вырастет соответственно.
Но это — только первый шаг. Нам не нужно, чтобы компонент рос таким образом:
![](https://habrastorage.org/webt/ko/1q/br/ko1qbr2veometmli-z6i5r3qjnw.jpeg)
Нам не подойдёт, если элемент будет размером в 1 пиксель на небольшом экране и 500 пикселей на крупном. Рост должен быть контролируемым, он должен начинаться и прекращаться в определенных точках:
![](https://habrastorage.org/webt/wm/9o/ku/wm9okusxzmdqxvob5agtgjcrs2a.jpeg)
Попробуем сделать график, на котором по вертикальной оси будут указаны размеры шрифтов, а по горизонтальной — ширина viewport. Тогда мы сможем выстроить точки прерывания в линию. Она не будет прямой:
![](https://habrastorage.org/webt/w6/cv/rz/w6cvrz-l6r2hbk7i-9zjrpzxpbm.jpeg)
Поскольку нам всем нравится математика, эту зависимость можно описать уравнением y = mx3 + mx2 + mx + b.
В CSS такого, конечно же, никак не сделать. Может быть, это возможно в JavaScript, но все равно это абсурд. Но важна сама идея: представьте, что у каждого компонента была бы функция, определяющая его поведение. Вместо бесконечного написания точек прерывания можно один раз описать компонент, и он будет правильно отображаться на любых экранах, хоть на телевизионных. Даже если это будет приближением, оно будет достаточно точным. Можно разбить кривую на несколько прямых, каждая из которых будет определена как y = mx + b. В итоге приходишь к такому:
![](https://habrastorage.org/webt/yo/4c/9v/yo4c9vjkopiuf4jtjd7jmlbrtpy.jpeg)
Но реализовывать такое в CSS или JavaScript у вас желания, скорее всего, не возникает, не правда ли? Ну, у меня оно возникло, но делать этого действительно не стоило. В конечном итоге, нам нужно достаточно простое поведение: чтобы с определённой точки элемент начинал расти, а после определенной — переставал расти. В CSS этот принцип можно реализовать при помощи формулы:
![](https://habrastorage.org/webt/dw/i5/z2/dwi5z2bsaoflrygiqsg1rwg0_o8.jpeg)
В CSS calc позволяет совершать базовые арифметические операции. В начале формулы 16 пикселей — это минимальный размер шрифта. Затем ищется разница между максимальным и минимальным размерами. Затем идет диапазон, в котором еще может продолжаться рост, и, наконец, разница между максимальным и минимальным размерами экрана. Вот и все, что вам необходимо. И получаете что-то вроде codepen.io/MadeByMike/pen/VvwqvW.
Добавлю на всякий случай, что популярные браузеры поддерживают это, нет причин не использовать:
![](https://habrastorage.org/webt/zc/hh/er/zchherljx0c_qhmwllgre8rip8w.jpeg)
Мы подумали: почему бы не использовать этот метод вообще везде: с границами, отступом, шириной, вплоть до высоты строк. В последнем случае, опять-таки, речь идет не о неконтролируемом росте, а об изменении между 1.3 и 1.5. Принцип тут тот же, надо только пересчитать формулу.
![](https://habrastorage.org/webt/tl/ha/xm/tlhaxmsrah89ncskrrhphdmwrba.jpeg)
Есть два способа достичь этих результатов. Можно просто выставить динамический размер шрифта на элементе HTML в CSS.
![](https://habrastorage.org/webt/6n/yg/pv/6nygpv1n6hnhhevpguhf7m-uauk.jpeg)
И тогда, в зависимости от viewport, все внутренние элементы автоматически будут приведены к масштабу. Если же вам нужен контейнер фиксированного размера, вы можете просто определить fixed-container с размером шрифта в пикселях и размером внутренних компонентов в em.
Либо, наоборот, можно включать гибкое поведение для отдельного контейнера, а все остальное оставлять фиксированного размера.
![](https://habrastorage.org/webt/_m/t0/j5/_mt0j5uidqulk5ojxhkzrxbnexs.jpeg)
На этом варианте мы в итоге и остановились. Если откроете Smashing Magazine и начнёте менять ширину окна, увидите, что все составляющие меняются: ширина, высота, межстрочный интервал, размер шрифта, SVG-логотип в углу и так далее.
Конечно, для этого нужно много «волшебных» чисел в CSS. Но всё это делается через calc. Другим свойствам, возможно, несколько грустно от этого, но calc у нас — самое используемое.
Нам очень помогло организовать наше пространство имён. Вот цитата из Гарри Робертса: «Я не знаю, какая у этого функция. Я не знаю, где это еще используется. Я не знаю, можно ли это стереть, изменить, или использовать еще где-либо. Я вообще об этом ничего не знаю!» Каждый из нас сталкивался с такой ситуацией, когда вы, будучи дизайнером или разработчиком, обращаетесь к CSS и JavaScript и не понимаете, что к чему. В итоге мы стали использовать много приставок для различных компонентов, например, таких:
![](https://habrastorage.org/webt/np/59/yb/np59ybcbmslkcx_tzms2kdviycc.jpeg)
Это очень сильно помогает, когда читаешь код, сразу понятно, что к чему. Надо только понять, на каких уровнях находятся компоненты.
Конечно, мы так же пользовались BEM, для определения связей. Я предполагаю, что в России о BEM слышали. Хоть, возможно, его и не уважают из-за настойчивости, с какой его рекламирует Яндекс. Мне, кстати, эта политика непонятна, поскольку, как мне кажется, в Европе и в США BEM достаточно хорошо известен, нет нужды так агрессивно его продвигать.
Другая важная тема — это отзывчивые суффиксы, с которыми можно сделать что-то такое:
![](https://habrastorage.org/webt/r8/hi/qd/r8hiqdhlxy1oo_o3s8b5vxb37nc.jpeg)
Цель такая: из кода должно быть ясно, что он делает, без необходимости заглядывать в CSS или JavaScript. Если в классе написано «c-image-list@small-screen c-carousel@large-screen», то мне сразу становится ясно, что тут к чему. Все, что остается сделать в CSS — это поставить символ “\” перед “@”.
Некоторая часть из этого кода написана другими людьми, некоторая часть — мной.
Классы, по которым планируется провести рефакторинг, или по которым он уже проведен, мы называем с префиксом .rf-*. Благодаря этому можно, например, выделить зелёным цветом на интерфейсе все элементы, уже прошедшие рефакторинг, а красным — те, которым рефакторинг еще предстоит. Это очень удобно.
![](https://habrastorage.org/webt/y6/xt/hq/y6xthqvfnc1vyuix_-hetvvse5y.jpeg)
Другая крайне полезная вещь — это модульная сетка в CSS, то есть Grid Layout. Кто из вас о ней слышал? Оказывается, все. А кто пытался с ней поиграть? Давайте посмотрим, что при её помощи можно сделать.
Когда её пытаются рекламировать (непонятно, зачем, она и так прекрасна), зачастую показывают следующую картинку:
![](https://habrastorage.org/webt/x-/8n/wt/x-8nwtgtpgzoaugmzejfnwpimwi.jpeg)
Но это — самое жуткое введение в модульную сетку, какое только можно придумать. Оно сложное. Но сетка совершенно не обязана быть сложной. При помощи неё можно создавать и простые вещи, например, такой вот необычный дизайн:
![](https://habrastorage.org/webt/ya/d2/op/yad2opfkt1plrup4q3dzoxulria.jpeg)
Сделать его крайне просто, буквально пять минут. У Джен Симмонс на сайте есть ещё другие примеры использования Grid. И, кстати говоря, с точки зрения поддержки браузерами тут тоже не о чем беспокоиться.
Несколько вещей, которые надо знать при её использовании. Есть линии сетки, которые могут быть горизонтальными и вертикальными. Между этими линиями — дорожки сетки, на пересечении горизонтальных и вертикальных линий — ячейки сети, а несколько ячеек вместе составляют зону сети.
![](https://habrastorage.org/webt/n9/6l/-w/n96l-wct5qn9irrwteejikqri34.jpeg)
Сеть определяется через задание шаблонных столбцов grid-template-columns, и для этого можно использовать различные нотации. Например, при помощи ключевого слова repeat() можно создать несколько дорожек с одинаковыми параметрами.
![](https://habrastorage.org/webt/uj/jy/qo/ujjyqok6ov2gfv9f3tvboe23km0.jpeg)
Другая полезная функция — minmax(), позволяющая расти между двумя значениями. Предположим, у нас есть контейнер с содержимым, и есть нечто, выходящее за рамки этого контейнера.
![](https://habrastorage.org/webt/6o/z2/z1/6oz2z1fsvrmzkxs15ucm_o4gsnu.jpeg)
У нас есть простой пример построения такого контейнера:
![](https://habrastorage.org/webt/cr/fm/ca/crfmcatzpzueujploimidv6gg2a.jpeg)
Ленивый разработчик закроет контейнер, подключит изображение, снова откроет контейнер, на этом успокоится и пойдет выпить.
![](https://habrastorage.org/webt/lt/ke/5r/ltke5rooouawfg45ukyozmcv3yw.jpeg)
Пожалуйста, не поступайте так. Есть значительно лучший способ.
Саму проблему стоит представить несколько иначе. Предположим, что у нас три столбца в модульной сетке, один справа, один слева, и посередине столбец с содержимым.
![](https://habrastorage.org/webt/q7/gz/yt/q7gzytloiu_s58frairqnj43ud4.jpeg)
Первое, что мы добавляем — это supports. Если вдруг вы не знаете, это функция для определения возможностей в CSS. Ее можно использовать вместо Modernizr. Загвоздка только в том, что у supports не всё хорошо с браузерным, так сказать, support. Зато у любого браузера с суппортом supports будет и суппорт «display: grid».
![](https://habrastorage.org/webt/th/ms/3t/thms3trhftvm0nlpmip4tztxe_k.jpeg)
Далее, мы определяем столбцы сетки, и присваиваем имена линиям разделения: “full-start”, “main-start”, “main-end”, “full-end”. Этих линий всегда будет на одну больше, чем столбцов. У каждой линии может быть несколько имён.
![](https://habrastorage.org/webt/io/y5/hg/ioy5hgg0ozsxc9-r5q3vxdp7sne.jpeg)
Теперь осталось только указать: всё, что находится в контейнере, необходимо поместить в столбец main. Затем, если надо вывести что-либо за пределы контейнера, указывается “grid-column: full”, и содержимое занимает все три столбца.
Преимущество такого подхода в отсутствии медиа-запросов и, соответственно, ссылок на окно просмотра. Благодаря этому такой контейнер можно поместить внутрь другого, добавив, например, ещё и боковое меню:
![](https://habrastorage.org/webt/z0/ak/zr/z0akzrjdeuob3npsgjottn-9eua.jpeg)
Дизайнерам почему-то очень нравится идея «вертикального ритма». Я задался вопросом, как его можно реализовать. Представим структуру страницы с заголовками, текстом, изображениями, в которой все элементы должны быть выровнены по правильным линиям. На экране из двух примеров это выполнено правильно в том, который справа.
![](https://habrastorage.org/webt/1l/az/vf/1lazvf3qpochfefpkr-pxhk36cs.jpeg)
Сделать это, на самом деле, достаточно просто.
![](https://habrastorage.org/webt/jg/lq/ih/jglqihw_au88evbnj9sbnmm5ahm.jpeg)
Здесь есть тег figure, который выводится за рамки родительского контейнера (“breaks out”). Извините, что так много CSS, уж очень мне это дело нравится.
![](https://habrastorage.org/webt/1k/1p/st/1k1pst9u2oskrlajvp0ourk0tuq.jpeg)
Для body можно выставить свойство calc, затем для root выставить свойство --gutter, которое определит зазор между строками.
![](https://habrastorage.org/webt/i6/sm/g5/i6smg5jng8cfat65zu0qxtejcdg.jpeg)
И, наконец, осталось передать в grid-row-gap то значение, которое мы определили для gutter в root.
Интересно, что я тут использую единицу измерения ch, «символьную», которой редко пользуются. Достаточно часто у дизайнеров есть требование, согласно которому в каждой строке должно быть, например, 60 или 70 символов. И получается 12 дорожек по 4,85 символа.
Единица ch (character unit) основана на ширине символа «0» в данном шрифте. Лия поправит меня, если я ошибаюсь. (Голос Лии Веру из зала: «Правильно»).
Сравним два варианта:
![](https://habrastorage.org/webt/g0/yy/y0/g0yyy0fewsxw4_55h-etpm34tms.jpeg)
Из них второй, очевидно, более читаемый. На всякий случай добавлю, что, конечно же, ch уже давно поддерживается в браузерах.
Итак, структура страницы оказалась достаточно короткой. CSS стал невероятно простым. Или сложным, зависит от того, как посмотреть. Кроме того, вам, конечно же, нужно будет использовать селектор “*”.
![](https://habrastorage.org/webt/hh/db/pe/hhdbpefudw2ihxqltx0bmiqd-sm.jpeg)
Он замечателен. Вот пример его использования: элементы, попадающие под правило “* + *”, получат свойство margin: 0, и содержимое будет ограничено центральным столбцом. Все, больше ничего делать не надо. Никаких медиа-запросов не происходит. И с точки зрения гибкости и топографии, у нас все построено именно таким образом.
Выйдем на наш сайт, прокрутим страницу немного вниз… Небольшое отступление: вот мы видим кнопку, на которой написано, что она «ничего не делает».
![](https://habrastorage.org/webt/z8/r3/02/z8r302ljpqnjzgookj-2dmesybc.png)
Это тоже часть индивидуальности, которую мы пытаемся придать нашему сайту. Так вот, именно на эту кнопку чаще всего нажимают! Что не так с людьми?
Вернёмся к теме. У нас всё реализовано так, как я рассказал, и с этим подходом есть сложность. Существуют браузеры, которые поддерживают supports, но при этом достаточно плохо поддерживают модульную сетку. Например, в Edge 13 код, который я только что вам показывал, интерпретируется весьма оригинально:
![](https://habrastorage.org/webt/6i/16/vj/6i16vj4sa-mnjegqi6lhz-kre2s.jpeg)
Поэтому в коде надо заменить display: grid на grid-gap: 0, не спрашивайте почему. Потребовалось много времени, чтобы выяснить, чем это обусловлено. Сумасшествие.
Бэкенд
Под конец я хочу поговорить о бэкенде. Крайне важная тема, особенно, я думаю, для вас. Кто-то, возможно, слышал о JAM Stack. Один человек. Хм, я этого не ожидал. Ничего страшного.
Я рассказывал о том, как мы делали наш журнал на основе WordPress, все было на PHP (кроме частей на Ruby). В 2012 году я встретил Мэтта, впоследствии ставшего одним из основателей Netlify. Это платформа для автоматизации веб-проектов, использующая CDN вместо традиционных серверов, и в эту CDN они как следует вложились. Когда меня заинтересовало их творение, Мэтт продемонстрировал перенос наших ресурсов на CDN Netlify, благодаря чему производительность возрастала в три раза (при том, что мы уже на тот момент потратили много усилий для оптимизации нашего процесса на WordPress).
Этот проект занял у нас целых два года из-за того, что у нас было много параллельной с ним активности. Хотя задействовано было много людей, большая часть — это наша с Ильей работа на CSS и JavaScript. Иногда говорят, что мы ненавидим WordPress. Это не совсем так. Я его не ненавижу. Просто не особо люблю! Ну, вообще он норм — инструмент, как любой другой. Просто в определенный момент он перестал нам подходить. Мы перешли к системе на основе генераторов статичных сайтов, которую также часто называют «JavaScript, API и разметка» или JAM Stack (разметка — markup). Как она устроена?
![](https://habrastorage.org/webt/z9/hn/0i/z9hn0i6r4zx0epuprhk7yg9fzjw.jpeg)
Мы все знаем, что интерес к FTP падает и он медленно умирает, а интерес к Git растет. Кроме того, конечно, растут Gulp, Grunt и подобные им инструменты. Наконец, для них есть очень много различных API.
Вспомним историю. Изначально у нас были только взаимодействующие браузер и сервер. Затем кто-то сказал «нет, надо ещё программу для интерактивных вещей на cgi-bin и Perl». После этого сказали «и этого недостаточно», добавили базы данных на серверах, на PHP, MySQL и Apache. Но и этого оказалось недостаточно, для увеличения производительности нам нужно кэширование. Когда это было реализовано, решили, что нам нужно что? Правильно, CDN. Всё это привело к колоссальному росту числа взаимодействующих сущностей в системе:
![](https://habrastorage.org/webt/so/14/rd/so14rdxxigwalzjb_x1j3_no30w.jpeg)
И тогда-то возникла идея: возможно, нам следует вернуться к максимально простой схеме. Сделаем просто «браузер и CDN».
Работает это следующим образом. У нас есть система, которая скорее всего, присутствует также у всех вас, из Git, средств сборки и API. Код подаётся в средства сборки. Каждая статья, каждый комментарий, каждый автор, каждая вакансия записываются как файл markdown. Далее из всего этого создается HTML, добавляются CSS и JavaScript. Это затем отправляется на CDN, где к этому получает доступ пользователь. Интерактивные вещи вроде поиска и комментариев делаются при помощи JavaScript поверх всей этой системы.
Мы пользовались Preact, что часто вызывало вопрос: не возникает ли проблем с временем загрузки? Не возникает, поскольку это не одностраничное приложение, а набор одностраничных приложений. Благодаря этому для того, чтобы начать отображать наши страницы или читать статьи, JavaScript не нужен вообще. У нас нет ни единого блокирующего запроса, поскольку вы просто заходите на страницу и загружаете критический CSS наверху. Для разных страниц у нас пять или шесть блоков критических CSS. И, конечно, наше приложение является PWA («прогрессивное веб-приложение»), хотя по большому счету других сегодня, скорее всего, уже и нет.
![](https://habrastorage.org/webt/ds/lx/d8/dslxd8emb2bjwha5453lsyydcok.jpeg)
Перед нами стек, в нем ничего сложного. У нас достаточно много микросервисов и API, но ничего особо сложного не происходит. Конечно, есть проверка наличия подписки и подобные вещи. Для оплаты используется Stripe. Для «бэк-офиса» в бэкенде используется система на Go.
На меня большое впечатление произвела скорость этой системы. Скорее всего, мы были одним из первых проектов такого масштаба, перешедших на JAM Stack. Я не ожидал, что у нас это получится, и был рад ошибиться. Если интересно, мы используем Hugo в качестве генератора статических сайтов, и мы используем Webpack. А также Gulp и Grunt, поскольку нам нужные разные плагины.
За два года было создано множество вещей. Netlify сделали для нас CMS, GoTell для комментариев, GoTrue для аутентификации, GoJoin для подписки на Stripe, GoCommerce взамен Shopify, и Gotiator, также для аутентификации. Это был большой путь для нас.
Многие думают, что из-за такого подхода у нас возникает множество зависимостей. На самом деле, это не так. Все доступно и без использования JavaScript.
![](https://habrastorage.org/webt/t8/ot/vn/t8otvnzxxbevjqapzhybn4ud01c.jpeg)
Если по какой-то причине вы не можете или не хотите пользоваться JavaScript, для всех действий есть запасные механизмы (ну, комментарии пока недоступны, это нам еще предстоит исправить). Например, в поиске как запасной вариант мы просто используем Google, и затем на него накладывается JavaScript.
С точки зрения производительности нам больше всего помогло наше решение с веб-шрифтами, о котором я говорил во вчерашнем докладе. На одном этом нам удалось сэкономить 600 миллисекунд.
![](https://habrastorage.org/webt/vr/3u/gv/vr3ugv9zai_7wvfjqmgymfte_u0.jpeg)
Для отзывчивых изображений мы в устаревших статьях используем элемент picture, но также у нас работает служба Cloudinary. Кроме того, у нас работают Preload, Zopfli/Brotli и gzip. Мы используем критические CSS, а не загрузку по инициативе сервера. В развёртывании у нас пока один бандл, мы планируем перейти к 8 или 10.
![](https://habrastorage.org/webt/h4/tw/_d/h4tw_dov0wuqhujcvs22k2fmwyo.jpeg)
Попробую продемонстрировать. Перед вами — то, как выглядит CMS. Это похоже на WordPress, но, конечно, гораздо хуже. Тем не менее, с нашими задачами справляется. Лучше всего то, что всё находится в одном и том же месте, и у нас тут кастомно сделанные авторы, вакансии, события, выступления и т. Д.
![](https://habrastorage.org/webt/n-/oh/bc/n-ohbckb5igea21awkqure3yxfy.jpeg)
Производительность была невероятной. Вот вы видите результаты полугодичной давности, до того, как мы занялись оптимизациями. К примеру, мы еще ничего не сделали с веб-шрифтами. Изначально отрисовка начиналась у нас на 700 миллисекундах, сейчас, при стабильном подключении — до 0.5 секунды. Попробуйте добиться такого с любой базой данных под WordPress. Просто не получится.
Ещё остаётся много работы, но система уже работает, можете сами всё посмотреть. Людям не нравится красный цвет, можно об этом поговорить отдельно.
В качестве заключения поделюсь с вами небольшим секретом, который позволит вам сэкономить. Попробуем, например, заказать книгу на нашем сайте. Там есть окно для ввода кода купона, который даст скидку. Если же такого кода нет, а скидку хочется, что мы делаем? Правильно, мы начинаем искать код в Google. Кто из вас так делает? (Поднимаются руки). Мы в России, конечно, мы так делаем.
Я много работал в коммерции, занимался тестированием вещей, связанных с этими кодами. Как улучшить конверсию? Мы знаем по опыту, что при использовании кода «из Гугла» он будет работать в меньшинстве случаев, соответственно, будет много ошибочных вводов. К чему я всё это рассказываю? Если мы попытаемся ввести случайный купонный код в нашем окне, оно сообщит нам, что код выглядит «fishy» («подозрительно»), и предложит вместо этого ввести «FISH». А этот код уже даст нам скидку на 1%.
![](https://habrastorage.org/webt/5c/eo/od/5ceoodlq2dqvqpo3cxvcrj4-exo.png)
И пользователь, увидев это, дальше купит книгу в любом случае, даже если ему придётся для этого одолжить кредитную карту у соседа. Потому что неизвестно, что произойдёт дальше — на сайте ведь есть много ничего не значащих вещей, например, поле для галочки с подписью «мне просто нравится ставить галочки». Мы теряем здесь 1% от цены, но это куда менее обычных кодов со скидками вроде $10.
Есть еще много вещей, о которых мы могли бы поговорить позже. В целом, большую часть времени над этим проектом мы провели с удовольствием, потому что мы разбирали, как работают наиболее продвинутые на сегодняшний день технологии, и комбинировали их друг с другом. Стоит помнить о том, в каком замечательном мире мы живем, и наслаждаться им. На этой ноте я хотел бы сказать «мяу» и поблагодарить всех за участие.
![](https://habrastorage.org/webt/by/ep/7r/byep7rmfyw8qdnmc3w8dhaswemg.jpeg)
Понравился доклад? Уже на этой неделе Виталий выступит на HolyJS 2018 Piter с двумя другими: «Dirty little tricks from the dark corners of eCommerce» и «New adventures in frontend, Season 2». А благодаря дискуссионным зонам его там можно будет как следует расспросить — по темам новых докладов и не только.
Bellicus
О чём вы только думали. ©