Русский
Русский
English
Статистика
Реклама

Верстка

CSS Grid понятно для всех

05.08.2020 14:08:45 | Автор: admin

Что такое Grid?


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

Поддержка браузерами


В 2020 году поддержка браузерами достигает 94 %



Grid контейнер


Мы создаем grid контейнер, объявляя display: grid или display: inline-grid на элементе. Как только мы это сделаем, все прямые дети этого элемента станут элементами сетки.

<body> <div class="row">  <div class="row__item header">   <h1>Header</h1>  </div>  <div class="row__item nav">   <h1>Navbar</h1>  </div>  <div class="row__item article">   <h1>Article</h1>  </div>  <div class="row__item ads">   <h1>Ads</h1>  </div> </div></body>

.row { display: grid; margin: auto; grid-template-rows: 60px 1fr ; grid-template-columns: 20% 1fr 15%; grid-gap: 10px; width: 1000px; height: 1000px; justify-items: center; justify-content: space-between; grid-template-areas: "header header header" "nav article ads"; }

grid-template-rows это CSS свойство, которое определяет названия линий и путь размера функции grid rows.

CSS свойство grid-row определяет с какой строки в макете сетки будет начинаться элемент, сколько строк будет занимать элемент, или на какой строке завершится элемент в макете сетки. Является сокращенным свойством для свойств grid-row-start и grid-row-end.

Свойство CSS grid-gap является сокращенным свойством для grid-row-gap и grid-column-gap, определяющего желоба между строками и столбцами сетки.

Свойство grid-template-areas определяет шаблон сетки ссылаясь на имена областей, которые заданы с помощью свойства grid-area.

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

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

.header{grid-area: header;}.nav{grid-area: nav;}.article{grid-area: article;}.ads{grid-area: ads;}

Создаем шаблон сайта с CSS Grid:




Изменяем шаблон


Вы можете изменить шаблон просто перераспределив грид-области в grid-template-areas.

Таким образом, если мы сменим на это:

grid-template-areas: "nav header header" "nav article ads"; }

То в результате получим такой шаблон:



Гриды с медиа запросами


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

Это делает CSS Grid идеальным для медиа запросов. Мы можем просто переназначить значения в ASCII-графике и обернуть результат в конечный медиа запрос.

@media all and (max-width: 575px) {.row {grid-template-areas:"header""article""ads""nav";grid-template-rows: 80px 1fr 70px 1fr ;grid-template-columns: 1fr;}}

В результате получим:



Таким образом, все дело состоит в переназначении значений в свойстве grid-template-areas.

Заключение


В данной статье мы рассмотрели всего лишь верхушку CSS Grid Layout айсберга. Иногда сложно поверить своим глазам какие штуки удается сделать при помощи CSS Grid. Это разрыв всех шаблонов. И мне это нравится.

Я вам советую обратить внимание на данную спецификацию и потратить немного своего времени на ее изучение. Поверьте, в будущем вам это точно пригодится и не важно, пишете вы на React, Angular, Vue (вставьте свое). Gridы пришли надолго.
Подробнее..

Из песочницы Делаем модальные окна для сайта. Заботимся об удобстве и доступности

18.09.2020 12:15:01 | Автор: admin

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


Вёрстка таких окон сначала кажется простой задачей. Модальные окна можно сделать даже без помощи JS только лишь с помощью CSS, но на практике они оказываются неудобными, и из-за маленьких недочетов модальные окна раздражают посетителей сайта.


В итоге было задумано сделать собственное простое решение.



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


  • Arctic Modal,
  • jquery-modal,
  • iziModal,
  • Micromodal.js,
  • tingle.js,
  • Bootstrap Modal (из библиотеки Bootstrap) и др.

(в статье не рассматриваем решения на базе Frontend-фреймворков)


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


Что мы ждём от модальных окон? Отвечая на этот вопрос, я основывался на докладе Знакомьтесь, модальное окно Анны Селезнёвой, а так-же на относительно старой статье NikoX arcticModal jQuery-плагин для модальных окон.


Итак, чтобы нам хотелось видеть?


  • Окна должны открываться как можно быстрее, без тормозов браузера, с возможностью анимировать открытие и закрытие.
  • Под окном должен быть оверлей. Клик/тап по оверлею должен закрывать окно.
  • Страница под окном не должна прокручиваться.
  • Окон может быть несколько. Открытие одного определенного окна должно осуществляться кликом на любой элемент страницы с data-атрибутом, который мы выберем.
  • Окно может быть длинным прокручиваемым.
  • Желательно поработать над доступностью, а также с переносом фокуса внутрь окна и обратно.
  • Должно работать на IE11+

Дисклеймер: Прежде чем мы рассмотрим подробности, сразу дам ссылку на готовый код получившейся библиотеки (HystModal) на GitHub, а также ссылку на демо+документацию.


Начнём с разметки.


1. Разметка HTML и CSS


1.1. Каркас модальных окон


Как открыть окно быстро? Самое простое решение: разместить всю разметку модального окна сразу в HTML странице. Затем скрывать/показывать это окно при помощи переключения классов CSS.


Набросаем такую разметку HTML (я назвал этот скрипт hystmodal):


<div class="hystmodal" id="myModal">    <div class="hystmodal__window">        <button data-hystclose class="hystmodal__close">Close</button>          Текст модального окошка.        <img src="img/photo.jpg" alt="Изображение в окне" />    </div></div>

Итак, разместим перед закрывающим тегом </body> наш блок с окном (.hystmodal). Он будет фоном. Удобно указать уникальный атрибут id (например #myModal) каждому окну (ведь их у нас может быть несколько).


Сделаем так, чтобы .hystmodal растягивался на всё окно браузера и закрывал собой содержимое страницы. Чтобы этого добиться, установим фиксированное позиционирование в CSS и приравняем свойства top, bottom, left и right к нулю.


.hystmodal {    position: fixed;    top: 0;    bottom: 0;    right: 0;    left: 0;    overflow: hidden;    overflow-y: auto;    -webkit-overflow-scrolling: touch;    display: flex;    flex-flow: column nowrap;    justify-content: center; /* см. ниже */    align-items: center;    z-index: 99;    /* Чтобы окно не прилипало к границе    браузера установим отступы */    padding:30px 0;}

В этом коде сделаны ещё две вещи:


  1. Так как мы хотим центрировать окно внутри страницы, превращаем .hystmodal в flex-контейнер с выравниваем его потомков по центру по вертикали и горизонтали.
  2. Окно может быть больше высоты экрана браузера, поэтому мы устанавливаем overflow-y: auto, чтобы при переполнении возникала полоса прокрутки. Также, для сенсорных экранов (в основном для Safari) нам стоит установить свойство -webkit-overflow-scrolling: touch, чтобы сенсорная прокрутка работала именно на этом блоке а не на странице.

Теперь установим стили для самого окна.


.hystmodal__window {    background: #fff;    /* Установим по умолчанию ширину 600px    но она будет не больше ширины браузера */    width: 600px;    max-width: 100%;    /* Заготовка для будущих анимаций */    transition: transform 0.15s ease 0s, opacity 0.15s ease 0s;    transform: scale(1);}

Кажется возникли сложности.


Проблема 1. Если высота окна больше высоты окна браузера, то контент окна будет обрезан сверху.



Это возникает из-за свойства justify-content: center. Оно позволяет нам удобно выровнять потомков по основной оси (по вертикали), но если потомок становится больше родителя то часть его становится недоступной даже при прокручиваемом контейнере. Подробнее можно посмотреть на stackoverflow. Решение установить justify-content: flex-start, а потомку установить margin:auto. Это выровняет его по центру.


Проблема 2. В ie-11 если высота окна больше высоты окна браузера, то фон окна обрезается.


Решение: мы можем установить flex-shrink:0 потомку тогда обрезки не происходит.


Проблема 3. В браузерах кроме Chrome нет отступа от нижней границы окна (т.е. padding-bottom не сработал).


Сложно сказать баг это браузеров или наоборот соответствует спецификации, но решения два:


  • установить псевдоэлемент ::after после потомка и дать ему высоту вместо padding
  • обернуть элемент в дополнительный блок и дать отступы уже ему.

Воспользуемся вторым методом. Добавим обертку .hystmodal__wrap. Так мы заодно обойдём и проблему 1, а вместо padding у родителя установим margin-top и margin-top у самого .hystmodal__window.


Наш итоговый html:


<div class="hystmodal" id="myModal" aria-hidden="true" >    <div class="hystmodal__wrap">        <div class="hystmodal__window" role="dialog" aria-modal="true" >            <button data-hystclose class="hystmodal__close">Close</button>              <h1>Заголовок модального окна</h1>            <p>Текст модального окна ...</p>            <img src="img/photo.jpg" alt="Изображение" width="400" />            <p>Ещё текст модального окна ...</p>        </div>    </div></div>

В код также добавлены некоторые aria и role атрибуты для обеспечения доступности.


Обновленный код CSS для обертки и окна.


.hystmodal__wrap {    flex-shrink: 0;    flex-grow: 0;    width: 100%;    min-height: 100%;    margin: auto;    display: flex;    flex-flow: column nowrap;    align-items: center;    justify-content: center;}.hystmodal__window {    margin: 50px 0;    flex-shrink: 0;    flex-grow: 0;    background: #fff;    width: 600px;    max-width: 100%;    overflow: visible;    transition: transform 0.2s ease 0s, opacity 0.2s ease 0s;    transform: scale(0.9);    opacity: 0;}

1.2 Скрываем окно


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


Но этот подход нас не устроит, ведь свойство display не анимируется. Все переходы дочерних элементов, указанные в свойстве transition, работать не будут.


Нам поможет другое свойство visibility:hidden. Оно скроет окно визуально, хотя и зарезервирует под него место. А так как все будущие окна на странице имеют фиксированное
позиционирование они будут полностью скрыты и не повлияют на остальную страницу. Кроме того, на элементы с visibility:hidden нельзя установить фокус с клавиатуры, а от скрин-ридеров мы уже скрыли окна с помощью атрибута aria-hidden="true".


Добавим также классы для открытого окна:


.hystmodal--active{    visibility: visible;}.hystmodal--active .hystmodal__window{    transform: scale(1);    opacity: 1;}

1.3 Оформление подложки


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


Просто разместим элемент .hysymodal__shadow прямо перед закрывающие </body>. В будущем, сделаем так, чтобы этот элемент создавался автоматически из js при инициализации библиотеки.


Его свойства:


.hystmodal__shadow{    position: fixed;    border:none;    display: block;    width: 100%;    top: 0;    bottom: 0;    right: 0;    left: 0;    overflow: hidden;    pointer-events: none;    z-index: 98;    opacity: 0;    transition: opacity 0.15s ease;    background-color: black;}/* активная подложка */.hystmodal__shadow--show{    pointer-events: auto;    opacity: 0.6;}

1.4 Отключение прокрутки страницы


Когда модальное окна открывается, мы хотим, чтобы страница под ним не прокручивалась.
Самый простой способ этого добиться повесить overflow:hidden для body или html, когда окно открывается. Однако с этим есть проблема:


Проблема 4. В браузере Safari на iOS страница будет прокручиваться, даже если на тег html или body повешен overflow:hidden.
Решается двумя способами, либо блокированием событий прокрутки (touchmove, touchend или touchsart) из js вида:


targetElement.ontouchend = (e) => {    e.preventDefault();};

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


ps: можно конечно применить библиотеку scroll-lock, в которую заложено это решение, но в статье было решено воспользоваться другим вариантом.


Другое решение основано частично на CSS. Пусть когда окно открывается, на элемент <html> будет добавляться класс .hystmodal__opened:


.hystmodal__opened {    position: fixed;    right: 0;    left: 0;    overflow: hidden;}

Благодаря position:fixed, окно не будет прокручиваться даже в safari, однако здесь тоже не всё гладко:


Проблема 5. При открытии/закрытии окна страница прокручивается в начало.
Действительно, это происходит из-за изменения свойства position, текущая прокрутка окна сбрасывается.


Для решения, нам нужно написать следующий JS (упрощенно):


При открытии:


// Находим тег html и сохраняем егоlet html = document.documentElement;//сохраним текущую прокрутку:let scrollPosition = window.pageYOffset;//установим свойство top у html равное прокруткеhtml.style.top = -scrollPosition + "px";html.classList.add("hystmodal__opened");

При закрытии:


html.classList.remove("hystmodal__opened");//прокручиваем окно туда где оно былоwindow.scrollTo(0, scrollPosition);html.style.top = "";

Отлично, приступим к JavaScript коду.


2. Код JavaScript


2.2 Каркас библиотеки


Нам нужна совместимость со старыми браузерами включая IE11 поэтому нам нужно выбрать из 2 вариантов кодинга:


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

Основа нашей библиотеки единственный класс HystModal. Ниже я приведу скелет кода с комментариями, а потом добавим остальной функционал.


class HystModal{    /**     * При создании экземпляра класса, мы передаём в него     * js-объект с настройками. Он становится доступен     * в конструкторе класса в виде переменной props     */    constructor(props){        /**         * Для удобства некоторые свойства можно не передавать         * Мы должны заполнить их начальными значениями         * Это можно сделать применив метод Object.assign         */        let defaultConfig = {            linkAttributeName: 'data-hystmodal',            // ... здесь остальные свойства        }        this.config = Object.assign(defaultConfig, props);        // сразу вызываем метод инициализации        this.init();    }    /**      * В свойство _shadow будет заложен div с визуальной     * подложкой. Оно сделано статическим, т.к. при создании     * нескольких экземпляров класса, эта подложка нужна только     * одна     */    static _shadow = false;    init(){        /**         * Создаём триггеры состояния, полезные переменные и.т.д.         */        this.isOpened = false; // открыто ли окно        this.openedWindow = false; //ссылка на открытый .hystmodal        this._modalBlock = false; //ссылка на открытый .hystmodal__window        this.starter = false, //ссылка на элемент "открыватель" текущего окна        // (он нужен для возвращения фокуса на него)        this._nextWindows = false; //ссылка на .hystmodal который нужно открыть        this._scrollPosition = 0; //текущая прокрутка (см. выше)        /**         * ... остальное         */        // Создаём только одну подложку и вставляем её в конец body        if(!HystModal._shadow){            HystModal._shadow = document.createElement('div');            HystModal._shadow.classList.add('hystmodal__shadow');            document.body.appendChild(HystModal._shadow);        }        //Запускаем метод для обработки событий см. ниже.        this.eventsFeeler();    }    eventsFeeler(){        /**          * Нужно обработать открытие окон по клику на элементы с data-атрибутом         * который мы установили в конфигурации - this.config.linkAttributeName         *          * Здесь мы используем делегирование события клика, чтобы обойтись одним         * лишь обработчиком события на элементе html         *          */        document.addEventListener("click", function (e) {            /**             * Определяем попал ли клик на элемент,             * который открывает окно             */             const clickedlink = e.target.closest("[" + this.config.linkAttributeName + "]");            /** Если действительно клик был на              * элементе открытия окна, находим              * подходящее окно, заполняем свойства             *  _nextWindows и _starter и вызываем             *  метод open (см. ниже)             */            if (clickedlink) {                 e.preventDefault();                this.starter = clickedlink;                let targetSelector = this.starter.getAttribute(this.config.linkAttributeName);                this._nextWindows = document.querySelector(targetSelector);                this.open();                return;            }            /** Если событие вызвано на элементе             *  с data-атрибутом data-hystclose,             *  значит вызовем метод закрытия окна             */            if (e.target.closest('[data-hystclose]')) {                this.close();                return;            }        }.bind(this));        /** По стандарту, в обработчике события в this         * помещается селектор на котором события обрабатываются.         * Поэтому нам нужно вручную установить this на наш          * экземпляр класса, который мы пишем с помощью .bind().         */         //обработаем клавишу escape и tab        window.addEventListener("keydown", function (e) {               //закрытие окна по escape            if (e.which == 27 && this.isOpened) {                e.preventDefault();                this.close();                return;            }            /** Вызовем метод для управления фокусом по Tab             * и всю ответственность переложим на него             * (создадим его позже)             */             if (e.which == 9 && this.isOpened) {                this.focusCatcher(e);                return;            }        }.bind(this));    }    open(selector){        this.openedWindow = this._nextWindows;        this._modalBlock = this.openedWindow.querySelector('.hystmodal__window');        /** Вызываем метод управления скроллом         * он будет блокировать/разблокировать         * страницу в зависимости от свойства this.isOpened         */        this._bodyScrollControl();        HystModal._shadow.classList.add("hystmodal__shadow--show");        this.openedWindow.classList.add("hystmodal--active");        this.openedWindow.setAttribute('aria-hidden', 'false');        this.focusContol(); //вызываем метод перевода фокуса (см. ниже)        this.isOpened = true;    }    close(){        /**         * Метод закрытия текущего окна. Код упрощён         * подробнее в статье далее.         */        if (!this.isOpened) {            return;        }        this.openedWindow.classList.remove("hystmodal--active");        HystModal._shadow.classList.remove("hystmodal__shadow--show");        this.openedWindow.setAttribute('aria-hidden', 'true');        //возвращаем фокус на элемент которым открылось окно        this.focusContol();        //возвращаем скролл        this._bodyScrollControl();        this.isOpened = false;    }    _bodyScrollControl(){        let html = document.documentElement;        if (this.isOpened === true) {            //разблокировка страницы            html.classList.remove("hystmodal__opened");            html.style.marginRight = "";            window.scrollTo(0, this._scrollPosition);            html.style.top = "";            return;        }        //блокировка страницы        this._scrollPosition = window.pageYOffset;        html.style.top = -this._scrollPosition + "px";        html.classList.add("hystmodal__opened");    }}

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


const myModal = new HystModal({    linkAttributeName: 'data-hystmodal', });

Тогда по клику по ссылке/кнопке с атрибутом data-hystmodal, например такой: <a href="#" data-hystmodal="#myModal">Открыть окно</a> будет
открываться окно. Однако у нас появляются новые нюансы:


Проблема 6: если в браузере есть фиксированный скроллбар (который влияет на ширину страницы), то при открытии/закрытии окна происходит сдвиг контента, когда полоса прокрутки то появляется то пропадает.



Действительно скроллбар пропадает и контент страницы перераспределяется. Чтобы решить эту проблему, можно добавить отступ справа к тегу html, равный ширине скроллбара когда он пропадает.


Однако ширина скроллбара может быть разной в разных браузерах и операционных системах. Кроме того, скроллбара может не быть на коротких страницах или он может быть плавающим (например, в Chrome на Android). Поэтому ширину нужно вычислять динамически из скрипта.


Дополним метод _bodyScrollControl()


//при открытии окнаlet marginSize = window.innerWidth - html.clientWidth;//ширина скроллбара равна разнице ширины окна и ширины документа (селектора html)if (marginSize) {    html.style.marginRight = marginSize + "px";} //при закрытии окнаhtml.style.marginRight = "";

Почему код метода close() упрощён? Дело в том, что просто убирая классы CSS у элементов, мы не можем анимировать закрытие окна.


Проблема 7. При закрытии окна, свойство visibility:hidden применяется сразу и не даёт возможности анимировать закрытие окна.


Причина этого известна: свойство visibility:hidden не анимируется. Конечно, можно обойтись без анимации, но, если она нужна, сделаем следующее.


  • Создадим дополнительный CSS-класс .hystmodalmoved почти такой-же как и .hystmodal--active

.hystmodal--moved{    visibility: visible;}

  • Затем при закрытии сначала добавим этот класс к окну и повесим обработчик события transitionend на модальном окне. Затем удалим класс `.hystmodalactive, таким образом вызывая css-переход. Как только переход завершится, сработает обработчик события transitionend, в котором сделаем всё остальное и удалим сам обработчик события.

Ниже: новая версия методов закрытия окна:


close(){    if (!this.isOpened) {        return;    }    this.openedWindow.classList.add("hystmodal--moved");    this.openedWindow.addEventListener("transitionend", this._closeAfterTransition);    this.openedWindow.classList.remove("hystmodal--active");}_closeAfterTransition(){    this.openedWindow.classList.remove("hystmodal--moved");    this.openedWindow.removeEventListener("transitionend", this._closeAfterTransition);    HystModal._shadow.classList.remove("hystmodal__shadow--show");    this.openedWindow.setAttribute('aria-hidden', 'true');    this.focusContol();    this._bodyScrollControl();    this.isOpened = false;}

Вы заметили, что мы создали ещё один метод _closeAfterTransition() и перенесли основную логику закрытия туда. Это нужно, чтобы удалить обработчик события transitionend после закрытия окна, ведь в метод removeEventListener необходимо передать именно ту функцию, которую мы привязывали.


Кроме того, если анимация не будет нужна, можно просто вызвать this._closeAfterTransition() не вешая его на событие.


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


//внутри конструктораthis._closeAfterTransition = this._closeAfterTransition.bind(this)

2.2 Закрытие окна по клику на оверлей


Нам нужно обработать ещё одно событие закрытие окна по клику на элемент подложки .hystmodal__wrap. Мы можем повесить обработчик клика на документ для делегирования события как при открытии и проверить что событие произошло на .hystmodal__wrap примерно так:


document.addEventListener("click", function (e) {    const wrap = e.target.classList.contains('hystmodal__wrap');    if(!wrap) return;    e.preventDefault();    this.close();}.bind(this));

Это будет работать, но есть один малозаметный недостаток.


Проблема 8. Если кнопку мыши нажать внутри окна, а отпустить за его пределами (над подложкой), окно закрывается.


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


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


Мы могли бы решить это изменением html, добавляя ещё один div сразу после .hystmodal__window и размещая его визуально под окном. Но нам бы не хотелось добавлять лишний пустой div ещё сильнее усложняя разметку.


Мы можем разбить наш addEventListener на два отдельных обработчика: для событий mousedown и mouseup и будем проверять чтобы оба события происходили именно на .hystmodal__wrap. Добавим новые обработчики событий в наш метод eventsFeeler()


document.addEventListener('mousedown', function (e) {    /**    * Проверяем было ли нажатие над .hystmodal__wrap,    * и отмечаем это в свойстве this._overlayChecker    */    if (!e.target.classList.contains('hystmodal__wrap')) return;    this._overlayChecker = true;}.bind(this));document.addEventListener('mouseup', function (e) {    /**    * Проверяем было ли отпускание мыши над .hystmodal__wrap,    * и если нажатие тоже было на нём, то закрываем окно    * и обнуляем this._overlayChecker в любом случае    */    if (this._overlayChecker && e.target.classList.contains('hystmodal__wrap')) {        e.preventDefault();        !this._overlayChecker;        this.close();        return;    }    this._overlayChecker = false;}.bind(this));

2.3 Управление фокусом


У нас заготовлено два метода для управления фокусом: focusContol() для переноса фокуса внутрь окна и обратно при его закрытии, а также focusCatcher(event) для блокирования ухода фокуса из окна.


Решения для фокуса были реализованы аналогично js-библиотеке Micromodal (Indrashish Ghosh). А именно:


1.В служебный массив сохраним все css селекторы на которых может быть установлен фокус (свойство помещаем в init()):


//внутри метода init или конструктораthis._focusElements = [    'a[href]',    'area[href]',    'input:not([disabled]):not([type="hidden"]):not([aria-hidden])',    'select:not([disabled]):not([aria-hidden])',    'textarea:not([disabled]):not([aria-hidden])',    'button:not([disabled]):not([aria-hidden])',    'iframe',    'object',    'embed',    '[contenteditable]',    '[tabindex]:not([tabindex^="-"])'];

2.В методе focusContol() находим первый такой селектор в окне и устанавливаем на него фокус, если окно открывается. Если же окно закрывается то переводим фокус на this.starter:


focusContol(){    /** Метод переносит фокус с элемента открывающего окно     * в само окно, и обратно, когда окно закрывается     * см. далее в тексте.     */    const nodes = this.openedWindow.querySelectorAll(this._focusElements);    if (this.isOpened && this.starter) {        this.starter.focus();    } else {        if (nodes.length) nodes[0].focus();    }}

3.В методе focusCatcher() находим в окне и превращаем в массив коллекцию всех элементов на которых может быть фокус. И проверяем, если фокус должен был выйти на пределы окна, то вместо этого устанавливаем фокус снова на первый или последний элемент (ведь фокус можно переключать как по Tab так и по Shift+Tab в обратную сторону).


Результирующий код метода focusCatcher:


focusCatcher(e){    /** Метод не позволяет фокусу перейти вне окна при нажатии TAB     * элементы в окне фокусируются по кругу.     */    // Находим все элементы на которые можно сфокусироваться    const nodes = this.openedWindow.querySelectorAll(this._focusElements);    //преобразуем в массив    const nodesArray = Array.prototype.slice.call(nodes);    //если фокуса нет в окне, то вставляем фокус на первый элемент    if (!this.openedWindow.contains(document.activeElement)) {        nodesArray[0].focus();        e.preventDefault();    } else {        const focusedItemIndex = nodesArray.indexOf(document.activeElement)        if (e.shiftKey && focusedItemIndex === 0) {            //перенос фокуса на последний элемент            focusableNodes[nodesArray.length - 1].focus();        }        if (!e.shiftKey && focusedItemIndex === nodesArray.length - 1) {            //перерос фокуса на первый элемент            nodesArray[0].focus();            e.preventDefault();        }    }}

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


Проблема 9. В IE11 не работают методы Element.closest() и Object.assign().


Для поддержки Element.closest, воспользуемся полифилами для closest и matches от MDN.


Можно их вставить просто так, но так как у нас проект всё равно собирается webpack, то удобно воспользоваться пакетом element-closest-polyfill который просто вставляет этот код.


Для поддержки Object.assign, можно воспользоваться уже babel-плагином @babel/plugin-transform-object-assign


3. Заключение и ссылки


Повторяя начало статьи, всё изложенное выше, я оформил в маленькую библиотеку hystModal под MIT-лицензией. Вышло 3 кБ кода при загрузке с gzip. Ещё написал для неё подробную документацию на русском и английском языке.


Что вошло ещё в библиотеку hystModal, чего не было в статье:


  • Настройки (вкл/выкл управление фокусом, варианты закрытия, ожидание анимации закрытия)
  • Коллбеки (функции вызывающиеся перед открытием окна и после его закрытия (в них передаётся объект модального окна))
  • Добавлен запрет на какие-либо действия пока анимация закрытия окна не завершится, а также ожидание анимации закрытия текущего окна перед открытием нового (если окно открывается из другого окна).
  • Оформление кнопки-крестика закрытия в CSS
  • Минификация CSS и JS плагинами Webpack.

Если вам будет интересна эта библиотека, буду рад звёздочке в GitHub, или напишите в Issues о найденных багах. (Особенно большие проблемы, наверное, в грамматике английской версии документации, так как мои знания языка пока на начальном уровне. Связаться со мной также можно в Instagram

Подробнее..

Скачать готовую html-вёрстку письма можно с помощью плагина для Фигмы

03.12.2020 14:20:34 | Автор: admin

Речь пойдёт о Marka Email Generator. Это новый плагин для Фигмы инструмента, в котором мы работаем с дизайнами и прототипами писем.

До2019 года мызнали два способа создания вёрстки: вредакторе кода ивблочных редакторах. Идеальный блочный редактор пока неизобрели, поэтому свою агентскую вёрстку мысоздавали вредакторах кода. Донастоящего момента.

В конце 2019 года появился плагин для Фигмы, который позволяет, при соблюдении определённых правил при создании дизайн-макета, выгружать макет в готовое для отправки письмо.

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

Мы предлагали разработчику исправления и фичи, участвовали в тестировании. В процессе работы над плагином стало очевидно, что мы недооценивали потенциал продукта, ведь в новом инструменте удалось реализовать поддержку даже самых сложных подходов и особенностей email-вёрстки.

Возможности плагина

  1. Качество вёрстки науровне высококлассного верстальщика.

    К анализу и доведению до ума вёрстки, которую генерирует новый плагин для Фигмы, были привлечены наши ведущие верстальщики. Поэтому объём кода существенно снизился и сам код стал максимально соответствовать стандартам нашего агентства.

  2. Адаптивность.

    Имеется поддержка адаптивности её теперь полностью контролирует дизайнер.

  3. Поддержка Outlook.

    Вёрстка электронных писем, которую генерирует плагин, постоянно тестируется вemailonacid.comи поддерживается популярными почтовыми клиентами, включая Outlook.

  4. Поддержка произвольной базовой ширины письма.

    Оптимальной считается базовая ширина 600px, но это не закон. Часто для лучшего результата требуется большая или меньшая базовая ширина. Плагин способен на программном уровне устанавливать базовую ширину в соответствии с шириной вашего дизайн-макета.

  5. Возможность добавлять вписьмо блоки сшириной, отличной отбазовой.

    Если необходимо сделать подвал, шапку письма или какой-то акцентный блок в содержимом шириной 100%, в Marka такое возможно.

  6. Поддержка тёмных тем.

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

  7. Управление видимостью блоков надесктопе/мобильных.

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

  8. Возможность использования Google-шрифтов.

    Вы можете использовать в Фигме любой шрифт из коллекцииGoogle Fonts плагин автоматически добавит шрифты вписьмо.

  9. Автоматическая конвертация SVG-графики врастровую.

    Плагин при выгрузке кода определяет фреймы свекторной графикой ипреобразует ихвPNG-формат.

  10. Поддержка шахматных блоков.

    В дизайне иногда используются блоки с чередованием: изображение-текст, текст-изображение, изображение-текст. Тогда в адаптивной версии у этих блоков должно быть чёткое следование: изображение-текст, изображение-текст, изображение-текст. Marka может и такое.

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

    MailChimp, ExpertSender, MindBox и другие системы рассылки позволяют загружать письмо в вёрстку в виде архива и сразу кодом в html-документе, где есть относительные ссылки до изображений в архиве. Marka умеет выгружать вёрстку писем в таком формате.

  12. Опциональная автозагрузка изображений письма наоблачный хостинг.

    При активации этой опции плагин отдаст только вёрстку, авсе изображения письма будут загружены наЯндекс.Облако.

  13. Опциональная обработка текста письмаТипографом.

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

  14. Опциональная минификация кода.

    Если письмо весит больше 102кБ, почтовый клиент Gmail отобразит его неполностью.

    Если вы делаете в Marka письмо, которое не вписывается в лимит, то можно использовать опцию минификации. Она уберёт лишние символы (пробелы, переносы, комментарии) и сократит вес кода на 40%.

  15. Возможность добавления невидимого прехедера.

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

Как собирается письмо измастер-шаблона спомощью Marka Email Generator

Лучше один раз увидеть

Сравним использование плагина для Фигмы с другими способами вёрстки

Marka Email Generator удобное No-code решение с агентским качеством вёрстки писем на выходе. Marka предоставляет новый подход к процессу создание письма и новые возможности. Сравним подход Marka с другими способами создания вёрстки:


Вёрстка писем в редакторе кода

Создание письма вблочном редакторе

Использование плагина Marka

Трудозатраты

Необходим верстальщик, который воплотит вкоде дизайн письма. Наиболее трудозатратный способ.

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

Верстальщик ненужен. Письмо собирает менеджер или дизайнер.

Возможности дизайна

Ограничены уровнем верстальщика издравым смыслом.

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

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

Качество кода

Зависит отуровня верстальщика.

Вбольшинстве современных редакторов оставляет желать лучшего.

На уровне вёрстки писем агентства Email Soldiers.

Pixel Perfect попадание вёрстки в макет

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

100% Pixel Perfect

100% Pixel Perfect

Объём кода

Зависит отуровня верстальщика. При высоком уровне минимальный объём кода.

Большой. Очень большой.

Средний

Удобство модификации иповторного использования

Верстальщики повторно используют решения, ноотдизайнеров часто приходят задачи, требующие вёрстки снуля.

Посути работа строится наиспользовании готовых решений.

Работа садаптированным мастер-шаблоном напоминает работу сблочным редактором.

Боевое применение нового плагина для Фигмы

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

Одним изпервых заказчиков, для которых мыиспользовали новый инструмент, стал туроператор Алеан.

Мыадаптировали дизайн мастер-шаблона под логику Marka Email Generator. Финальная сборка писем сейчас производится настороне заказчика инапоминает работу сблочным редактором.

Ещё одна работа письма для агентства i-Media:

Что говорят клиенты

Туроператор Алеан

Анна Сахарова, интернет-маркетолог туроператора Алеан:

Технология Marka Email Generator вызвала у нас большой интерес: из макета, сделанного в Фигме, буквально за пару секунд получается письмо, свёрстанное в лучших практиках HTML.

Ребята изEmail Soldiers подготовили для нас два мастер-шаблона, сблоками, которые можно вразличных конфигурациях применять вписьмах. Изних мысоздали уже около 20разных писем. Очень трудно остановиться настандартном шаблоне, когда можно постоянно применять что-то новое ?

Что нам понравилось:

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

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

Сразу в Фигме можно обработать довольно много изображений и даже gif-анимацию и вставить в письмо.

Плагин стоит всего 7$вмесяц.

Ребята готовы помогать вработе сплагином игибко совершенствовать функционал для удобства работы сним.

Агентство интернет-рекламы i-Media

Мария Гудкова, маркетолог i-Media:

Унас вi-Media 13услуг, которые мыпродвигаем ипять отраслей бизнеса, накоторые мынацелены. Под каждую услугу иотрасль регулярно верстаем email-рассылки, отправляем дайджесты для клиентов инаших сотрудников. Вмесяц унас выходит оттрёх довосьми писем.

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

Пару месяцев назад мыодними изпервых попробовали плагин Marka Proи, если честно, очень сомневались ипереживали. Думали, что ручной труд профессионального верстальщика заменить невозможно. Номыпопробовали инепожалели.

Теперь маркетологи сами справляются совсем процессом. Тратим гораздо меньше времени исил наemail-письма. Сплагином отидеи доотправки письма проходит небольше 2часов.

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

Что говорит дизайнер

Андрей Ведерников, дизайнер Creative Soldiers:

Фигма простой графический редактор без излишеств, у неё нет, как в Фотошопе, множества функций. Но, несмотря на простоту Фигмы, в неё удалось добавить сложный плагин, от которого наши дизайнеры, верстальщики и разработчики до сих пор под впечатлением. Он генерирует html-код для писем прямо из дизайн-макета.

Подойдёт не любой дизайн-макет, а только который сделан по правилам разработчика плагина. В гайде к Marka описаны основные функции плагина для Фигмы и даны подробные разъяснения про его работу. Но главное, что нужно для успешной работы с Marka, практика. Мы до сих пор открываем для себя особенности этого инструмента.

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

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

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

Подводные камни нового плагина для Фигмы

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

Можно изучить гайд для разработчиков, но что-то придётся открывать напрямую в работе. Например, в письмах задан кёрнинг (расстояние между буквами) в 3%, а плагин для Фигмы не считал эту информацию. Приходится поправлять руками.

Ещё пример: мобильная версия рассылок работает нетак, как насайтах, ивMarka есть возможность перенести картинку наследующую строку мобильной версии, тогда как ввеб-версии картинки расположены наодной строке. Обнаружили это тоже только напрактике.

Плюсы Marka

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

Что говорит менеджер

Сергей Соболевский, интернет-маркетолог Email Soldiers:

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

Марка отлично подойдёт клиентам, укоторых нет верстальщика вштате.

Плагин для Фигмы гораздо эффективнее классических блочных редакторов: у последних много ограничений при подготовке письма.

У Marka Email Generator есть свой обучающий мануал, но подойдёт он не всем. Для правильной работы нужно разбираться в Фигме хотя бы на среднем уровне.

Подробнее..

Как я создал лучший colorpicker

18.01.2021 18:09:31 | Автор: admin

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

Начнём с самого начала. Создаём базовую HTML-разметку:

<!doctype html><html lang="en"><head>    <meta charset="UTF-8">    <meta name="viewport"          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">    <meta http-equiv="X-UA-Compatible" content="ie=edge">    <title>Document</title></head><body>    <div id="app">        <header>            <h1 id="title">Color Picker</h1>        </header>    </div>    <div id="colors-block"></div></body></html>

Далее надо вывести все цвета. Я решил выводить их на PHP, чтобы пользователь после открытия страницы уже видел палитру, а не ждал, пока это отрендерится у него на клиенте. Выводить решил в шестнадцатеричном варианте. Для этого делаем 6 вложенных циклов for и выводим блоки 1x1 px.

Код
<?php$color = '';        for($i=0;$i<15;$i++) {            $a = $i;            switch($i) {                case 10:                    $a = 'A';                    break;                case 11:                    $a = 'B';                    break;                case 12:                    $a = 'C';                    break;                case 13:                    $a = 'D';                    break;                case 14:                    $a = 'E';                    break;                case 15:                    $a = 'F';                    break;            }            for($j=0;$j<15;$j++) {                $b = $j;                switch($j) {                    case 10:                        $b = 'A';                        break;                    case 11:                        $b = 'B';                        break;                    case 12:                        $b = 'C';                        break;                    case 13:                        $b = 'D';                        break;                    case 14:                        $b = 'E';                        break;                    case 15:                        $b = 'F';                        break;                }                for($k=0;$k<15;$k++) {                    $c = $k;                    switch($k) {                        case 10:                            $c = 'A';                            break;                        case 11:                            $c = 'B';                            break;                        case 12:                            $c = 'C';                            break;                        case 13:                            $c = 'D';                            break;                        case 14:                            $c = 'E';                            break;                        case 15:                            $c = 'F';                            break;                    }                    for($l=0;$l<15;$l++) {                        $d = $l;                        switch($l) {                            case 10:                                $d = 'A';                                break;                            case 11:                                $d = 'B';                                break;                            case 12:                                $d = 'C';                                break;                            case 13:                                $d = 'D';                                break;                            case 14:                                $d = 'E';                                break;                            case 15:                                $d = 'F';                                break;                        }                        for($m=0;$m<15;$m++) {                            $e = $m;                            switch($m) {                                case 10:                                    $e = 'A';                                    break;                                case 11:                                    $e = 'B';                                    break;                                case 12:                                    $e = 'C';                                    break;                                case 13:                                    $e = 'D';                                    break;                                case 14:                                    $e = 'E';                                    break;                                case 15:                                    $e = 'F';                                    break;                            }                            for($n=0;$n<15;$n++) {                                $f = $n;                                switch($n) {                                    case 10:                                        $f = 'A';                                        break;                                    case 11:                                        $f = 'B';                                        break;                                    case 12:                                        $f = 'C';                                        break;                                    case 13:                                        $f = 'D';                                        break;                                    case 14:                                        $f = 'E';                                        break;                                    case 15:                                        $f = 'F';                                        break;                                }                                $color = "#{$a}{$b}{$c}{$d}{$e}{$f}";                                                                echo '<div class="color__item" style="width:1px; height:1px;background:'.$color.';"></div>';                                $color = '';                                                            }                        }                    }                }            }        }

Если i>=10 то заменяем на символ из шестнадцатеричной кодировки.

В итоге через пару минут ожидания я решил выключить пылесос, который почему-то лежал включенный. Но оказалось, что это не он, а кулер моего ноутбука. Я понял, что, видимо, вывожу сразу слишком много цветов, поэтому решил выводить только первые 10 000 цветов для тестирования. Получилась такая красота:

Неплохо, но попадать по цветам, слишком неудобно. Поэтому увеличим размеры "пикселей"

Отлично! Но есть одна проблема: здесь только синий цвет, но хотелось бы получить побольше. К сожалению, мой слабенький ноут не может отобразить всю палитру сразу, несмотря на то, что я не использую даже сторонних плагинов. Поэтому я решил выводить различные палитры для основных цветов в зависимости от GET-параметра. Для этого создаем меню:

<header>  <h1 id="title">Color Picker</h1>  <nav>    <ul>      <li><a href="?x=blue">Blue colors</a></li>      <li><a href="?x=green">Green colors</a></li>      <li><a href="?x=red">Red colors</a></li>    </ul>  </nav></header>

А в самом PHP и придумал хитрый способ чтобы переписывать нужны было как можно меньше. Теперь цвета выводятся вот так:

<?php$x = $_GET['x'];if ($x == 'red') {$color = "#{$e}{$f}{$c}{$d}{$a}{$b}";} elseif ($x == 'green') {$color = "#{$a}{$b}{$e}{$f}{$c}{$d}";} else {$color = "#{$a}{$b}{$c}{$d}{$e}{$f}";}$q++;if ($q <=10000) {  echo '<div class="color__item" style="width:2px; height:2px;background:'.$color.';"></div>';  $color = '';}

Что получилось:

Остальные палитры доработаю чуть позже или можете доработать их сами!)

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

<h3>Selected Color:</h3><div id="selected-color"></div><input type="hidden" id="color" name="color" value="rgb(255,255,255)">

А вот так выглядит JS:

document.querySelectorAll('.color__item').forEach((item, i, arr) => item.onclick = (e) => {document.querySelector('#selected-color').style.background = e.target.style.background; document.querySelector('#color').value = e.target.style.background});

Отлично! Теперь на все цвета вешается обработчик клика и выбранный цвет записывается в наш input[type='hidden'], который можно будет передать с остальной формой. Также мы показываем выбранный цвет пользователю

Безопасность

Не забудем и о безопасности. Так как название палитры передается как GET-параметр и обрабатывается нашим PHP, то есть вероятность XSS-инъекции! Чтобы защититься от инъекции, я позаимствовал код из этой статьи: http://personeltest.ru/aways/habr.com/ru/post/470193/ Автор показал очень простой и эффективный способ защиты, так что не будем городить костыли и воспользуемся им. Код вставлять сюда не буду, т.к. он идентичен коду в той статье, поэтому не буду дублироваться.

Теперь при открытии страницы появляется ошибка: <b>Call to undefined function mysql_real_escape_string()</b>. Я сначала хотел просто удалить эту строку, но подумал, что если кто-то из вас будет пользоваться моим кодом, то наверняка у вас будет работа с базой данных, поэтому проблему нужно решить.

Я вспомнил, что mysql в PHP устарел, и надо использовать mysqli. Поэтому соответствующим образом исправил вызов функции.

Умная IDE подсказывает, что не хватает обязательного параметра. Поэтому вторым аргументом я просто добавил true. Я нередко видел, как вторым аргументом передают булево значение. Например, в json_decode()

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

$v = mysqli_real_escape_string( $v, 'true' );

Однако, теперь ругается на первый аргумент, говоря, что аргумент должен быть объектом mysqli(), поэтому вместо "$v" я передал "new mysqli()". Он опять начал ругаться на что-то, но у меня плохо с английским, и я не понял суть. Поэтому решил забить и просто закомментировать строку. Скорее всего это баг из-за того, что PHP8 вышел лишь недавно, и многое работает криво.

Зато от XSS мы теперь защищены!

Запоминание цветов

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

<div id="save-color-block"><button id="save-color__button">Запомнить мой цвет</button></div>

Как и говорил, у меня плохо с английский языком, и я не знаю как переводится "запоминать". Поэтому, написал по-русски (приношу извинения перед англоязычными пользователями моего кода (I am sorry)).

Теперь будем сохранять данные на сервере по клику на кнопку. Для этого пользователь должен будет ввести любой ключ по которому можно будет в будущем извлечь его цвет. Для ввода ключа воспользуемся функцией prompt(), т.к. самописные модальные окна - зло, и они пользователей бесят. Затем, для отправки на сервер будем использовать fetch - никаких jQuery, axios и т.п. Ведь наша задача сделать код простым и производительным, который поддерживать и использовать будет приятно.

Код получился вот таким:

document.querySelector('#save-color__button').onclick = () => {  const color = document.querySelector('#color').value;  const key = prompt('Write your key:');  const formData = new FormData();  formData.append('key', key);  formData.append('color', color);  fetch('save-color.php', {    method: 'POST',    body: formData  }).then((response) => {    if (response.status === 200) {      alert('success!');    } else {      alert('error!');    }  })

Теперь нам нужно создать файл "save-color.php". Код его будет крайне простым

<?php$key = $_POST['key'];$value = $_POST['color'];file_put_contents($key.'.txt', $value);

Вот и всё! Теперь мы можем просто вбить в адресную строку mydomain.ru/{key}.txt и увидеть цвет, который мы выбирали!

Заключение

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

Ну и напоследок

/sarcasm

Подробнее..

SEO-friendly HTML для верстальщика

27.01.2021 18:04:51 | Автор: admin

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


В компанию ВсеИнструменты я попал больше года назад. До того момента мне еще не приходилось так тесно заниматься задачами поисковой оптимизации, а возраст и размер проекта лишь прибавляли волнения при решении seo задач. Так или иначе тот период прошел, и я не испортил своими правками уровень сайта в выдаче, благо мне помогали коллеги из SEO-подразделения.

Наш сайт, без преувеличения, состоит из огромной кодовой базы, и каждый день мы планомерно улучшаем его, добавляя новые фичи и исправляя существующие баги. Еще в начале своего пути я получил несколько крупных задач по улучшению текущей верстки проекта с использованием validator.w3.org. После окончания работ над этими задачами у меня возникла мысль собрать некоторую информацию по написанию валидной и SEO-пригодной верстки в одну небольшую статью с указанием ссылок на дополнительную и более подробную информацию.

Вы познакомитесь с несколькими важными областями валидной SEO-верстки и найдете примеры работы с validators.w3.org. Дополнительные материалы, указанные ниже, будут весьма полезны в повседневной работе верстальщика.

Семантические теги

Семантическая верстка - это html элементы со смыслом понятные разработчику, браузеру и поисковым роботам. К таким относят: header, footer, main, article, section, nav, aside и тд. Использование перечисленных тегов описывается по спецификациям W3C или WHATWG. Короткую вводную можно получить в цикле видео\статей HTML шорты от Вадима Макеева. Приведу описание к нескольким тегам.

Section - определяет раздел в документе. В соответствии со спецификацией W3C по HTML5: "Раздел это тематически сгруппированный контент, как правило с заголовком."
Article - определяет независимый, самодостаточный контент. Контент, помещенный в этот элемент, должен иметь смысл сам по себе, т. е. он должен быть понятен в отрыве от остальных частей веб-сайта.
Подробнее о article, а так же section написано здесь.
Header - предназначен для определения заголовочного блока или "шапки" документа или раздела. Подробнее здесь.
Footer - предназначен для определения "подвала" документа или раздела.
Nav - Предназначен только для основного блока навигационных ссылок.
Aside - определяет некий контент, находящийся в стороне от контента, внутри которого он расположен (как боковой блок страницы, "сайдбар").

В целом, тема доступности сайтов довольно обширна. Со всеми нюансами предлагаю ознакомиться в этой статье и еще советую пройтись по всей серии HTML шорты. Еще могу посоветовать ресурс Веб стандарты, некоторые статьи писали авторы спецификации HTML5 (переводы на русский). И для понимания, можно ознакомиться с контентной моделью HTML.

Микроразметка Schema.org

Чаще всего инструкции по включению микроразметки в HTML-код вы будете получать от SEO-специалистов. Но для понимания немного осветим эту тему.

Schema.org - стандарт семантической разметки данных, который помогает поисковикам лучше понимать данные, представленные на сайте. Например, с помощью разметки можно явно указать поисковым роботам, что на странице site.ru/product_page1 находится товар, и передать основные параметры: название, цену, артикул, производителя и т.д. На основе этих данных поисковики формируют расширенные сниппеты в поисковой выдаче.

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

Подробно о микроразметке написано в вики Яндекса. Документация Schema.org. Так же стоит обратить внимание и на гайд от Google.

Как проверить свой HTML

Так как один из критериев к SEO - это валидная верстка, необходимо прогонять написанный код через ранее упомянутый валидатор. К слову, помимо него есть валидатор от Google - в нем необходимо следить за выбранным роботом (Компьютер/Смартфон) и инструмент от Яндекса. Эти инструменты помогут Вам в задачах связанных с микроразметкой. Следует сравнивать новый и старый код, удостовериться, что ошибок нет и все существующие ранее сущности правильно считываются.

В целом, работа с ними сводится к тому, чтобы скопировать HTML код из браузера и вставить его в соответствующее текстовое поле валидатора. Можно копировать куски кода сразу из вашего IDE, но это должен быть чистый HTML с готовыми данными. После прохождения проверки вы будете получать уведомления о различных ошибках в коде. Warning можно опустить. Но от всех Error необходимо избавиться, чтобы верстка удовлетворяла принципам валидной HTML-страницы. В процессе работы могут возникнуть нерешаемые проблемы. Такое стоит гуглить и принимать во внимание, что валидаторы могут не поспевать за всеми нововведениями.

Перейдем к нескольким конкретным примерам (не)валидной верстки и их проверке с validator.w3.org.

Списки

К спискам относятся теги ul и ol (маркированные и нумерованные соответственно).
Выглядит это так:

<ul><li>item 1</li></ul><!-- или --><ol><li>item 1</li></ol>

Внутри открывающего и закрывающего тегов ul могут стоять только элементы li, а уже внутри самих этих элементов (пунктов) можно вставлять любой контент (текст, картинки, заголовки, абзацы, ссылки и даже другие списки). То есть, <ul><div></div></ul> является не валидной версией, и https://validator.w3.org/nu/ явно об этом напишет в выводе ошибок (Рис 1).

Рис 1. Ошибка спискаРис 1. Ошибка списка

Ссылки

В использовании тега <a> тоже есть нюанс, в href недопустимы пробелы. То есть, <a href="tel:+7 (967) 321-22-33">phone</a> не является валидным вариантом (Рис. 2), однако <a href="tel:+7(967)321-22-33">phone</a> соответствует всем критериям.

Рис 2. Ошибка ссылкиРис 2. Ошибка ссылки

Атрибуты

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

Таблицы

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

<table border="1" cellpadding="0" cellspacing="0" width="400"></table>

На данный код мы получим сразу 4 ошибки об устаревших атрибутах (Рис. 3).

Рис 3. Устаревшие атрибуты таблицыРис 3. Устаревшие атрибуты таблицы

Это можно спокойно переписать с использованием стилей и классов.

Резюмируя вышеописанное получим примерно такой код:

<style>.table {  border-collapse: collapse;    width: 400px;    border-spacing: 0;   }.column {    padding: 0;    border: 1px solid #333;  }</style><table class=table>  <tr>  <td class=column></td>  </tr></table>

Подобное решение относится ко всем атрибутам, влияющим на стили элементов. Но есть такие, которые относятся к логике DOM-элементов. Чаще их реализация полностью падает на браузеры. Остальное можно реализовать с помощью JavaScript.

Атрибут id

Этот атрибут является неотъемлемой частью HTML. На нем часто завязаны стили и клиентский JavaScript. Данный подход уже давно не используется ввиду усложнения поддержки написанного кода. Используя id в браузере, часто можно наткнуться на проблему отсутствия уникальности значений этого свойства. Поэтому чаще всего чистый id заменяют на data-id или более специфичные названия. У нас часто используются data-атрибуты data-behavior и data-selector. Первый подходит для взаимодействия с пользователем, второй чаще используется для манипуляций с DOM. Однако, насколько я знаю, это необязательное правило. Помимо этого, в css можно писать код с обращением в любые из свойств элементов, будь то data-* или любой другой атрибут.

Пример микроразметки

Помимо примеров валидной верстки хотелось бы привести небольшой кейс использования микроразметки Schema.org. Используя микроразметку, желательно размечать верстку, которая видна на странице и никоем образом не скрывается от пользователя при помощи opacity, visibility, display или top/left/right/bottom: -100500px. Поисковики не жалуют скрытый контент. Иногда бывают исключения, но их стоит уточнять у SEO специалистов.

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

Itemscope - задает область действия словаря в структуре данных. Как правило, работает совместно с атрибутом itemtype и задаёт пределы, где itemtype будет активен. У этого атрибута нет значений.

Itemtype - указывает адрес словаря, который будет применяться для определения свойств элемента в структуре данных. Яндекс и Google поддерживают стандарт разметки Schema.org. Соответственно, в качестве значения itemtype указывается адрес словаря на этом сайте. К примеру, для разметки организаций используется значение https://schema.org/Organization.

Itemprop - используется для добавления свойств словаря микроданных к элементу. Имя свойства определяется значением itemprop, а значение свойства определяется содержимым HTML-элемента, к примеру, текстом который располагается внутри элемента.
Приведем пример микроразметки Article.

<div itemscope="" itemtype="http://personeltest.ru/aways/schema.org/Article"><...>         <div class="article-meta">     <div       itemprop="author"       itemscope=""       itemtype="http://personeltest.ru/aways/schema.org/Person"     >       <span         itemprop="name"         class="meta-item"       >         ВсеИнструменты.ру       </span>     </div>     <time       itemprop="datePublished"       class="datetime meta-item"       datetime="{{ article.getUpdatedTimeObj().format('Y-m-d') }}"     >       {{ article.getUpdatedTimeObj().format('d.m.Y') }}     </time>   </div>   <meta      itemprop="description"      content="{{ article.getShemaOrgDescription() }}"   />   <div     itemscope     itemprop="image"     itemtype="http://personeltest.ru/away/schema.org/ImageObject"   >     <img       itemprop="url"       src="{{ article.getShemaOrgImageUrl() }}"       alt=""       class="d-none"     >   </div>   <...></div> 

В данном примере представлена микроразметка статьи. Действие микроразметки ограничено дивом с атрибутами itemscope, itemtype = Article. Внутри включает микроразметку автора статьи и дату публикации. Включает в себя также краткое описание статьи и изображение. В данном кейсе при помощи бэкенда на этапе публикации парсится весь список изображений и выдается фронтенду при помощи метода getShemaOrgImageUrl().

Я не хотел бы сильно погружаться в детальные гайды по микроразметке, поэтому просто укажу несколько полезных статей на эту тему.
1. Микроразметка для сайта интернет-магазина: как настроить разметку Schema.org для товаров и категорий
2. Микроразметка товаров

Итог

Хотелось бы, чтобы этот материал был вам полезен. Я старался предоставить информацию для работы с SEO-версткой максимально сжато. Надеюсь, я смог достичь этой цели. Данной информации не хватит для формирования по-настоящему SEO-friendly сайта, поэтому я рекомендую использовать дополнительные материалы при разработке своих страниц. Эта тема сложна и обширна. Для плодотворного продвижения и удержания позиций сайта в поисковой выдаче необходимо работать в паре с SEO-специалистом и постоянно вести работы над улучшениями своих продуктов. Спасибо за уделенное время!

Подробнее..

Боль фронтов, или что нам нужно от дизайнеров

12.02.2021 12:08:58 | Автор: admin

Вступление

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

Мифы о UI/UX-дизайнерах

Вначале я хотел бы обратить внимание на предвзятое отношение и недоверие фронтендщиков к UI/UX-дизайнерам. Далее по тексту я опущу приставку UI/UX и буду писать просто дизайнер, подразумевая именно дизайнеров интерфейсов. Выделим несколько мифов, которые мешают в коммуникации.

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

Мой дизайнер самый ленивый. Этот миф возникает, когда приходишь несколько раз с одной и той же просьбой к своему дизайнеру, но он её упорно игнорирует. Зачастую дизайнеров меньше на проекте, и они всегда завалены работой и техдолгом как я уже упоминал выше, техдолг есть не только у разработчиков). Если работа простаивает без помощи дизайнера, лучше сходить к тимлиду возможно, есть задачи, которыми можно заняться в ожидании макета. Например, настроить инфраструктуру, среду для тестирования или что-нибудь ещё. Если тимлида нет, можно спросить дизайнера, чем он занимается, и помочь ему с расстановкой приоритетов. Объясните, какие экраны нужны в первую очередь, а какие могут подождать. Возможно, ваш дизайнер готовит дизайн-систему для проекта, тогда его лучше вообще не отвлекать, ведь как и у программистов, у них всегда есть важные задачи, при работе над которыми лучше не отвлекаться. Если вам действительно что-то очень нужно, объясните почему, спросите, когда у коллеги будет возможность заняться вашим вопросом, и до этого времени постарайтесь его не беспокоить.

Мой дизайнер только рисует макеты, откуда он знает, как лучше? Этот миф распространен у Junior-разработчиков. Специально для них объясню, что дизайнеры то люди, которые прорабатывают макет не только чтобы он смотрелся красиво и современно, но и чтобы им было удобно пользоваться. Они знают множество паттернов поведения пользователя, сочетания цветов и форм, о которых мы не догадываемся, поэтому лучший совет в этом пункте: больше доверяйте своему коллеге, он наверняка знает, что делает.

Мой дизайнер самый упёртый. Наверняка каждый фронтенд-разработчик слышал нет от дизайнера, отсюда и возникает этот миф. Опираясь на предыдущие мифы, первый совет поверьте ему на слово. Если не удаётся, попробуйте получить у него больше информации, почему он говорит нет, или обратиться к его менее загруженному коллеге за разъяснением (правда, таким образом можно обидеть своего дизайнера, будьте к этому готовы).

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

Сложности с макетами

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

Следующая проблема связана с высотой блоков и вертикальными отступами между ними. Бывало, делаешь всё по макету, а при проверке на pixel perfect видишь, что вертикальные отступы отличаются. В моём случае это возникло из-за беспорядка в стилях, определяющих высоту блока. В макете высота строки (line-height) была задана в пикселях и была меньше размера основного текста (font-size), а размер блока был задан через height. При вёрстке я не смотрел на высоту блока, потому что обычно она не задается, ведь это может сломать элемент при переносе строки, и такой блок сложнее адаптировать. Высота блока должна формироваться автоматически и состоять из внутренних отступов (padding), высоты строки (line-height) и ширины рамки (border-width), при этом высота строки должна быть больше либо равна размеру шрифта (font-size). Отступы от блока считаются от внешнего края его границы, поэтому чтобы отступы и размеры блока совпадали с макетом, внимательно проверяйте все свойства. Если в них есть проблемы, постарайтесь объяснить их важность своему дизайнеру и попросите его привести эти стили в порядок. На одном из проектов мы с дизайнером договорились, что все отступы в проекте должны быть кратны определённой величине, например, четырем или восьми пикселям, тогда в случае расхождения отступов на сайте и в макете предпочтение отдаётся ближайшей кратной величине. Этот подход решает много проблем, но важно донести его тестировщику, который может прийти с багами, что отступы отличаются от макетов. Ещё рекомендация: всегда просматривайте свою вёрстку в pixel perfect, чтобы знать, где у вас явные расхождения и где вы могли что-то упустить, а где сам макет расходится с дизайн-системой.

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

Рисунок 1 внутренние отступы на примере макета кнопкиРисунок 1 внутренние отступы на примере макета кнопки

В макете отступы внутри кнопки 8px от текста до верхнего края кнопки, но при вёрстке приходится уменьшать их на ширину бордера (border-width), потому что в браузере, как правило (если box-sizing: border-box), бордер входит в высоту и ширину элемента, и внутренний отступ (padding) считается именно от его внутреннего края. Похожая проблема наблюдается, когда кнопка в макете без обводки, но при ховере обводка появляется. Тогда, если делать один-в-один с макетом, наша кнопка будет прыгать, поэтому надо самому добавлять бордер с прозрачностью. Рекомендация только одна: всегда нужно удостовериться, что ваш элемент выглядит так, как нужно.

Следующая проблема связана с прелоадерами. В решении нам поможет теория конечных автоматов. Часто сами фронтендщики грешат тем, что задают одну булевую переменную (isFetching или isLoading) для отображения прелоадера, хотя состояний там гораздо больше. Например, в случае повторного перехода на страницу, на которой уже есть кэшированные данные, произойдёт отображение контента, а потом всё исчезнет и появится прелоадер, потому что пройдет обновление данных. Согласитесь, это не очень красиво. Такая проблема возникла потому, что мы смешали состояние первичной загрузки и обновления данных, а прелоадер использовали один и тот же в обоих случаях. Решить это можно, попросив вашего дизайнера продумать все состояния. Для этого лучше описать их, либо привести пример. При этом на фронтенде нужно будет задавать переменную не в булевом виде, а перечислением состояний, и обрабатывать каждое состояние отдельно.

Раз уж зашла речь о состояниях, хочу отметить, что часто в макетах не хватает всех состояний интерактивных элементов. А их, как правило, шесть:

  • Normal сообщает, что компонент интерактивен и включен.

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

  • Hover сообщает, когда пользователь навел курсор на интерактивный элемент.

  • Active активное или нажатое состояние сообщает о том, что пользователь нажал на кнопку.

  • Progress/Loading используется, когда действие не выполняется немедленно и сообщает, что компонент находится в процессе завершения действия.

  • Disabled сообщает, что компонент в настоящее время не является интерактивным, но может быть включен в будущем.

Часто про это забывают, и некоторые состояния сливаются. Сами фронтенд-разработчики иногда объединяют hover и focus в один стиль, что является ошибкой. Постарайтесь обсудить это со своим дизайнером до старта работ, потому что такие решения влияют на доступность вашего продукта. Самый жизненный пример вы кликнули на кнопку, а потом убираете с неё курсор, но она как будто остаётся в состоянии ховера.

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

Следующая сложность возникает, когда стайлгайд используется неправильно. Например, есть шрифты для десктопной версии Heading-1 и мобильной версии MobileHeading-1, но в макете Heading-1 в десктопе в мобильной версии неожиданно становится Heading-3. С этим очень сложно работать, потому что вся система, которую я делал на фронте по стайлгайду, начинает рушиться прямо в этом месте. Основной посыл: если есть стайлгайд или дизайн-система, старайтесь максимально ей соответствовать. Например, если дизайнер спрашивает, нужно ли добавлять в стайлгайд немного изменённую кнопку, однозначно говорите да.

Отдельно поговорим об адапативности. Как правило, вёрстка бывает адаптивная и резиновая. Адаптивная подстраивается под конкретные заданные разрешения экрана, а резиновая плавно изменяется, подстраиваясь под любую ширину экрана. На мой взгляд, резиновая вёрстка более современная и универсальная, а ее создание не вызывает трудностей, потому что в арсенале есть flex-box, grid, vw/vh, математические функции и прочее,. Однако, все давно привыкли к бутстраповским брекйпоинтам, и большинство макетов опираются именно на них. Хорошо, если в макете есть хотя бы три состояния: десктоп (как правило, 1440px), планшет (часто это 1024px или 768px) и телефон (320px или 375px). Именно с этого места обычно начинаются проблемы. Приходит заказчик и говорит, что на его моноблоке, у которого разрешение 2500px, сайт выглядит ужасно. Потом приходит аналитик и говорит, что сайт плохо выглядит на его ноутбуке, с разрешением в 1380px и так далее. Здесь описано сразу две проблемы.

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

Вторая проблема промежуточные состояния в макетах. Если размышлять адаптивно, а не резиново, все версии, отображаемые в макете, используются для состояний выше указанного, то есть макет на 1440px подходит для экранов шириной от 1440px и выше до следующего брейкпоинта (если он есть, конечно). Если ширина экрана меньше указанной в макете, должна отображаться версия для предыдущего брейкпоинта. Например, у вас в макете есть состояние на 1440px и 768px, на ширине в 1380px должна отображаться версия на 768px с ограничением ширины контентной области в соответствии с макетом. Выглядеть это будет не очень, мягко говоря. Худший сценарий, когда между брейкпоинтами большой разрыв. Например, дизайнер отобразил состояние на 1920px и на 768px. Тогда, следуя прямой логике, на 1440px включится состояние 768px, но так быть не должно. Суть проблемы в том, что, глядя на макеты в трёх разрешениях, фронтендщик не всегда понимает, какое состояние и в какой момент должно включиться. Если рассмотреть этот пример на резиновой вёрстке, на ширине экрана в 1380px должен отображаться макет для версии в 1440px, а на ширине 1110px версия для 1024px. Здесь возникают вопросы: в какой момент должна включаться какая из версий? До какой ширины экрана будет отображаться версия в 1024px? рассмотрим потенциальные варианты решений. Первый пойти к дизайнеру и описать проблему. Наверняка у него уже есть видение, как сайт должен меняться при сжатии и расширении экрана, он объяснит вам хотя бы на словах, однако это не всегда работает. Второй вариант отвязать свой разум от бутстраповских брейкпоинтов и рассматреть каждый блок как независимый. Потом я начинаю сжимать и разжимать каждый блок, наблюдая за его поведением, и определяю оптимальное разрешение для смены состояния. Многим верстальщикам такой подход не нравится и кажется избыточным. Основной аргумент возможно появление множества брейкпоинтов, но как показывает практика, этих состояний вряд ли будет больше шести, и все они будут инкапсулированы внутри своих блоков и ни на что не повлияют. Однако, ваш макет будет действительно резиновый и сможет подстраиваться под любое разрешение экрана.

Чем дизайнер может помочь фронтенд-разработчику

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

  • Комментарии к макетам. Невозможно всё отобразить в макете, и в этом нет необходимости, но некоторую информацию лучше описать в комментариях. Конечно, можно передавать информацию устно, но если фронтенд-разработчиков много, будьте готовы объяснять каждому отдельно. Усложнится и процесс онбординга новых людей, потому что можно просто забыть, почему было принято то или иное решение.

  • История изменения макетов. Часто при работе над макетом неожиданно обновляются требования к продукту, и в макет вносят изменения. Фронтендщику ставят задачу на перевёрстку, но, на первый взгляд, все выглядит, как раньше. Только при более детальном исследовании выясняется, что поменялся, например, порядок иконок социальных сетей в футере, изменились некоторые отступы в контентной области или изменились некоторые тексты на странице. Чтобы это выяснить, приходится делать скриншот макета и сопоставлять его с текущей вёрсткой сайта. В Figma на данный момент нет системы контроля версий, поэтому всё ложится на плечи команды. И только коммуникация помогает решить данную проблему.

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

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

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

  • Структура проекта в Figma. Многие разработчики жаловались мне, что невозможно открыть Figma, потому что на одной вкладке отображаются все страницы проекта. Правильная структура хранения проекта облегчит работу с ним как дизайнеру, так и разработчику.

  • Названия у цветов и шрифтов. Когда у всех цветов и типов шрифтов есть имена, фронтенд разработчику не придётся их придумывать. Идеально, если имена содержат только буквы, цифры и знаки $ и _, при этом первый символ не является цифрой. Это необязательно, но позволит использовать названия прямо в коде, что облегчит их применение и поддержку в актуальном состоянии.

  • Консистентность между версиями. Это, скорее, просьба к дизайнерам. Разрабатывая макет мобильной версии сайта, старайтесь помнить, что это всё-таки сайт, а не мобильное приложение. Хочется видеть консистентность между десктопной и мобильной версиями. В некоторых проектах мобильная и десктопная версии настолько отличались, что приходилось делать разные версии с нуля, а это забирает в два раза больше времени на разработку.

Что следует знать дизайнерам о фронтенде

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

    • box-sizing определяет, как вычисляется общая ширина и высота элемента;

    • margin определяет внешний отступ;

    • padding определяет внутренний отступ;

    • border отвечает за все персональные свойства границ;

    • overflow работает с переполнением;

    • flex/grid наиболее популярные типы отображения элементов.

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

  • Отличие блочных элементов от строчных. Это позволит глубже понять композицию веб-страницы.

  • Браузерные инструменты разработчика упростят процесс проведения авторского надзора и помогут проверить некоторые гипотезы непосредственно в рабочей среде.

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

Что следует знать фронтендщику о дизайне и не только

  • Сетка. Практически все макеты строятся на основе сетки. Зная её, верстать становится проще, а учитывая, что теперь у нас есть grid, это превращается в удовольствие.

  • Основы Figma. Говорить с дизайнером на одном языке и понимать особенности и отличия вёрстки в Figma и WEB-е.

  • БЭМ. Неважно, как вы верстаете, будь то CSS-in-JS или CSS-modules, методология позволяет навести порядок в голове и мыслить правильными категориями.

  • Наследование стилей. Многие CSS свойства наследуются от родительского блока, в Figma это отсутствует.Чтобы не переписывать все стили, не глядя , помните, какие свойства берутся от родителя, а какие объявляются в самом элементе.

  • Конечные автоматы. Понимать, сколько состояний может быть у того или иного элемента на странице.

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

Заключение

В этой статье я осветил только часть того моста, который перекинут между двумя берегами фронтенда и UI/UX-дизайна. Надеюсь, мой опыт поможет фронтенд-разработчикам и дизайнерам чуть лучше понять друг друга.

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

P. S. (постскриптум)

За помощь в подготовке материала благодарю самого крутого из дизайнеров Олега Ровного.

Подробнее..

Сердце, не познавшее боли разочарования, не знало и радости полёта

18.02.2021 14:23:54 | Автор: admin

The Host (Stephenie Meyer)


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



Думаю, в недалеком будущем No-Code/Low-Code продукты сделают свое дело, и UI/UX и фронтендеры уже не будут знать, что это такое, когда глаз дергается синхронно с кнопкой в веб-версии макета. А что сейчас? Чтобы дизайнеру и фронту было проще ужиться друг с другом, а их совместная работа упростилась, мы придумали Quarkly.



Сооснователи проекта Саша и Артем не понаслышке знакомы со всеми болячками, которые возникают во время коммуникации дизайнера и фронта. Александр фулстек-разработчик, Артем UI/UX. В данном случае, что называется, карты сошлись.


В Quarkly мы стремимся к пресловутому Low-Code и даже No-Code при сборке сайтов и веб-приложений, и когда мы запустим в релиз каталог-маркетплейс готовых компонентов, это станет в целом очень даже возможным.


По состоянию на февраль 2021 года маркетплейса у нас пока нет, но есть весь базовый набор инструментов как для дизайнера, привыкшего делать макеты/прототипы в популярных дизайн-инструментах (Figma, Framer), так и для разработчика.


Уже сейчас готовый макет из Figma не без труда, но довольно быстро можно перетащить в Quarkly, ниже оставляю туториал с русскими и английскими субтитрами:




За счет чего Quarkly поможет снять боль


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


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


  1. Дизайнер и фронт работают, как они привыкли каждый это делать дизайнер создает макет в Figma, далее фронт переносит всё в код;
  2. Дизайнер и фронт совместно создают проект в Quarkly.

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



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


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


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


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



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



Наш канал на YouTube, где можно найти полезные мануалы: смотреть


Наш чат в телеграме: https://t.me/quarklyapp

Подробнее..

Перевод Примеры применения переменных CSS на практике

30.04.2021 14:04:59 | Автор: admin

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


Если вы ещё не работали с переменными CSS, рекомендую прочитать эту статью, чтобы познакомиться с ними. Как только вы их освоите, работа станет намного проще. Цель этой статьи сосредоточить внимание на разных случаях практического использования переменных CSS помимо их применения для создания маркеров дизайна, таких как цвета.

Вы готовы? Тогда вперёд!

В чём основная проблема?

Если вы используете переменные CSS так же, как и препроцессоры CSS (например в Sass), то вы не полностью реализуете все их преимущества. Рассмотрите следующий пример:

:root {    --brand-primary: #7777e9;    --brand-secondary: #c96fde;}.title {    color: var(--brand-primary);}

И тут нет никакой разницы с нижеприведённым примером в Sass:

$brand-primary: #7777e9;$brand-secondary: #c96fde;.title {    color: $brand-primary;}

Да, применение переменных CSS в качестве переменных цвета ни в коей мере не является ошибкой. Но это всё равно, что покупать Apple MacBook M1 для посещения интернет-сайтов, хотя с этим и так хорошо справляется ваш старый настольный ПК, собранный в 2012 году. Какой смысл покупать ультрасовременный компьютер и делать на нём то же самое, никак не используя весь спектр его возможностей? Как вы понимаете, примерно так я и думаю об использовании переменных CSS для сохранения информации о цветах.

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

Примеры и случаи практического использования

Полные формы записи свойств

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

<!-- Base component --><header class="page-header">    <h2>...</h2>    <p>...</p></header><!-- Component variation --><header class="page-header page-header--compact">    <h2>...</h2>    <p>...</p></header>
.page-header {    --padding-start: 2.5rem;    --padding-block: 2rem;    padding: var(--padding-block) 1rem var(--padding-block) var(--padding-start);}.page-header--compact {    --padding-start: 1.5rem;    --padding-block: 1rem;}

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

.page-header {    padding: 2rem 1rem 2rem 1.5rem;}.page-header--compact {    padding: 1rem 1rem 1rem 2.5rem;}

Всё вышесказанное применимо и для свойства внешнего отступа margin.

Свойства CSS background

Что касается свойств CSS для работы с фоном, то и здесь переменные CSS помогают сократить объём создаваемого нами кода. И даже больше того: благодаря их применению сам код CSS легче читать.

Хранение значений URL

При работе с интерфейсом пользователя вам может потребоваться добавить какое-либо изображение в декоративных целях. В таком случае хорошим решением будет использование элементов <div> и background-image. Если интерфейс должен быть динамическим, то значения для изображения нужно подставлять с помощью JavaScript.

Без применения переменных CSS соответствующий код HTML будет выглядеть так:

<section     class="newsletter"     style="background-image: url('/assets/ui/decoraitve/newsletter-lg-aj1891101.svg')"></section>

Но вместо того, чтобы напрямую изменять свойство background-image, мы можем сделать следующее.

<section     class="newsletter"     style="--thumb:url('/assets/ui/decoraitve/newsletter-lg-aj1891101.svg')"></section>
.newsletter {    background-image: var(--thumb);    background-size: cover;    background-position: 100% 50%;}

Обратите внимание, что необходимо включить элемент url() без переменной CSS.

Положение фонового изображения

В приведённом выше примере фоновое изображение помещается справа. Для макетов с направлением текста справа налево (RTL) положение фона следует перевернуть.

.newsletter {    --pos: 100% 50%;    background-image: var(--thumb);    background-size: cover;    background-position: 100% 50%;}html[dir="rtl] .newsletter {    -background-position: 0% 50%;}

Чтобы упростить эту задачу, мы можем воспользоваться переменными CSS.

.newsletter {    /* other styles */    background-position: var(--pos);}html[dir="rtl] .newsletter {    --pos: 0% 50%;}

Угловой градиент: часть 1

Угловой градиент также можно применять при создании макетов для нескольких языков. По умолчанию он может быть равен 45deg, и, возможно, потребуется изменить его на -45deg для макетов RTL.

.element {    --angle: 90deg;    background: linear-gradient(var(--angle), #4088vb, #C05858);}html[dir="rtl] .element {    --angle: -90deg;}

Угловой градиент: часть 2

В случае с угловым градиентом использование переменных CSS с радиальными градиентами действительно существенно упрощает настройку положения. В следующем примере положение градиента изменяется при помощи переменной --pos.

А здесь показано, как можно сделать то же самое без переменных CSS.

.card {    background: radial-gradient(        circle 200px at center top,        rgba(64, 136, 203, 0.5),        #f7f7f7    );}

Теперь предположим, что у нас есть какой-то вариант карточки .card-2 и он должен находиться в другом положении. Необходимо написать следующий код:

.card-2 {    background: radial-gradient(        circle 200px at center top,        rgba(64, 136, 203, 0.5),        #f7f7f7    );}

Таким образом, переписывается всё определение градиента. Можно ли сделать лучше? Определённо. Обратите внимание, что единственным настраиваемым значением для этого варианта является переменная --pos.

.card {    --pos: center top;    background: radial-gradient(        circle 200px at var(--pos),        rgba(64, 136, 203, 0.5),        #f7f7f7    );}.card-2 {    --pos: left top;}

Свойство clip-path

Весьма полезным случаем использования переменной CSS является изменение с её помощью значений clip-path: polygon() при переходе с настольных на мобильные устройства.

На показанном выше рисунке необходимо изменить положение вершин многоугольника. С помощью переменных CSS сделать это намного проще.

.hero {    --first: 4% 7%;    --second: 80% 0;    --thrid: 100% 95%;    --fourth: 10% 100%;    clip-path: polygon(var(--first), var(--second), var(--thrid), var(--fourth));}@media (min-width: 40rem) {    .hero {        --second: 96% 0;        --thrid: 92% 82%;    }}

Если вы хотите узнать больше о свойстве CSS clip-path, здесь вы найдёте статью за авторством вашего покорного слуги.

Элемент флажка

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

Первое, что я сделал, это определил значения hsla() для корневого элемента компонента.

.form-item {    --primary-h: 240;    --primary-s: 56%;    --primary-l: 63%;    --primary-alpha: 100%;}

Теперь я могу использовать эти свойства в функции определения цветов hsla().

/* The circle that appears on hover */.form-item__label:after {    --primary-alpha: 0;    background-color: hsla(        var(--primary-h),        var(--primary-s),        var(--primary-l),        var(--primary-alpha)    );}.form-item__label:hover:after {    --primary-alpha: 15%;}

Код SVG, встроенный в CSS

Когда-то я работал над пользовательским интерфейсом для проекта одного клиента и столкнулся с такой ситуацией. У нас был раздел с двумя лентами (одна сверху, а вторая снизу). Мне необходимо было изменить цвет, угол поворота и размер этих лент, не создавая отдельный код CSS для каждой из них. Спасением стали переменные CSS!

Прежде всего я подготовил требуемый код SVG в Adobe Illustrator. Я разделил каждую ленту на три слоя:

  • светлые области;

  • тёмные области;

  • базовый слой.

Затем я экспортировал этот код SVG и поместил его в элементах <defs> так, чтобы легко можно было использовать его повторно. Обратите внимание, я также добавил ключевое слово currentColor! Это и есть то самое магическое значение, которое заставит всё работать.

Наконец, теперь нам необходимо определить размер и угол поворота в CSS.

.tape {    width: var(--size);    transform: rotate(var(--angle));}
<svg class="tape" style="--angle: 10deg; color: red; --size: 120px;" aria-hidden="true" focusable="false" viewBox="0 0 123 47">  <use href="#tape"></use></svg>

Готово. Мы создали собственный код SVG, который можно настраивать по мере необходимости. Впечатляет, не правда ли?

Создание миксинов (примесей-шаблонов), таких, как в Sass

Об этой интересной возможности я узнал из рекомендуемого мною к просмотру выступления Ли Веру (Lea Verou). Идея состоит в том, чтобы установить исходные переменные CSS для определённого свойства, а затем переопределять их, когда это понадобится.

Здесь показан пример, как мы можем использовать эту возможность. Очень часто мне необходимо, чтобы враппер был центрирован, для чего можно добавить margin: 0 auto к соответствующему элементу враппера. В тех случаях, когда необходимо отцентрировать какой-то свой элемент, мы можем выполнить следующее:

<div class="featured-section u-center"></div>
.u-center {  --mx: initial;  --my: initial;  margin: var(--my) var(--mx);}.featured-section {  --mx: auto;  --my: 2rem;}

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

Использование функции calc()

Функция calc() в сочетании с переменными CSS может очень пригодиться. Мы можем создать какой-то базовый размер для компонента, а затем, меняя только одну переменную, можем делать его больше или меньше.

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

.c-avatar {  width: calc(var(--size, 32) * 1px);  height: calc(var(--size, 32) * 1px);}

Обратите внимание, я использовал функцию var(--size, 32). Если переменная --size не определена, то значение 32 будет использовано как резервное значение. Важно указать 1px, чтобы добавить px к результирующему числу.

Таким образом, мы можем создавать вариации классов, просто добавляя переменную CSS --size.

.c-avatar--medium {    --size: 64;}.c-avatar--large {    --size: 128;}

Псевдоэлементы

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

В заголовке раздела содержится декоративная фиолетовая линия, которая является псевдоэлементом. Мы можем передать переменную CSS данному заголовку, и этот псевдоэлемент унаследует её.

.section-title {    --dot-color: #829be9;}.section-title:before {    content: "";    background-color: var(--dot-color);}

Но, кроме того, мы также можем имитировать изменение цвета псевдоэлемента с помощью Javascript.

Встроенные стили

Другим примером полезного применения переменных CSS является использование их в качестве встроенных стилей. И тут открывается множество возможностей для настройки какого-либо компонента путём изменения одной или нескольких переменных.

Рассмотрите следующий пример.

.o-grid {    display: grid;    grid-template-columns: repeat(auto-fit, minmax(var(--item-width, 200px), 1fr);    grid-gap: var(--gap);}

У нас есть настроенный грид и заданное по умолчанию для ширины элемента грида значение 200px. В коде HTML мы можем переопределить его, переустановив значение для переменной CSS.

<!-- Example 1 --><div class="o-grid" style="--item-width: 250px;">     <div></div>     <div></div>     <div></div></div><!-- Example 2 --><div class="o-grid" style="--item-width: 350px;">     <div></div>     <div></div>     <div></div></div>

Ну разве это не полезно? Если вы хотите узнать больше о переменных CSS со встроенными стилями, я уже писал об этом более подробно.

Заключение

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

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

Узнайте, как прокачаться и в других специальностях или освоить их с нуля:

Другие профессии и курсы
Подробнее..

Как я сделал свою сборку Gulp для быстрой, лёгкой и приятной вёрстки

03.06.2021 18:21:18 | Автор: admin

Серьёзно и профессионально я начал заниматься вёрсткой в 2019 году, хотя до этого ещё со школы интересовался данной темой как любитель. Поэтому новичком мне себя назвать сложно, но и профессионалом с опытом 5+ лет я тоже не являюсь. Тем не менее, я успел познакомиться со сборщиком Gulp, его плагинами и сделал для себя хорошую, как по мне, сборку для работы. О её возможностях сегодня и расскажу.

ВАЖНО! В этой статье речь пойдёт о самой последней версии сборки. Если вы пользуетесь версиями сборки, вышедшими до публикации этой статьи, информация будет для вас не релевантна, но полезна.

Какие задачи решает эта сборка?

  • вёрстка компонентами (вам не нужно в каждую страницу копировать head, header, footer и другие повторяющиеся элементы, вплоть до кнопок или кастомных чекбоксов);

  • вёрстка с препроцессорами (SASS/SCSS);

  • конвертация шрифтов из ttf в eot, woff, woff2;

  • лёгкое (почти автоматическое) подключение шрифтов;

  • лёгкое (почти автоматическое) создание псевдоэлементов-иконок;

  • обработка изображений "на лету";

  • минификация html/css/js файлов;

  • возможность вёрстки с использованием php;

  • выгрузка файлов на хостинг по FTP;

  • несколько мелких задач с помощью миксинов.

Для тех, кому лень читать и делать всё руками - сразу ссылка на сборку.

Собственно создание сборки

Начнём собирать нашу сборку (простите за тавтологию). Предварительно нам потребуется уже установленная на компьютере LTS-версия Node.js и NPM (входит в пакет Node.js) либо Yarn. Для нашей задачи не имеет значения, какой из этих пакетных менеджеров использовать, однако я буду объяснять на примере NPM, соответственно, для Yarn вам потребуется нагуглить аналоги NPM-команд.

Первое, что нам нужно сделать - это инициализировать проект. Открываем директорию проекта в командной строке (очень надеюсь, вы знаете, как это делается) и вводим команду npm init.

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

Далее будет намного удобнее работать через Visual Studio Code (поскольку у него есть встроенный терминал) или любой другой удобный вам редактор + терминал.

Прежде всего, нам нужно установить сам Gulp. Делается это двумя командами npm i gulp -global - устанавливаем Gulp глобально на систему и npm i gulp --save-dev - устанавливаем Gulp локально в проект. Ключ --save здесь отвечает за сохранение версии плагина при дальнейшей установке (без него вам может установить более новую, несовместимую с другими плагинами версию), а ключ -dev указывает на то, что этот пакет необходим только во время разработки проекта, а не во время его выполнения. Например, если мы устанавливаем в проект пакет Swiper, который содержит скрипты слайдера и будет отображаться на странице, мы будем устанавливать его без ключа -dev, поскольку он нужен для выполнения, а не для разработки.

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

После этого нам нужно подключить Gulp в нашем файле, для того чтобы он исполнялся. Это делается с помощью require:

const gulp = require('gulp');

Далее, для каждой задачи будем использовать модули в отдельных файлах. Для того, чтобы не подключать каждый модуль отдельно, нужно установить и подключить плагин require-dir. Устанавливается он всё той же командой (как и все последующие плагины, поэтому далее повторяться не буду, просто знайте, что установить - это npm i $PLUGIN-NAME$ --save-dev). После установки подключаем его и прописываем путь к директории, в которую будем складывать модули (у меня это директория tasks):

const gulp = require('gulp');const requireDir = require('require-dir');const tasks = requireDir('./tasks');

Первая задача

Давайте проверим, всё ли мы правильно сделали. Создадим в директории tasks файл модуля с именем hello.js. В созданном файле напишем простейшую функцию, которая будет выводить в консоль строку "Hello Gulp!" (можете придумать что-то менее банальное, если хотите).

module.exports = function hello () {console.log("Hello Gulp!");}

Теперь вернёмся в gulpfile.js и зададим там задачу hello:

const gulp = require('gulp');const requireDir = require('require-dir');const tasks = requireDir('./tasks');exports.hello = tasks.hello;

Теперь командой gulp hello в терминале запустим нашу задачу. Если всё сделано правильно - в терминал должно вывестись приблизительно такое сообщение:

[13:17:15] Using gulpfile D:\Web projects\Easy-webdev-startpack-new\gulpfile.js[13:17:15] Starting 'hello'...Hello Gulp![13:17:15] The following tasks did not complete: hello[13:17:15] Did you forget to signal async completion?

Так же, можно получить список всех заданных задач командой gulp --tasks.

Файловая структура

Теперь, когда мы создали первую функцию, можно подумать о том, какая структура будет у наших проектов. Я предпочитаю использовать директорию (папку) /src для хранения исходных файлов и директорию /build для готовых файлов проекта.

В директории src/ нам понадобятся следующие поддиректории:
  • components/ - директория для компонентов

  • components/bem-blocks/ - директория для БЭМ-блоков

  • components/page-blocks/ - директория для типовых блоков страницы, таких как хедер, футер и т.п.

  • fonts/ - директория для шрифтов

  • img/ - директория для изображений

  • js/ - директория для файлов JavaScript

  • scss/ - директория для файлов стилей

  • scss/base/ - директория для базовых стилей, которые мы изменять не будем

  • svg/ - директория для файлов SVG

  • svg/css/ - директория для SVG-файлов, которые будут интегрироваться в CSS

Получиться в итоге должно приблизительно следующее:

 project/  build/ 
Подробнее..

Используйте ссылки и кнопки правильно. Пожалуйста

09.06.2021 14:20:05 | Автор: admin

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

Почему возникает проблема

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

Ссылки создаются с помощью тега <a>.

<a href="http://personeltest.ru/aways/htmlacademy.ru">HTML Academy</a>

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

Для кнопок используют тег <button>.

<button class="button">9 900 руб.</button>

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

Пример двух кнопок, где нижняя похожа на ссылкуПример двух кнопок, где нижняя похожа на ссылкуПример ссылки, похожей на кнопкуПример ссылки, похожей на кнопку

Что случится, если вместо ссылки сделать кнопку

Если URL-адрес обернуть не <а>, а тегом <button>, то при нажатии пользователя на правую кнопку мыши браузер предложит выполнить действия, которые положены при клике на кнопку. Адрес нельзя будет открыть в новой вкладке или отправить через контекстное меню.

Контекстное меню при клике правой кнопкой мыши на кнопкуКонтекстное меню при клике правой кнопкой мыши на кнопку

Такая кнопка не позволит открыть страницу в новой вкладке и через комбинацию клавиш Ctrl и левая кнопка мыши.

При наведении курсора на правильную ссылку её адрес появляется внизу окна браузера. URL-адрес, обёрнутый в <button>, не отобразится.

Адрес правильной ссылки в окне браузера при наведении на неё курсораАдрес правильной ссылки в окне браузера при наведении на неё курсора

Что произойдёт, если вместо кнопки сделать ссылку

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

Контекстное меню при клике правой кнопкой мыши на ссылкуКонтекстное меню при клике правой кнопкой мыши на ссылку

Если функциональный элемент обернуть тегом <a>, то при клике правой кнопкой мыши всплывающее окно будет как у ссылки, но оно не будет иметь смысла. Такая ссылка не имеет корректного адреса, а значит открыть, сохранить, копировать её или поделиться ею невозможно.

<a href="javascript:;">На самом деле это кнопка</a>

При наведении курсора на псевдоссылку внизу окна браузера появится не адрес, а javascript:; или АдресТекущейСтраницы/#.

Как определить элемент по макету

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

У ссылки должны быть стили для состояния покоя, при наведения курсора :hover, в момент нажатия :focus, активного :active и иногда состояния, когда пользователь уже посещал эту страницу :visited.

У кнопки нет состояния :visited, зато есть состояние блока :disabled.

Состояния ссылок в стайлгайде макетаСостояния ссылок в стайлгайде макета

Однако рассчитывать только на макет не нужно. У ссылки может не быть :visited, а у блока :disabled это может запутать.

Забудьте про div семантика спасёт интернет

Всё-таки кнопка или ссылка?

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

Ссылка

Кнопка

За что отвечает

Навигация, т. е. пользователь перемещается на другую часть страницы или на новую страницу.

Выполнение какой-либо функции без перехода на другую страницу добавить в корзину, купить, отправить, проголосовать, войти и т. д.

Что видит пользователь

При наведении курсора на ссылку внизу окна браузера возникает её адрес.

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

При наведении курсора на ссылку внизу окна браузера не отображается адрес.

Через меню по клику правой кнопкой мыши нельзя скопировать адрес или поделиться им.

Пример, чтобы расставить всё по своим местам

На макете отрисована фраза Войти. Если клик по ней должен открывать окно для ввода регистрационных данных на этой же странице, это кнопка. Если при нажатии должна открываться отдельная страница для входа, это ссылка.

Другие великие противостояния


Ссылки ссылками, а промокод VESELO даст приятную скидку на любой профессиональный курс в HTML Academy. Например, на курс Анимации для фронтендеров можно записаться в любой момент, а пользы для карьеры будет целый вагон.

Подробнее..

Как быстро создать Bootstrap-сайт для бизнеса 6 полезных инструментов

26.09.2020 22:13:23 | Автор: admin


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

Что такое Bootstrap


Bootstrap это открытый и бесплатный фреймворк HTML, CSS и JS. Веб-разработчики по всему миру используют его для быстрого создания адаптивных сайтов и веб-приложений. Существуют и альтернативы, среди которых, например, фреймворки Foundation и UIkit, но Bootstrap считается самым популярным.

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

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

Startup


Startup это drag-n-drop конструктор Bootstrap-тем, который позволяет быстро создавать лендинги для бизнеса. Инструмент предлагает более 300 готовых блоков, которые можно использовать в интерфейсе. В несколько кликов собранный дизайн можно экспортировать в чистый HTMl, CSS, JavaScript.



При этом, итоговый результат будет оптимизирован под отображение на мобильных устройствах.

Pinegrow


Это десктоп-редактор для macOS, Windows и даже Linux, который позволяет создавать Bootstrap-сайты. Это инструмент уже скорее для разработчиков и верстальщиков, ведь он позволяет углубляться в такие моменты, как верстка CSS-сеток и правил, rich visual controls, SASS и LESS и т.п.



Помимо прочего, с помощью Pinegrow можно создавать интерфейсы под фреймворк Foundation и WordPress.

Bootstrap Magic


Еще один инструмент создания тем для Bootstrap 4.0, который подойдет более опытным разработчикам. Это продукт с открытым кодом, который позволяет писать HTML-код прямо в специальном редакторе и тут же генерировать его превью.



Bootstrap Build


Это бесплатный билдер тем на Bootstrap 4 (и как уточняется, скоро появится поддержка пятой версии). Пользователи могут использовать до 500 элементов UI, а также создавать собственные темы на основе готовых шаблонов в специальном редакторе, а затем экспортировать результат работы в SASS-файлы.



Bootstrap Studio


Как и Pinegrow, это десктоп-приложение, но которое работает в формате drag-n-drop. Здесь есть большая библиотека встроенных компонентов, включая хедеры, футеры, галереи и слайдшоу.



Все это позволяет его использование для людей с небольшим опытом веб-разработки.

Codeply


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



Заключение


Это лишь некоторые интересные инструменты, которые позволят создавать красивые Bootstrap-сайты быстрее и делать их функциональными. Делитесь в комментариях ссылками на другие полезные продукты так наш список будет еще более полным.
Подробнее..

Как я написал диплом по химии с (Xe)LaTeX

22.10.2020 12:07:47 | Автор: admin
Эту статью я задумал еще на втором курсе, когда впервые решил перейти с Word'а на LaTeX. В конце третьего курса я ее начал, и, наконец, после защиты диплома я нашел в себе силы ее дописать. Здесь я постарался собрать свой опыт (и созданные костыли, куда же без них) в использовании LaTeX при подготовке текста, связанного с химией и в решении тех проблем, с которыми столкнулся я.

Введение


К использованию LaTeX меня подтолкнул тот факт, что однажды при попытке добавить подписи к картинкам Word просто испортил файл: файл открывался, текст отображался, однако отредактировать что-то было невозможно. Файл был успешно восстановлен из резервной копии, но осадочек, как говорится, остался. После этого момента я и вспомнил о LaTeX, о котором когда-то слышал. Далее последовалстандартный путь изучения: гугл, книги, stackexchange, метод проб и ошибок, etc.

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

Статья подразумевает некоторые знания в LaTeX, примерно на уровне написать простую преамбулу, вставить картинку и сверстать таблицу.

Общие настройки


Я использую движок XeLaTeX и biber для обработки библиографической информации.
Общие идеи преамбулы я взял у Amet13 и дополнил необходимыми мне пакетами.

Из непосредственно химических пакетов:
  • chemmacros дает возможность выводить длинные названия веществ с адекватными переносами, и форматировать всяческие экспериментальные данные (спектры, температуры плавления)
  • mhchem форматирует простые (строчные) формулы и реакции
  • chemscheme добавляет плавающее окружение для схем реакций со своим названием и нумерацией
  • chemnum нумерация соединений


Настраивается это всё так
\usepackage{chemmacros}\usepackage[version=4]{mhchem}\mhchemoptions{layout=stacked}\chemsetup{formula = mhchem}\chemsetup{modules=all}\usepackage{chemscheme}\renewcommand{\schemename}{Схема}\usepackage{chemnum}\setchemnum{format=\bfseries}



Дополнительные пакеты:
  • placeins вместе с модификатором h! из пакета float не позволяет плавающим рисункам уплывать куда-нибудь не туда
  • todonotes позволяет оставлять заметки на полях и в тексте
  • threeparttable добавляет возможность делать сноски к таблицам
  • makecell переносы в таблицах (очень удивился, когда узнал, что для этого требуется отдельный пакет)


Организация файлов


Мне показалось логичным создать корневой файл, в котором подключается все необходимое преамбула, разделы, приложения. Для всего, что подключается один раз и навсегда папка include, для разделов папка sections, для приложений appendix.
У каждого раздела в папке sections своя папка, где хранятся изображения в папке img и исходные файлы схем в папке ChemDraw.

Дерево папок и корневой файл
. appendix  img include sections     conclusion      img     experimental      img     introduction      img     literature      ChemDraw      img     results         ChemDraw         img

main.tex:
\documentclass[12pt, a4paper, final]{extarticle}\input{include/preamble.tex}\input{include/siunitx.tex}\input{include/acronyms.tex}\begin{document}\includepdf{include/titul_bac.pdf}\include{include/toc}\include{include/loa}\include{sections/introduction/introduction}\include{sections/literature/literature}\include{sections/results/results}\include{sections/experimental/experimental}\include{sections/conclusion/conclusion}\include{include/bibliography}\include{appendix/appendix}\end{document}



Для файлов был создан git-репозиторий в основном для бэкапа и возможности фиксировать добавление тех или иных фрагментов диплома или правок.

Картинки


Мне было удобнее использовать EPS или векторный PDF, который умеет выводить любой химический редактор.

Для создания изображения из нескольких частей, подписанных буквами, служит пакет subfigure с настройкой:
\renewcommand{\thesubfigure}{\asbuk{subfigure})}

В коде это выглядит так
\begin{figure}    \centering    \subfigure[Подпись к рисунку 1]    {    \includegraphics[width = 0.45\textwidth]{рисунок1}    }    \subfigure[Подпись к рисунку 2]    {    \includegraphics[width = 0.45\textwidth]{рисунок2}    }    \caption{Подпись ко всему рисунку}\end{figure}



Таблицы


Таблицы в целом стандартные, созданы в основном с помощью Excel и сайта Tables Generator. Для того, чтобы входило больше текста все таблицы обернуты в окружение small, для переносов в ячейках строк используется пакет makecell. Для более книжного вида используются линейки различной толщины из пакета booktabs, сноски к таблицам делаются пакетом threeparttable.

Цитаты


Для LaTeX существует несколько библиографических движков: biblatex, biber. Эти программы требуют наличие bib-файла. Для его подготовки существуют несколько подходов от ручного редактирования до специальных программ типа Mendeley и Zotero.

Я пользуюсь Mendeley, потому что там у меня есть коллекция отсортированных статей.

Единственная проблема при поиске библиографической информации по doi Mendeley загружает также дату выхода статьи, а biblatex ее вставляет в документ, давая что-то типа:
Jakob F., Herdtweck E., Bach T. Synthesis and Properties of Chiral Pyrazolidines Derived from (+)Pulegone // Chemistry A European Journal. 2010. Июль. Т. 16, No 25. С. 75377546.

вместо
Jakob F., Herdtweck E., Bach T. Synthesis and Properties of Chiral Pyrazolidines Derived from (+)Pulegone // Chemistry A European Journal. 2010. Т. 16, No 25. С. 7537 7546.

Проблема решается двумя командами в преамбуле:
\AtEveryBibitem{\clearfield{month}}\AtEveryCitekey{\clearfield{month}}


Также в процессе общения с рецензентом выявились следующие недостатки списка литературы: для русскоязычных статей слова Том, Номер и Страницы следует сокращать как Т., "" и С. соответственно, а для англоязычных как V., "" и P.; в случае, если авторов больше трех, то следует выводить первых трех (а не одного, как сделано по умолчанию) и далее [и др.] или [et al.] с учетом языка источника.

К моему счастью, biblatex позволяет настраивать вывод библиографических записей непосредственно в преамбуле. Проблема крылась в том, что Mendeley не умеет работать с полем langid в bib-файле, которое требуется для biblatex. В итоге я решил прописать каждой статье поле language через Mendeley и заменить в bib-файле language на langid. Далее через интерфейс biblatex для разных языков были заданы разные настройки:

\DefineBibliographyExtras{russian}{\renewcommand{\bibrangedash}{\,--\,}}\DefineBibliographyExtras{english}{\renewcommand{\bibrangedash}{\,--\,}}\DefineBibliographyStrings{english}{number = {}, jourvol = {V. }}


Также по-умолчанию несколько ссылок подряд разделяются не запятой, как это требуется по ГОСТу, а точкой с запятой. Это легко решается одной командой:
\renewcommand{\multicitedelim}{, }


Непосредственно химия


Формулы


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

Простые формулы
(\ce{Mg(ClO4)2}, \ce{Mg(NTf2)2}, \ce{TiCl4}, \ce{SnCl4}, \ce{Yb(OTf)3})

превращется в


Нумерация соединений


В органической химии принято присваивать соединениям номера, ибо иногда название вещества по системе ИЮПАК, призванной (по идее) обеспечивать однозначное соответствие между структурной формулой и названием, может растянуться строчки на две-три:

Например (doi:10.1021/cm052861i)

2-(1-(3,5-bis((perfluorophenyl)methoxy)benzoyl)-3-cyano-4-((E)-2-(5-((E)-4-(dibutylamino)styryl)thiophen-2-yl)vinyl)-5-oxo-1,5-dihydro-2H-pyrrol-2-ylidene)malononitrile


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

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

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

Вторая же проблема имеет несколько вариантов решения. Во-первых существует изрядно устаревший подход с заменой строки текста в eps-файле с помощью специального пакета в момент компиляции документа. Способ малоприменимый на практике в моем случае: эти пакеты совместимы только с оригинальным LaTeX (а с некоторыми костылями и с pdfTeX), а новые версии ChemDraw хранят текст в eps-файле побуквенно.

Вариант номер два отрисовывать структурные формулы средствами LaTeX, для чего служат такие пакеты как XyMTeX и chemfig. Вариант не лишенный достоинств, но требующий перевода структур в формат пакета вручную или почти вручную. В случае chemfig, существует скрипт на Python под названием mol2chemfig (который я так и не смог у себя запустить), который позволяет из стандартного формата mol получать код для отрисовки структурной формулы в LaTeX. Однако этот подход требует ручного создания схем в документе, что мне не понравилось.

В итоге я остановился на пакете overpic, который позволяет вывести любой текст поверх любого изображения в любом месте. Из недостатков необходимость этот текст вручную выставлять, пересобирая в процессе документ несколько раз. Зато это позволяет рисовать схемы в WYSIWYG редакторе по типу ChemDraw, пользуясь всеми его графическими возможностями.

Как это выглядит
В документе:

И в коде:
\begin{overpic}{sections/literature/img/azomethine_generation.eps}        \put(6, 44){\textbf{\cmpd{hydrazone}}}        \put(56, 44){\textbf{\cmpd{enhydrazine}}}        \put(6, 29){\textbf{\cmpd{carbene}}}        \put(62, 29){\textbf{\cmpd{silyl}}}        \put(6, 15){\textbf{\cmpd{oxidation}}}        \put(49, 16){\textbf{\cmpd{diazo}}}        \put(65, 16){\textbf{\cmpd{azo}}}        \put(22, 0){\textbf{\cmpd{metathezis}}}    \end{overpic}



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


В отличие от основной части работы, в экспериментальной части принято приводить полные названия соединений по ИЮПАК, а не номера. Проблема заключается в том, что LaTeX в каждом слове допускает только один перенос, а команда \iupac{} из пакета chemmacros позволяет своему аргументу переноситься несколько раз и добавляет макросы \E, \Z и подобные для использования в названиях соединений.
Также принято приводить экспериментальные характеристики полученных соединений температуру плавления, спектры и прочие подобные вещи.

Например
\data*{Т\textsubscript*{пл.}} 147--\SI{150}{\celsius}.

будет выведено как:



Приложения


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

Стандарты оформления моего ВУЗа требуют не нумеровать страницы в приложениях и давать их заголовки с выравниванием вправо.

    \pagenumbering{gobble}    \titleformat*{\section}{\raggedleft\large\bfseries}


Из оглавления я также решил их убрать.

    \addtocontents{toc}{\protect\setcounter{tocdepth}{0}}


По-умолчанию пакет appendix нумерует приложения латинским буквами, я изменил нумерацию на арабскую в соответствии со стандартами оформления (опять с помощью костыля)

    \makeatletter    \renewcommand{\thesection}{\@arabic\c@section}    \makeatother


В приложениях у меня живут в основном ЯМР-спектры в виде картинок, которые из программы для их обработки выходят в виде PDF формата A4 альбомной ориентации. К сожалению, у меня так и не получилось в одном документе совместить книжную и альбомную ориентацию (я подозреваю, что это вообще невозможно), поэтому пришлось изобретать свой велосипед с использованием пакета rotating.

Велосипед
    \begin{figure}[h!]        \rotatebox{90}{            \begin{minipage}{0.82\textheight}                \includegraphics[width=\linewidth]{appendix/img/1.pdf}                \caption{Спектр 1}            \end{minipage}        }    \end{figure}



Список сокращений


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

Пример
\DeclareAcronym{bz}{    short={Bz},    long={Бензоил},    first-style=short}


при упоминании в тексте как
\ac{bz}
будет выведено в виде Bz а в списке сокращений будет приведено с расшифровкой.

Часть списка сокращений выглядит так:




Презентация


На презентации к защите останавливаться не буду, поскольку решил ее делать по-старинке в PowerPoint. На мой взгляд, смотрибельность для презентации важнее, а WYSIWYG-подход этому более способствует.

Вместо заключения


Главный вопрос: стоило ли оно того? К окончательному выводу я так и не пришел, поскольку при всех его достоинствах LaTeX выдает PDF-файл, в который невозможно вносить исправления. Из-за этого моему руководителю приходилось каждый раз присылать список правок в виде файла в Word'e. Также мне сильно повезло с тем, что в моем ВУЗе отстутствует такое мероприятие как нормоконтроль, и в большинстве вопросов оформления я был ограничен только своим чувством прекрасного и здравым смыслом.

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

Основными источниками информации для статьи послужили:
  1. Серия статей Каталог классов и стилей LaTeX за авторством Евгения Балдина, в особенности, пятая часть
  2. Раздел chemistry на CTAN
  3. Документация упомянутых в статье пакетов
Подробнее..

Перевод Создание совершенной печатной машины из Sublime Text

19.04.2021 10:09:21 | Автор: admin
UPD: Прошло больше месяца с тех пор, как я написал первоначальный черновик этой статьи. С тех пор я опубликовал еще три записи в блоге и более двадцати на моем канале в Телеграм. Настройки зарекомендовали себя фантастически, мне он очень нравится, и у меня нет желания искать где-либо еще.

Я был давним поклонником iA Writer из-за того, что писал. Я купил оригинальную версию для iPad, оригинальную версию macOS (когда она еще называлась MacOS X), версию для Android и даже ту, которую они переиздали как платное обновление по полной цене. На мой взгляд, в нем есть идеальный баланс между функциями и простотой, дизайном и направленностью.

Вот скриншот первоначальной версии iA Writer от 2011 года:

image

А вот как это выглядит сейчас, в 2021 году:

image

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

Ограничения iA Writer


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

  • iA Writer предназначен для работы с одним документом за раз. Я предпочитаю работать с проектами и папками, переключаясь между файлами.
  • Библиотека iA Writer привязана к iCloud, и вы должны хранить там все свои файлы. Недавно я отказался от iCloud и вообще предпочитаю, когда инструменты не определяют, где мне хранить файлы.
  • При наличии собственного блога публикация состоит из периодического редактирования CSS/JS/шаблонов, для чего iA Writer, опять же, не оптимизирован.
  • Я привык к таким удобствам Sublime, как несколько курсоров, поиск в файлах, Go Anywhere и интеграция с Git. Чувствуешь себя скованно, не имея этого всего под рукой.


Оптимизация Sublime Text для письменной работы


Я решил попробовать повторить то, что делает iA Writer, но внутри Sublime Text. Это мои настройки.

Цветовая схема


К счастью, iA Writer использует абсолютный минимум цветов, поэтому повторить эту часть было проще всего.

image

Исходный код: github.com/tonsky/sublime-scheme-writer.

В Package Control: Цветовая схема Writer.

P.S. Да, есть и темная версия.

Шрифт


iA Writer дебютировал с проприетарным шрифтом Nitti, но позже переключился на IBM Plex Mono, который выпускается под лицензией Open Font License.

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

image

Параметры следующие:

font_face: IBM Plex Mono,
font_size: 16,
line_padding_bottom: 3,
line_padding_top: 3,
wrap_width: 72

Это уже очень хорошее соответствие, но перфекционист во мне хотел получить точное соответствие. Две вещи требовали корректировки: немного увеличенный вес шрифта (текст вместо обычного) и дополнительные 3,5% ширины символа. Поэтому я взял на себя смелость и модифицировал оригинальный IBM Plex Mono, чтобы он соответствовал этим характеристикам.

Сморите:

image

Совпадает почти идеально! Вы можете получить мою версию IBM Plex Mono на github.com/tonsky/font-writer.

Смена профиля


Мы настроены на то, чтобы писать, но как нам вернуться к кодированию?

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

Встречайте Profile Switcher! Он хранит несколько отдельных файлов Preferences.sublime-settings и мгновенно переключается между ними.

image

image

Источники: github.com/tonsky/sublime-profiles

В управлении пакетами: Profile Switcher.

P.S. Альтернативный способ поместить настройки для записи в файл настроек для синтаксиса Markdown. Мне этот подход нравится меньше, потому что он влияет, например, на Sublime Merge diff view и все файлы разметки, некоторые из которых я не хочу видеть в режиме записи.

Кроме того, Profile Switcher кажется чем-то, что может быть полезно не только для написания/кодирования duo.

Все вместе (TL;DR)


  1. Скачайте и установите шрифт Writer.
  2. Через Package Control установите цветовую схему Writer
  3. Через Package Control установите Profile Switcher.
  4. Создайте профиль Writing с помощью команды Profiles: Create profile.
  5. Поместите эти настройки сюда (просто замените все, что у вас есть):


{
caret_extra_width: 2,
draw_centered: правда,
draw_indent_guides: ложь,
draw_white_space: [нет],
font_face: Writer,
font_size: 16,
желоб: ложь,
highlight_line: ложь,
line_padding_bottom: 3,
line_padding_top: 3,
маржа: 10,
scroll_context_lines: 2,
scroll_past_end: 0,5,
word_wrap: правда,
wrap_width: 72,
color_scheme: Пакеты / sublime-scheme-writer / Writer.sublime-color-scheme,
theme: Adaptive.sublime-theme,
}

Вы должны увидеть что-то вроде этого:

image

Сравните с тем, с чего мы начали:

image

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

Отсутствующие функции


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

Дуоширинный шрифт


Чего ждать? Дуоширинный? Это что?

Что ж, это еще одна гениальная идея от iA: сделать W и M 1,5 ширину, оставив остальную часть шрифта моноширинной. Он по-прежнему выглядит и ощущается моноширинным, но Ms и W больше не уродливы без причины. Хотелось бы, чтобы таких шрифтов было больше.

image

Можем ли мы воспроизвести это в Sublime Text? И да и нет. ST может отображать не моноширинные шрифты, но отключает полужирный/курсивный шрифт, если шрифт не моноширинный.

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

Если вы хотите попробовать дуоширинный шрифт, его можно бесплатно загрузить по ссылке github.com/iaolo/iA-Fonts.

Висячая пунктуация


Функция, которую я люблю с самой первой версии, единственный способ форматировать заголовки Markdown.

image

Почему это так круто? Если ### выровнено по основному тексту, вам нужно пропустить ### и найти первую значимую букву.

Если он висит снаружи, ничто не сможет помешать вам.

Динамическая типографика


Еще одна вещь, которую сложно воспроизвести в Sublime Text, это динамическая типографика. Насколько я понимаю, iA Writer динамически переключается между несколькими версиями с разным интервалом и весом в зависимости от текущего размера шрифта и разрешения экрана. Это сложно реконструировать и еще сложнее повторить в Sublime Text.

Хотя, с профилями

Подсветка синтаксиса


Во-первых, да, в iA Writer есть подсветка синтаксиса для простого английского. Выглядит это так:

image

Предположительно, это помогает писать более сбалансированные предложения. Как вы могли заметить, я этим никогда не пользовался :)

Режим фокусировки


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

image

Заключение


Sublime Text можно довольно хорошо настроить и превратить в фантастический инструмент для письменной работы.

Однако специализированное программное обеспечение, такое как iA Writer, может делать больше.

Надеюсь, вы найдете эту информацию полезной или (что еще лучше!) вдохновитесь написать что-нибудь.

6 апреля 2021 г.



Наши серверы можно использовать для разработки и продакшена на любом языке.

Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!

Подробнее..

Mathcha внебрачный сын Word и Latex

02.06.2021 16:12:10 | Автор: admin


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


Дисклеймер: данный обзор основан на опыте работы автора с инструментом и не является рекламой сервиса Mathcha.io


С чем же мы имеем дело


Mathcha.io онлайн WYSIWYG (What You See Is What You Get) редактор текста, который имеет поддержку встроенных в текст формул, блоков формул, картинок, кода с подсветкой, а также некоторых других фич, про которые речь в этой статье не пойдёт (checkbox, вставка видео с Youtube, создание диаграмм и рисунков).



Работа с программой


Текст


Интерфейс программы напоминает Word, что помогает быстро сориентироваться. Сверху есть разные инструменты форматирования: центровка текста, жирный/подчёркнутый/курсив, ссылки, копирование стиля, списки, шрифт (всего 5 штук), размер и цвет текста. Всё это помогает работать с обычным текстом в один клик (в том числе благодаря общепринятым ctrl+b и подобным).



Математика


Вот ради чего это всё затевалось. Есть 2 способа подключения формул: inline-math и math-container (первый можно встраивать в строки текста, а второй только как отдельный блок, что является логичным для математических выкладок).


Лайфхак: можно создать inline-math на текущей позиции курсора, напечатав $. Я не нашёл в настройках способа отключить это (возможно он есть). Но по умолчанию вместо обычного значка доллара приходится писать \$ + Enter, что очень неудобно в финансовых документах. В обычном TeX такая проблема тоже есть, так как $ обозначает начало формулы.



Синтаксис из TeX символы


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


Большинство символов можно найти в выпадающем списке по названию:



Также очень удобная фича, когда не можешь описать символ словами поиск по рисунку:



А также есть автозамена "программистских" значков на математические, например, <= (меньше или равно) заменяется на цельный символ.


Математические конструкции


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



Поиск по рисунку также работает



Так ли это удобно?


Но именно тут возникает главное упущение разработчиков mathcha, которое сильно затрудняет работу: после каждого специального символа необходимо нажимать Enter. Даже если вы полностью напечатали название. Да, предпросмотр дроби хорошо выглядит, а также он очень полезен, когда числитель и знаменатель сложные, но, например, напечатать \frac{3}{5} часто быстрее, чем \frac <Enter> 3 <стрелочка вниз> 5 <стрелочка вправо>.


В любом месте документа (в том числе в математических блоках) можно сделать импорт из TeX, но для этого необходимо напечатать \from-latex <Enter>, потом написать формулу как в TeX (в этом окне также есть предпросмотр), а потом мышкой нажать на OK. Это может занять ещё больше времени, чем первый вариант.



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



Вставка картинок


Вставить картинку в документ можно из буфера обмена, с устройства или по url. Также 50 мегабайт ваших картинок хранятся в привязке к аккаунту. Можно делать подпись к картинкам или открывать их на полный экран.



Код


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



Связь с внешним миром


Экспорт в PDF


Единственный способ экспортировать документ в PDF нажать кнопку "Печать" (ctrl+P) и далее выбрать "Печать в PDF" (в зависимости от ОС). Можно выбрать поля и формат страницы, а также колонтитулы.



Экспорт в TeX


Есть возможность экспорта выделенной области как тело документа TeX, но полная совместимость не гарантируется.


Поделиться документом


Можно поделиться документом по прямой ссылке на сайт mathcha.io в формате read-only. Также недавно появилась возможность добавить коллабораторов в документ, но я не пробовал, насколько хорошо работает синхронизация при такой совместной работе.


Десктопная версия


Существует платная (3$ в месяц) офлайн версия, которая имеет некоторые преимущества по сравнению с онлайн версией. Она имеет поддержку экспорта в формат .mathcha, а также снимаются некоторые лимиты. Без лицензии программа находится в режиме read-only, то есть вы всё ещё можете экспортировать файл из онлайн редактора в .mathcha, а после открыть его на чтение в десктопной версии (онлайн версия открывать .mathcha файлы не умеет). Также плюсом офлайн формата является приватность, то есть ваши документы не хранятся где-то в интернете


Выводы


Mathcha самостоятельный инструмент, который использует TeX, а также другие виды контента. Я бы не рекомендовал использовать её людям, которые имеют обширный опыт при работе с обычными TeX документами (так как при большой скорости печати подсказки начинают мешать). Также не стоит рассматривать Mathcha как полную замену TeX-у, так как её возможности сильно ограничены (например, отсутствием внешних пакетов). При работе в ней вы будете "заперты", то есть вынести текущие наработки за пределы редактора не всегда просто. У меня никогда не пропадали документы из хранилища mathcha, но я не могу быть полностью уверен в его надёжности.


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




Облачные серверы от Маклауд быстрые и безопасные.


Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!


Подробнее..

Перевод - recovery mode 41 термин в дизайне, полезный для UX-исследователя

05.09.2020 12:21:57 | Автор: admin


Работа с UX-дизайнерами и знакомство с их словарным запасом это почти изучение нового языка. Давайте посмотрим на 41 часто используемый дизайнерский термин. Для лучшего взаимопонимания в команде.



Flat Design (Плоский дизайн)


Flat Design это минималистский стиль дизайна пользовательского интерфейса. Он характеризуется фокусированием на использовании простых двухмерных элементов с яркими цветами.


Ник Бабич (Nick Babich) из UX Planet называет flat design более сложным кузеном минимализма, поскольку все элементы пользовательского интерфейса основаны на простоте.

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




Interaction Design (Интерактивный дизайн)


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




Material Design (Материальный дизайн)


Material Design, часто называемый просто материалом, это язык дизайна, разработанный Google и используемый на устройствах Android.


Вот краткое вводное видео об этом от Google:



Iterative Design (Итеративный дизайн)


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



Design sprints (Дизайн-спринты)


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



Brand Identity (Фирменный стиль)


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




Mood board (Доска настроения)


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


Доска настроения используется всеми дизайнерами, в том числе теми, кто занимается дизайном UX, графики, моды и т.д.



Storyboard (Раскадровка)


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



User Journey Maps / UX Flow / Flowchart


Карты пути пользователя (также иногда называемые UX-потоком или блок-схемой) представляют собой описательные документы, которые иллюстрируют шаги, которые пользователь может предпринять для выполнения задачи над продуктом. Они часто включают имя, шаги и описание того, что происходит на каждом шаге.



Есть ли различия между картами пути пользователя и потоками UX? Да.

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


В то время как UX-потоки имеют более формальные правила (вероятно, из-за их происхождения в виде блок-схем).



Wireframe (Каркас)


Думайте о каркасах как о проекте экрана. Они представляют собой низкокачественное представление макета и содержания веб-сайта.




Wireflow


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


Чуть больше про Wireflow
Wireflow это не скетч. Wireframe-ы специально никак не связаны с дизайном, чтобы демонстрировать как сайт/приложение будет работать, а не выглядеть. В wireframe все выглядит схематично, но за этими чертежами стоят многие часы раздумий. Каждый небольшой блок должен быть спланирован и расположен в нужном месте. Каждая ссылка должна куда-то вести. Каждая страница должна быть доступна по ссылке с другой страницы. Каждая кнопка должна быть там, где она нужна пользователю, и не быть там, где от нее нет толку. Лишь 10% создания wireframe-ов приходится на рисование; 90% занимает процесс продумывания.



Mockup (Макет)


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




MVP


MVP или минимально жизнеспособный продукт(minimum viable product) относится к основному набору функций, с которыми мы можем запустить продукт, чтобы начать работу. Это не означает, что мы не будем развивать дальнейшие элементы или части. Продукты часто запускаются как MVP для быстрого выпуска и сбора ценных отзывов пользователей.


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




Low and High-fidelity protos


Прототипы с низкой и высокой точностью


На ранних этапах вы можете создавать бумажные прототипы (с низкой точностью Low protos) карандашом и бумагой для проверки концепций или течений. Позже, после проверки алгоритмов и концепций, вы можете перейти на программное обеспечение для проектирования, такое как Sketch, для создания прототипа с высокой точностью (High-fidelity protos). Прототипы будут выглядеть не как каракули, а как приложения на вашем мобильном устройстве, и их можно будет использовать для точной настройки деталей вашего пользовательского интерфейса.




Adaptive design (Адаптивный дизайн)


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




Responsive design (Отзывчивый веб-дизайн)


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



Про разницу Адаптивного и Отзывчивого


Affordance (Ухватистость или провоцировательность)


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



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



Picker (Сборщик)


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




Bar (Панель навигации)



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


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




UI Element


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



UI Pattern


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


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


Widget (Виджет)


Виджет это просто экранный элемент, с которым взаимодействуют пользователи. Примеры виджетов: ползунки, инструменты календаря, кнопки, контактные формы...



Pixel (Пиксель)


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



Hierarchy (Иерархия)


Иерархия это визуальное расположение элементов дизайна, подчеркивающее важность.




Breadcrumbs (Хлебные крошки)


Хлебные крошки это вспомогательные средства навигации, которые сообщают пользователям, где они находятся на веб-сайте. Это позволяет пользователям повторять свои шаги на многоуровневых веб-сайтах. Несмотря на свой второстепенный статус, крошки используются с 1995 года, помогая сделать дизайн более удобным для пользователя.




API


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




Onboarding (Адаптация)


Создавайте благоприятные условия для новых пользователей, облегчая им это. Дизайн процесса адаптации для вашего сайта обычно ограничивается сценарием первого использования.



Lorem Ipsum (Текст рыба)


Также известное как фиктивная копия, lorem ipsum это общий текст-заполнитель, используемый, когда настоящий текст недоступен. Он используется в качестве текста-заполнителя, чтобы продемонстрировать, как будет выглядеть дизайн после того, как будет добавлен реальный основной текст.




Legibility (Разборчивость)


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




Microcopy (Микрофотокопия)


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



Grid System (Сетка)


Системы сеток это организационные инструменты, которые помогают дизайнерам (особенно графическим дизайнерам) размещать контент на экране. Они состоят из вертикальных и горизонтальных линий, образующих то, что мы называем столбцами и строками.




Scale (Масштаб)


Масштаб характеризует изменение размера объекта при сохранении его формы и пропорций. Большой масштаб может создать драму, а маленький может создать мелкие детали.



Color Theory (Теория цвета)



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



Cool Colors (Холодные цвета)




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



Warm Colors (Теплые цвета)




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



Gradient (Градиент)


Как видно на двух картинках выше, это постепенное изменение цвета от одного тона к другому.



Opacity (Прозрачность)


Степень прозрачности элемента. Чем ниже непрозрачность, тем прозрачнее элемент.



Resolution (Разрешение)


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




Contrast (Контраст)


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




Saturation (Насыщенность)


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




Ну вот и все. Это были одни из самых распространенных терминов, с которыми вы могли столкнуться при работе с UI, UX или графическими дизайнерами.

Подробнее..

Recovery mode Как мы автоматизировали тестирование верстки сайта с помощью скриншотов

08.02.2021 10:22:45 | Автор: admin

Привет, меня зовут Фахридин Джамолидинов, я специалист департамента тестирования в Ростелеком ИТ. Занимаюсь автоматизацией тестирования основного сайта компании rt.ru и сегодня я расскажу, как про мы внедрили тестирование скриншотами, или как помочь автотестам видеть ошибки.

Наш сайт это не только витрина для информирования клиентов и продаж услуг и товаров для сегментов B2C, B2B и B2O, он ещё предназначен для обслуживания текущих клиентов: FAQ, чат, формы обратной связи, платежные формы и т.п.Он постоянно обновляется, и каждый раз после выпуска новой версии нужно проверять сотни страниц с богатым, динамичным UI на работоспособность в браузерах и адаптивность вёрстки.

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

Как всё начиналось

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

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

Итого, что нам требовалось:

  • возможность сравнения всей страницы целиком, отдельных элементов, групп элементов;

  • проверка на адаптивность (десктоп 1920px, планшет 768px, мобила 360px);

  • поддержка минимум двух браузеров: Chrome и Firefox;

  • игнорирование и скрытие элементов (групп элементов) при сравнениях;

  • удобочитаемый отчет с подсветкой отличий.

В качестве стека технологий было решено использовать то, на чём ранее были реализованы функциональные тесты:

Java основной язык программирования;
TestNG фреймворк автоматизации тестирования;
Maven сборщик;
Selenide обертка над Selenium, которая упрощает написание веб автотестов;
Selenoid GGR сервер-балансировщик для запуска изолированных браузеров в Docker контейнерах;
Allure фреймворк для создания отчётов автотестов и плагин ScreenDiff;
aShot библиотека для попиксельного сравнения изображений.

Благодаря балансировщику Selenoid GGR (Go Grid Router), в котором настроено распределение на несколько машин, мы имеем возможность поддержки нескольких браузеров (при необходимости: нескольких версий), плюс запуск тестов (изолированных браузеров) в параллель (~40 потоков).

В этой статье мы покажем как работает автотестирование по скриншотам будем акцентировать внимание на функционал aShot (кстати, спасибо ребятам из Яндекса за такие полезные инструменты как aShot и Allure) и на самом процессе.

Как это работает

Тесты условно разбиты на две группы:

  • fullscreen страницы целиком (с прокручиванием);

  • element(s) отдельный элемент (группа элементов)

Каждая из групп представляет из себя data-driven тесты, т.е. каждая страница, элемент (группа элементов) это отдельный параметризованный тест на основе DataProvider, а вся задача сводится к сравнению двух скриншотов. Например, регресс верстки списка Landing Page, в виде схемы выглядит так:

Избавляемся от динамики

Динамика в основном проявляется в виде:

  • каретки в полях ввода, которая мигает (может пропасть или появиться);

  • CSS Transition и Animations;

  • видео с автопроигрыванием и ряд других моментов.

Там, где есть возможность отключаем (инъекцией CSS):

Каретку делаем прозрачной (задаем значениецвета = transparent). Таким образом она всегда будет невидимой и не будет влиять на результат. CSS Transition обнуляем transitions-delay и transition-duration. CSS Animation обнуляем animation-delay, animation-duration и ставим состояние анимации в паузу, устанавливаяanimation-play-stateвpaused.

*, *::after, *::before {    caret-color: transparent !important;    transition-delay: 0s !important;     transition-duration: 0s !important;    animation-delay: 0s !important;     animation-duration: 0s !important;    animation-play-state: paused !important;    overflow: hidden; // Опционально скрываем полосу прокрутки}

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

Проверяем на адаптивность

Если с десктоп браузером всё понятно, с планшетом и мобилой встал вопрос, как проще эмулировать браузер. Было решено, что пока достаточно использовать фичу вебдрайвера mobileEmulation. Пример скрипта поднятия вебдрайвера Chrome с включением этой опции, в режиме планшета и выбором девайса = iPad:

@Override    public WebDriver createDriver(DesiredCapabilities capabilities) {WebDriverManager.chromedriver().setup();Map<String, String> mobileEmulation = new HashMap<>();mobileEmulation.put("deviceName", "iPad");ChromeOptions chromeOptions = new ChromeOptions();chromeOptions.setExperimentalOption("mobileEmulation", mobileEmulation);WebDriver driver = new ChromeDriver(chromeOptions);WebDriverRunner.setWebDriver(driver);return driver;    }

Снимаем скриншоты

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

screens / {browser} / {desktop | tablet | mobile} / {region} в зависимости от выбранного для запуска браузера, устройства (режима адаптивности) и регионов (некоторые компоненты могут быть регионозависимы, т.е. отображаться по-разному в зависимости от выбранного пользователем региона).

Название файла состоит обычно из:

  • для fullscreen (страницы целиком) = {URL path} + опционально {query}, {ref};

  • для отдельного элемента | групп элементов = {URL path} + {уникальный class | id | path} (тут на усмотрение кому как удобно, главное, чтобы можно было выделить уникальное значение)

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

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

Пример снятия скриншота всей страницы (fullscreen):

Создаем объект Screenshot AShot, перед вызовом метода takeScreenshot() вызываем метод shootingStrategy(), в параметрах которого задаем правило съемки viewportPasting(300), т.е. снимать скриншот с прокручиванием, с таймаутом 300 мс. AShot по умолчанию использует jQuery для поиска координат, при его отсутствии, необходимо включить поиск координат с помощью WebDriver API предварительно вызвав метод coordsProvider(new WebDriverCoordsProvider()).

Screenshot actualScreenshot = new AShot()   .shootingStrategy(ShootingStrategies.viewportPasting(200))   .coordsProvider(new WebDriverCoordsProvider())   .takeScreenshot(getWebDriver());

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

Черные области при прокруткеЧерные области при прокруткеНекорректный масштаб и склейка областей при прокруткеНекорректный масштаб и склейка областей при прокрутке

Погуглив и проанализировав DPR (Device Pixel Ratio) значения страниц в разных режимах, стало понятно, что дело скорее всего в соотношении пикселей устройств, которые мы эмулируем. Запустив window.devicePixelRatio;в консоли браузера, можно найти его. Задали другой shootingStrategy, указав подходящий устройству DPR scaling в параметрах, и таким образом избавились от вышеуказанных проблем.
Для режима планшет (iPad) указали ShootingStrategies.viewportRetina(600,0,0,2f).
Для мобилы (Pixel 2XL) указали ShootingStrategies.viewportRetina(600,0,0,3.5f)

Пример снятия скриншота конкретного элемента (группы элементов):

При вызове метода takeScreenshot(), в параметрах, помимо текущего WebDriver, передаем еще элемент WebElement либо коллекцию элементов Collection <WebElement>, по которым мы хотим получить скриншот:

Collection<WebElement> elements = new ArrayList<>();   elements.add($x("//div[contains(@class,'rtk-offer-list')]")); // допуслуги и оборудование   elements.add($x("//div[@class='rtk-offer__legend']")); // блок ценыScreenshot actualScreenshot = new AShot()   .shootingStrategy(ShootingStrategies.viewportPasting(200))   .coordsProvider(new WebDriverCoordsProvider())   .takeScreenshot(getWebDriver(),elements);

Снятие скриншота c установкой игнорирований элемента(-ов) при сравнении:

Создаем set из элементов, которые хотим игнорировать при сравнениях:

Set<By> ignoredElements = new HashSet();ignoredElements.add(By.xpath(xpath);

и передаем при снятии актуального скриншота этот набор вызовом метода ignoredElements(final Set ignoredElements)

Screenshot actualScreenshot = new AShot()   .shootingStrategy(ShootingStrategies.viewportPasting(200))   .coordsProvider(new WebDriverCoordsProvider())   .ignoredElements(ignoredElements)   .takeScreenshot(getWebDriver());

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

expectedScreenshot.setIgnoredAreas(actualScreenshot.getIgnoredAreas());

Сравнение скриншотов

После того как был получен актуальный скриншот, применены правила и фильтры к нему и эталонному скриншоту, сопоставляем их и аттачим в отчёт.

ImageDiff diff = new ImageDiffer().withDiffMarkupPolicy(new ImageMarkupPolicy().withDiffColor(Color.RED)).makeDiff(expectedScreenshot, actualScreenshot);    if(diff.getDiffSize()!=0){       Allure.label("testType", "screenshotDiff");       attachImg("expected", expectedScreenshot.getImage());       attachImg("actual", actualScreenshot.getImage());       attachImg("diff", diff.getMarkedImage());       attachImg("diff (прозрачность)", diff.getTransparentMarkedImage());       Assert.fail("Скрины отличаются");    }
 Пример отчета с шагами и вложениями (без блока Screen Diff) Пример отчета с шагами и вложениями (без блока Screen Diff)

Для удобства просмотра отличий используем плагин Allure ScreenDiff, который добавляет специальный блок в сценарий, внутри отчёта, с двумя режимами:

  • Отображение отличий с подсветкой (Show diff);

  • Отображение формы с режимом наложения (Overlay) с передвигаемым по горизонтали ползунком для удобного визуального сопоставления текущего и ожидаемого результата.

Отображение отличий с подсветкой (Show diff)Отображение отличий с подсветкой (Show diff) Отображение формы с режимом наложения (Overlay) Отображение формы с режимом наложения (Overlay)

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

А в чём польза?

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

Пользователи мобильной версии версии сайта бренда долгое время вместо кнопки Узнайте больше видели Узнайте боль (спасибо ребятам из Альфа-банка, которые первыми это заметили). Это один из примеров, который вызывает больше улыбку чем неудобство, но бывают ситуации, которые не столь безобидны. На этом пока всё. Всем стабильных тестов! :)

Подробнее..

Полное руководство по CSS Flex опыт использования

20.04.2021 00:18:08 | Автор: admin

Как и CSS Grid, Flex Box довольно сложен, потому что состоит из двух составляющих: контейнера и элементов внутри него.

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

Это все, на что способен Flex.Это все, на что способен Flex.

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

CSS Flex или Flex Box

Flex это набор правил для автоматического растягивания нескольких столбцов и строк внутри родительского контейнера.

display:flex

В отличие от многих других свойств CSS, в Flex есть основной контейнер и вложенные в него элементы. Некоторые свойства CSS-Flex относятся только к контейнеру. А другие можно применить только к элементам внутри него.

Вы можете думать о flex-элементе как о родительском контейнере со свойством display: flex. Элемент, помещенный в контейнер, называется item. Каждый контейнер имеет границы начала(flex-start) и конца гибкости(flex-end), как показано на этой диаграмме.

Горизонтальная (main) и вертикальная (cross) оси

Хотя список элементов представлен линейно, необходимо обращать внимание на строки и столбцы. По этой причине Flex включает в себя координатные оси. Горизонтальная ось называется main-axis, а вертикальная cross-axis.

Чтобы управлять шириной содержимого контейнера и промежутками между элементами, которые растягиваются вдоль main-axis, необходимо использовать Justify-content. Для управления вертикальными изменениями элементов необходимо использовать align-items.

Если у вас есть 3 столбца и 6 элементов, Flex автоматически создаст вторую строку для размещения оставшихся элементов. Если у вас в списке более 6 элементов, будут созданы дополнительные строки.

По умолчанию, элементы Flex равномерно распределяются внутри контейнера по горизонтальной оси. Мы рассмотрим различные свойства и значения.

Вы можете определять количество столбцов.Вы можете определять количество столбцов.

Распределение строк и столбцов внутри родительского элемента определяется свойствами CSS Flex flex-direction, flex-wrap и некоторыми другими, которые будут продемонстрированы дальше.

:У нас есть произвольное n-количество элементов, расположенных в контейнере. По умолчанию элементы растягиваются слева направо. Однако направление можно изменить. :У нас есть произвольное n-количество элементов, расположенных в контейнере. По умолчанию элементы растягиваются слева направо. Однако направление можно изменить.

Direction

Можно задать направление движения элементов (по умолчанию слева направо).

flex-direction: row-reverse изменяет направление движения списка элементов. По умолчанию стоит значение row, что означает движение слева направо.

Wrap

flex-wrap: wrap определяет перенос элементов на другую строку, когда в родительском контейнере заканчивается место.

Flow

flex-flow включает в себя flex-direction и flex-wrap, что позволяет определять их с помощью одного свойства.

Примеры:

  • flex-flow: row wrap определяет значения flex-direction как row и flex-wrap как wrap.

  • flex-flow:row wrap-reverse (перенос элементов вверх)

  • flex-flow:row wrap (стандартный перенос элементов); justify-content: space-between (пробел между элементами);

  • flex-flow: row-reverse wrap (направление движения справа налево со стандартным переносом сверху вниз)

  • flex-flow: row-reverse wrap-reverse (направление движения справа налево и обратный перенос элементов);

  • flex-flow: row wrap; justify-content: space-between; (стандартный перенос и направление; расстояние между элементами)

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

Когда мы меняем flex-direction на column, свойство flex-flow ведет себя точно так же, как и в предыдущих примерах. За исключением wrap-reverse, когда элементы переносятся снизу вверх.

justify-content

Я получил много просьб прояснить приведенный выше пример. Для этого я создал анимацию:

Анимированные возможности justify-content. Анимированные возможности justify-content.

Надеюсь, эта CSS-анимация поможет лучше понять работу justify content.

Свойства следующие:flex-direction:row; justify-content: flex-start | flex-end | center | space-between | space-around | stretch | space-evenly. В этом примере мы используем только 3 элемента в строке.

Нет никаких ограничений на количество элементов, которые можно использовать в Flex. Эти диаграммы демонстрируют только поведение элементов, когда одно из перечисленных значений применяется к свойству justify-content .

То же свойство justify-content используется для выравнивания элементов, когда flex-direction: column. То же свойство justify-content используется для выравнивания элементов, когда flex-direction: column.

Packing Flex Lines (согласно спецификации Flex)

Я не уверен, реализовано ли это в каком-либо браузере, но когда-то это было частью спецификации CSS-flex и, вероятно, стоит упомянуть об этом для полноты картины.

В спецификации Flex это называется Packing Flex Lines. По сути, это работает так же, как в примерах выше. Однако стоит обратить внимание, что интервал расположен между целыми группами элементов. Это полезно, когда вы хотите создать зазоры между группами.

Packing Flex Lines, но теперь с flex-direction: column Packing Flex Lines, но теперь с flex-direction: column

align-items

align-items контролирует выравнивание элементов по горизонтали относительно родительского контейнера.

flex-basis

flex-basis работает аналогично другому свойству CSS: min-width. Оно увеличивает размер элемента в зависимости от содержимого. Если свойство не задействуется, то используется значение по умолчанию.

flex-grow

flex-grow применяется к конкретному элементу и масштабирует его относительно суммы размеров всех других элементов в той же строке, которые автоматически корректируются в соответствии с заданным значением свойства. В примере значение flex-grow для элементов было установлено на 1, 7 и (3 и 5) в последней строке.

flex-shrink

flex-shrink это противоположность flex-grow. В примере значение flex-shrink равно 7. При таком значении размер элемента равен 1/7 размера окружающих его элементов (размер которых автоматически скорректирован).

При работе с отдельными элементами можно использовать только одно свойство из трёх: flex-grow , flex-shrink или flex-base.

order

Используя свойство order , можно изменить естественный порядок элементов.

justify-items

И последнее, что нужно для тех, кто хочет использовать CSS Grid вместе с Flex Box... justify-items в CSS Grid похожи на justify-content в Flex. Свойства, описанные на приведенной выше диаграмме, не будут работать в Flex, но в значительной степени эквивалентны сетке для выравнивания содержимого ячеек.

Опыт веб-студии ITSOFT

Мы в веб-студии ITSOFT перешли на Flex в 2010 году. В основе всех наших новых проектов лежит именно эта технология. Наш опыт показал, что она позволяет создавать адаптивные и кроссбраузерные сайты с действительно красивым дизайном.

При использовании Flex нужно учитывать, что:

  • Flex-элементы по умолчанию ужимаются под свое содержимое; Это может пригодиться, когда есть блоки, размер которых изначально неизвестен и зависит от количества контента.

    Примеры: пункты меню в https://ketoplus.ru/

  • Внешние отступы flex-элементов не схлопываются и не выпадают, в отличие от блочной модели.

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

    Пример: блоки в http://velpharm.ru/about/veltrade/

  • Flex-элементы умеют перераспределять свободное пространство вокруг себя, таким образом меняя свои размеры;

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

    Пример: главная страница http://oflomil.ru/

  • Внутри одного флекс-контейнера можно менять порядок флекс-элементов, хотя в DOM-дереве порядок остается неизменным.

    Бывают макеты страниц, в которых порядок следования элементов отличается на мобильной и десктопной версиях. Flex справится с задачей.

    Пример: разный порядок следования логотипа и навигации в шапке в мобильной и десктопной версиях (http://elmucin.ru/).

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

    Пример: кнопка всегда находится в нижней части карточки статьи (https://rabiet.ru/experts/), блок продукция (https://stomatofit.ru/#products).

  • Flex-элементы могут переноситься на следующую строку, если указано соответствующее свойство.

    Эта особенность полезна в каталогах и различных списках, где изначально количество всех элементов неизвестно. Если их станет слишком много и предусмотрен перенос, то страница в этом случае не развалится.

    Пример: каталог Велфарм (http://velpharm.ru/catalog/), блок Где купить (http://valosemid/#partners, https://gopantomid.ru/)

Стоит отметить, что Flexbox поддерживается в Internet Explorer 10-11, хоть и с некоторыми оговорками.

Некоторые интересные фишки Flex мы реализовали на сайте oflomil.ru. На разводящей странице есть 3 столбца на всю высоту видимой области экрана. На мобильном они трансформируются в 3 строки, каждая из которых равномерно занимает место в видимой части экрана. На продуктовых страницах без единого скрипта реализована бегущая строка. Текстовые элементы расположены в ряд благодаря inline-flex. Все свободное пространство в ряду распределено между этими элементами равномерно. Наш собственный сайт также свёрстан с использованием Flex.

Реализация бегущей строки с Flex Реализация бегущей строки с Flex

Из недостатков можно отметить то, что Flex не хватает при верстке писем. Не во всех почтовых клиентах он работает корректно.

В скором времени большую распространённость получит технология Grid. Однако Grid не замена Flexbox. Флексы в связке с гридами помогут решать задачи, которые раньше были сложными или вовсе невозможными. К примеру, Masonry-раскладка одна из тех вещей, которую нельзя полноценно реализовать на данный момент. После появления возможностей спецификации Grid Layout 3 уровня в браузерах, реализация такой раскладки станет возможной и к тому же простой.

Источники: оригинал руководства с картинками


Дата-центр ITSOFT размещение и аренда серверов и стоек в двух дата-центрах в Москве. За последние годы UPTIME 100%. Размещение GPU-ферм и ASIC-майнеров, аренда GPU-серверов, лицензии связи, SSL-сертификаты, администрирование серверов и поддержка сайтов.

Подробнее..

Перевод Адаптивный дизайн как антипаттерн

27.04.2021 16:10:26 | Автор: admin


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

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

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

Пространственный газлайтинг


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

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

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

Межсайтовая непоследовательность


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

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

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

Казалось бы, почему пользователь просто не отрегулирует размер окна, если попадет на веб-страницу, для просмотра которой требуется окно пошире. В конце концов, именно так приходилось действовать пользователю до появления адаптивного дизайна, когда была возможность просто переключаться между веб-страницами с заданной фиксированной шириной. Но на самом деле не все так просто: на неадаптивных страницах совершенно ясно, нужно ли изменить размер окна, чтобы в нем поместилась вся страница. А на адаптивной веб-странице пользователю ничто не подсказывает, эй! В такое окно, как у тебя сейчас, вся страница не влезет. Нет ни полосы прокрутки, ни обрезки содержимого; в лучшем (или, полагаю, в худшем) случае есть меню-гамбургер или какой-нибудь другой странный как бы мобильный интерфейс.

Что делать пользователю?


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

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

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

Что делать веб-дизайнеру?


Я оставил этот раздел напоследок, поскольку он самый важный. Все вышеизложенное подводит нас к простому выводу:веб-дизайнерам нужно долго и крепко обдумывать, как именно реализовать адаптивный дизайн.

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

  1. Настольный ПК/ноутбук
  2. Планшет
  3. Смартфон

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

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

let mobile = navigator.userAgent.match(/Mobi/);let ipad = navigator.userAgent.match(/iPad/);let android = navigator.userAgent.match(/Android/);if (mobile && !ipad)this is a phoneelse if (ipad || android)this is a tablet

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



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

Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!

Подробнее..

Перевод Как решить проблему блокировки изображений в email-рассылках полное руководство

11.01.2021 18:14:50 | Автор: admin
Как бороться с блокировкой изображений в электронных письмах?Как бороться с блокировкой изображений в электронных письмах?

Блокировка изображений одна из самых серьезных проблем, с которой сталкиваются маркетологи, когда проводят email-кампании. Обычно причина кроется в настройках по умолчанию или личных предпочтениях получателя. В результате у большого количества подписчиков изображения блокируются автоматически и письма не доносят до человека основную мысль сразу же, а то и вовсе выглядят испорченными. Поэтому важно оптимизировать рассылки для режима отключенных изображений. Как это сделать? Сервис DashaMail делится лайфхаками.

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

Картинки в имейле не прогрузились...Картинки в имейле не прогрузились...

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

Настройки по умолчанию в популярных почтовых службах

Стандартных настроек для блокировки изображений нет. Ниже мы схематично описываем их для самых популярных почтовых клиентов для ПК, веб-служб и мобильных устройств. Мы добавили в сравнение поддержку ALT-текстов (замещающих или альтернативных текстов) и стилизованных ALT-текстов (стилизованных замещающих текстов). Эти атрибуты HTML-разметки необходимы. Когда изображения в письме отключены или недоступны, заполненный альтернативный текст часто показывается вместо изображения.

Настройки десктопных программ

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

Отметим несколько нюансов почтовых служб Outlook. Outlook 2000, 2003, 2007, 2010 и 2013 добавляют к альтернативному тексту длинное сообщение от службы безопасности. Из-за этого он становится практически бесполезным, ведь он появляется только в конце предупреждения:

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

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

Веб-версии почтовиков

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

* По умолчанию открытие изображений разрешено, но для теста было запрещено вручную. ** Изображения разрешены по умолчанию, и запретить их отображение нельзя. В GMX и в Web.de отображение картинок запрещено для писем, находящихся в папке Спам. Если это произошло, то изображения сворачиваются, а альтернативный текст не поддерживается.* По умолчанию открытие изображений разрешено, но для теста было запрещено вручную. ** Изображения разрешены по умолчанию, и запретить их отображение нельзя. В GMX и в Web.de отображение картинок запрещено для писем, находящихся в папке Спам. Если это произошло, то изображения сворачиваются, а альтернативный текст не поддерживается.

Хотя все веб-версии почтовиков поддерживают альтернативный текст, работа его стилизованной версии зависит от того, какой браузер использует подписчик. Стилизованный альтернативный текст отображается в текущих версиях Chrome и Firefox, а в Internet Explorer нет. В этом браузере видно его цвет, но не такие атрибуты как шрифт, размер, стиль и насыщенность.

Отображение заблокированных изображений в браузере ChromeОтображение заблокированных изображений в браузере ChromeОтображение заблокированных изображений в браузере Internet ExplorerОтображение заблокированных изображений в браузере Internet Explorer

Outlook.com относится к блокировке изображений немного странно. Он по умолчанию отключает картинки не во всех письмах, а только в тех, которые были отправлены от подозрительных пользователей. При этом неясно, по какому принципу отправителей делят на подозрительных и проверенных. Кроме того, пользователи Outlook могут запрещать отображение картинок во всех имейлах, которые приходят от отправителей не из списка контактов. Почтовый сервис по-разному обрабатывает эти два вида фильтрации:

  • в электронных письмах с подозрительных адресов он не показывает картинки, но отображает альтернативный текст;

  • для пользователей, у которых установлены более строгие настройки блокировки содержимого, Outlook.com использует серые поля.

Вот такую красоту видят получатели рассылок в веб-версии Outlook вместо заблокированных изображенийВот такую красоту видят получатели рассылок в веб-версии Outlook вместо заблокированных изображений

Gmail не блокирует изображения с декабря 2013 года. Казалось бы, маркетологи и дизайнеры должны быть в восторге письма будут отображаться как нужно, а открытое отслеживание станет более надежным. Однако и это изменение не прошло гладко. Нередко изображения повреждаются или искажаются из-за проблем с кэшированием.

Мобильные почтовые клиенты

Хорошие новости для дизайнеров: у мобильных клиентов почтовых служб отличная поддержка альтернативного и альтернативного стилизованного текста!

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

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

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

Альтернативный и альтернативный стилизованный тексты поддерживаются в BlackBerry Z10, но отображаются не всегда, например, в тех случаях, когда не помещаются в рамки максимального размера изображений. Если многие из ваших подписчиков пользуются BlackBerry, используйте краткий альтернативный текст!

Outlook.com для Android и iPhone по умолчанию блокирует изображения по той же схеме что и Outlook для ПК.

И, наконец, Yahoo! Для пользователей, которые читают имейл-сообщения в браузере Android, используется уникальная тактика блокировки изображений. Yahoo! блокирует все изображения, цвета фона, ссылки и так далее и отображает только текст из HTML-версии. Да-да, это не опечатка только текст из HTML, а не живой текст!

Никаких картинок только HTML-текст!Никаких картинок только HTML-текст!

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

После нажатия кнопки Просмотреть HTML-сообщение полностью письмо выглядит интереснее, но картинок по-прежнему нетПосле нажатия кнопки Просмотреть HTML-сообщение полностью письмо выглядит интереснее, но картинок по-прежнему нет

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

Как бороться с блокировкой изображений?

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

Альтернативный текст + стилизованный альтернативный текст

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

Так выглядит письмо, к изображениям в котором не добавили альтернативный текстТак выглядит письмо, к изображениям в котором не добавили альтернативный текстРассылка оживает, стоит только прописать альтернативный текстРассылка оживает, стоит только прописать альтернативный текст

Чтобы добавить альтернативный текст, нужно прописать атрибут к тегу изображения:

<img alt="insert alt text here" src="image.jpg" width="250" height="250" />

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

<img alt="" src="image.jpg" width="250" height="250" />

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

<img style="font-size: 15px; color: #ffffff; font-style: italic; font-weight: bold; height: 250px; width: 250px;" alt="insert alt text here" src="image.jpg" width="250" height="250" />

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

Со стилизованным альтернативным текстом письмо выглядит еще интереснееСо стилизованным альтернативным текстом письмо выглядит еще интереснее

Неубиваемые кнопки

Хотя тексты и дизайн вашей кампании могут иметь большое значение при взаимодействии подписчиков с письмами, обычно самая важная часть призыв к действию (Call to Action, он же CTA). CTA должны быть доступны для просмотра, даже если картинки отключены. Кнопки на основе изображений не обрабатываются они блокируются. Пользователи не выполняют действия, а конверсия не повышается. Да, есть вариант с текстовыми ссылками, но не лучше ли немного повеселиться и попробовать сохранить стиль бренда, используя неубиваемые кнопки?

Неубиваемые кнопки состоят из текстового слоя в сочетании с цветом фона, стилизованного под кнопку с изображением. Создавать их можно самыми разными способами (например, бесплатный инструмент Campaign Monitor), но мы предпочитаем использовать простой HTML и встроенные стили, которые хорошо подходят для большинства почтовых служб.

<table border="0" cellspacing="0" cellpadding="0" width="80%">

<tr>

<td bgcolor="#0b534a" style="padding: 12px 18px 12px 18px; -webkit-border-radius:3px; border-radius:3px" align="center"><a href="http://personeltest.ru/aways/litmus.com" target="_blank" style="font-size: 16px; font-family: Helvetica, Arial, sans-serif; font-weight: normal; color: #ffffff; text-decoration: none;">Visit Litmus</a></td>

</tr>

</table>

Вот пример одной из кампаний по электронной почте, в которой использовался этот метод.

Кнопка выжила даже несмотря на то, что отображение изображений запрещеноКнопка выжила даже несмотря на то, что отображение изображений запрещеноТак выглядит то же самое письмо, когда просмотр изображений разрешенТак выглядит то же самое письмо, когда просмотр изображений разрешен

Баланс изображений и текста

Некоторые ниши (розничная торговля, туризм) предпочитают использовать электронные письма, основой которых являются изображения. Это нужно, чтобы поддерживать узнаваемость бренда и создавать красивый дизайн, но мы не рекомендуем так делать. Как поясняет Campaign Monitor, в электронных письмах на основе изображений не учитываются размеры файлов для пользователей смартфонов, доступность или соотношение кода HTML и текста, которые важны для алгоритмов анти-спам фильтров. Все это не оставляет выхода, когда изображения отключены. Взгляните на это письмо:

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

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

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

  • доступность;

  • отсутствие проблем со спамом из-за соотношения HTML кода и фактического текста;

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

Электронное письмо HelloTravel прекрасный пример имейла, в котором для борьбы с блокировкой изображений используется много фактического текста и неубиваемые кнопки:

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

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

Цветной фон

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

Письмо с цветным фоном, но отображение картинок запрещеноПисьмо с цветным фоном, но отображение картинок запрещеноПисьмо с цветным фоном, отображение картинок включеноПисьмо с цветным фоном, отображение картинок включено

Хотя есть несколько способов кодирования цвета фона, рекомендуется использовать атрибут HTML bgcolor (Background Color) с 6-значным HEX-кодом.

Мозаика и пиксельная графика

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

Отображение картинок в режиме блокировки изображенийОтображение картинок в режиме блокировки изображенийТо же самое письмо, когда изображения доступныТо же самое письмо, когда изображения доступны

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

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

Выводы

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

Подробнее..

Из песочницы Фетиш WYSIWYG или Как правильно скрещивать ужа с ежом

05.11.2020 12:07:06 | Автор: admin

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


Уяснив стартовые данные, я впал в лёгкое уныние. Больше всего в тот момент мне хотелось сослаться на обстоятельства непреодолимой силы, перегруженность, невменяемость, сезонное обострение ящура короче говоря, найти любой повод и на волю, в пампасы! Но сакраментальное ты ж программист! и осторожное буду должен уже прозвучали, вздохи химика становились все тяжелее, размеренно падая на и без того узкую тропку к отступлению, химиковы глаза за толстыми стёклами очков давали изрядную фору фирменному взгляду Кота-в-сапогах из Шрека...


Пути назад не было. Квест начался.


Химик пришел не с пустыми руками. Он принёс множество листиков с зачем-то уже напечатанным текстом и формулами, тщательно нарисованными шариковой ручкой в специально сделанных пропусках между абзацами. Впрочем, тут же выяснилось, что большая часть СНТ всё ещё пребывает в недрах могучего химикова ума, а листочки это так, наброски, черновики и вообще проба пера.


Ситуация вырисовывалась невесёлая. Химик весьма уверенно набирал текст в notepadе и даже, кажется, знал, как выделить строчку в Wordе курсивом. Я совершенно точно помнил формулы воды, этилового спирта и был убеждён, что лить воду в серную кислоту ни в коем случае нельзя. Или наоборот? Неважно, главное на этом пересечение наших познаний исчерпывалось. Вопрос вырисовывался один, но глобальный: как? Как организовать работу так, чтобы химик мог излить ещё не рождённый СНТ на бумагу то есть, в какой-то текстовый формат, а я мог бы разобраться в структуре документа и сверстать его надлежащим образом, вставив в нужные места все упомянутые выше красоты?


Word отпал, когда к концу следующего дня химик прислал первые наброски нашего с ним великого творения, в порядке здоровой инициативы набранные с помощью именно это редактора. По привычке он набирал в нём текст как в блокноте: абзацные отступы, состряпанные из ядрёной смеси пробелов и табуляций, ряды пустых абзацев, долженствующие перенести текст на следующую страницу, нумерованные вручную списки, колонки текста, выровненные все теми же многострадальными пробелами и переносами строк в самых неожиданных местах Химик блистал! К сожалению, он совсем забыл про поля, и когда я выставил их ширину в требуемые значения, всё это великолепие рассыпалось в совершенно невзрачные и не поддающиеся восстановлению ошмётки. What you see оказалось не совсем what you get, а говоря по правде совсем не.


Править все присылаемые химиком черновики и наброски присваивать нужные стили абзацам и заголовкам, делать списки списками, разрывы страниц разрывами, вычищать ненужные пробелы и т.д. и т.п. мне совершенно не улыбалось. Кроме того, я абсолютно не представлял (что уж там, я и сейчас пребываю в счастливом неведении) как изобразить в этом самом Wordе хотя бы структурную формулу какого-нибудь бензола, не говоря уже о чём-то посложнее не рисовать же, в самом деле, картинки?


Решение пришло после короткого гугления: Markdown! Прикинув, что возможности этого простого, как табуретка, языка разметки перекрывают потребности химика по оформлению текстовой части его работы на 99%, я подыскал внятное руководство и переправил его химику с предложением обсудить этот вариант по скайпу. На удивление, химик воспринял идею без особого сопротивления: как потом выяснилось, вольная борьба с Wordом изрядно поднадоела ему самому.


По обсуждении, план совместной работы над документом сводился к следующему:


  • Химик, используя подходящий Markdown-редактор, готовит текстовую часть документа, соблюдая его структуру, вводя разделы, подразделы и т.п.
  • Простые формулы вписываются непосредственно в Markdown-разметку, сложные и структурные рисуются от руки, сканы пересылаются мне; место в тексте для них маркируется.
  • Данные для таблиц, диаграмм и графиков присылаются мне в сыром виде (как оказалось, это были в основном CSV-файлы); место в тексте для них также маркируется.
  • Я подготавливаю сложную вёрстку (титульник, формулы, таблицы, диаграммы и графики, библиографию и т.д.) как компоненты составного документа LaTeX.
  • После подготовки и вычитки всех материалов я верстаю их в единый документ LaTeX, добавляю содержание, приложения и т.п.
  • Профит!

И работа пошла, пусть поначалу со скрипом и неровно, но пошла! После нескольких дней ошибок, химик на удивление неплохо приноровился к незатейливому синтаксису Markdown, благо, редактор не слишком отличался от его излюбленного блокнота. Для удобства, текст публикации был разбит на несколько md-файлов, по числу основных разделов. Во избежание случайной утраты данных проект был помещён под контроль VCS; правда, мне приходилось рулить проектом сразу на двух машинах: на своём и, в ипостаси альтер-эго химика посредством TeamViewer на его компьютере.


Предлагая к использованию Markdown, я планировал воспользоваться всеми любимым pandocом и просто-напросто преобразовать md-файлы в исходники LaTeX, но время поджимало, и компоновку итогового документа пришлось начать, не дожидаясь полного завершения работ химиком. И вот тут-то Оказалось, я здорово недооценил перфекционизм и энтузиазм моего соавтора: просматривая очередной коммит проекта, я заметил массовые и довольно объёмные изменения в md-файлах, которые были давно вычитаны, исправлены, преобразованы в LaTeX и щедро нафаршированы формулами, таблицами и прочими кулинарными ингредиентами. Как выяснилось, в порыве творческого экстаза химик в очередной раз перечитал уже набранные разделы, остался не весьма ими доволен и, ничтоже сумняшеся, тут же устранил недочёты. Всю ночь возился! горделиво заявил он по скайпу в ответ на мои робкие попытки узнать, что же произошло.


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


Из этих двух вариантов всё более хотелось выбрать третий: пампасы! Тем более, что химик явно недоумевал, почему я не разделяю восторгов по поводу улучшений и украшений, несомненно нашёптанных ему его органико-химической музой в, разумеется, лучшие творческие минуты его жизни, что не оставляло сомнений в том, что муза посетит его ещё не раз и процесс внесения правок и изменений приобретает мрачноватую перспективу стать перманентным и всеобъемлющим.


И вдруг! Покопавшись в пакетах LaTeX, я с удивлением обнаружил среди прочих пакет с многообещающим названием markdown. Ещё не веря в удачу, я начал читать описание Да! Этот пакет позволял включать Markdown-файлы в документ LaTeX as is, без сторонних утилит, без дополнительных правок или излишних телодвижений, при этом позволяя использовать в Markdown-разметке конструкции LaTeX!


Теперь мне оставалось только прописать в md-текстах химика включение иллюстраций по месту (в виде tex-разметки), залить эти изменения на его компьютер и строго-настрого запретить ему править или выкидывать вот эти вот непонятные закорючечки. Остальной химиков текст ему позволялось изменять как угодно, в любое время дня и ночи, на пару с музой или без содействия оной. Простая пересборка LaTeXом подтягивала в итоговый документ все изменения, никак не отражающиеся на уже проделанной работе. Система контроля версий довершала глубоко эшелонированную линию обороны от возможных деструктивных поползновений.


Публикация была готова не совсем в срок, но до дедлайна уложиться удалось.


Ф-ф-у-у-у-ух.


Повторюсь, это вполне реальная история. Да, есть ещё люди, которые используют Word (или LibreOffice Writer, или AbiWord, или ) как пишущую машинку, не заморачиваясь стилями, параметрами абзацев и тому подобными, совершенно бессмысленными с их точки зрения, штуками. А почему нет? Это же вовсеушипрожужжанный WYSIWYG, они же видят перед собой что-то, вполне себе читаемое. Да, при этом они могут быть вполне успешными профессионалами в своей области. Да, им непросто объяснить суть проблемы, а научить правильной вёрстке непросто вдвойне. И да, порой им приходится готовить публикации...


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


Удачи!

Подробнее..
Категории: Верстка , Markdown , Latex

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru