Улучшаем юзабилити в вебе или создание Skeleton Screens с CSS

Улучшаем юзабилити в вебе или создание с помощью CSS

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

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

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

Иллюзия скорости

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

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

В веб-приложении эта концепция может заключаться в отображении макетов текста, изображений или других элементов контента, называемых skeleton screens. Если вы до сих пор не поняли о чём речь, то посмотрите на то, как это используют на практике такие «малоизвестные компании» как Facebook, Google, Slack и другие:

Улучшаем юзабилити в вебе или создание  Skeleton Screens с CSS
Пример skeleton screens Slack
Улучшаем юзабилити в вебе или создание  Skeleton Screens с CSS
Пример skeleton screens Facebook

Пример

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

Улучшаем юзабилити в вебе или создание  Skeleton Screens с CSS

Вы можете минимизировать превью до основных визуальных форм, до так называемого скелета пользовательского интерфейса, как на примере:

Улучшаем юзабилити в вебе или создание  Skeleton Screens с CSS

Всякий раз когда ваше веб приложение обращается к серверу, пользователю показывается skeleton screens, до тех пор пока фоном подгружается контент. Как только содержимое страницы будет полностью загружено, просто замените скелет на актуальный контент. Это можно сделать с помощью ванильного JavaScript или с помощью такой библиотеки, как React.

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

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

Рисуем skeleton screen в CSS

Сначала нужно нарисовать основные фигуры, которые будут составлять макет скелета. Это можно сделать, добавив различные градиенты в свойство background-image. По умолчанию линейные градиенты отрисовываются сверху вниз с различными цветовыми переходами. Если мы просто определим один цвет и оставим остальные прозрачными, мы сможем рисовать фигуры.

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

.skeleton {
  background-repeat: no-repeat;
  background-image: 
    /* layer 2: avatar */
    /* white circle with 16px radius */
    radial-gradient(circle 16px, white 99%, transparent 0),
    /* layer 1: title */
    /* white rectangle with 40px height */
    linear-gradient(white 40px, transparent 0),
    /* layer 0: card bg */
    /* gray rectangle that covers whole element */
    linear-gradient(gray 100%, transparent 0);
}

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

.skeleton {
  background-size:
    32px 32px,  /* avatar */
    200px 40px, /* title */
    100% 100%;  /* card bg */
}

Последним шагом является расположение элементов на макете. Это работает так же, как position:absolute, со значениями, представляющими свойства left и top. Мы можем, например, имитировать заполнение 24px для аватара и заголовка, чтобы соответствовать внешнему виду макета реального контента.

.skeleton {
  background-position:
    24px 24px,  /* avatar */
    24px 200px, /* title */
    0 0;        /* card bg */
}

Разбавим скелет кастомными свойствами

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

К счастью, для написания стиля скелета  более лаконично, мы можем использовать кастомные свойства CSS.

.skeleton {
  /*
    define as separate properties
  */
  --card-height: 340px;
  --card-padding:24px;
  --card-skeleton: linear-gradient(gray var(--card-height), transparent 0);

  --title-height: 32px;
  --title-width: 200px;
  --title-position: var(--card-padding) 180px;
  --title-skeleton: linear-gradient(white var(--title-height), transparent 0);

  --avatar-size: 32px;
  --avatar-position: var(--card-padding) var(--card-padding);
  --avatar-skeleton: radial-gradient(
    circle calc(var(--avatar-size) / 2), 
    white 99%, 
    transparent 0
  );

  /* 
    now we can break the background up 
    into individual shapes 
  */
  background-image: 
    var(--avatar-skeleton),
    var(--title-skeleton),
    var(--card-skeleton);

  background-size:
    var(--avatar-size),
    var(--title-width) var(--title-height),
    100% 100%;

  background-position:
    var(--avatar-position),
    var(--title-position),
    0 0;
}

Мало того, что так более читабельно, так ещё и будет легче изменить некоторые значения позже. Кроме того, мы можем использовать переменные (например, — avatar-size, —card-padding и т. д.) для определения стилей актуального макета и всегда синхронизировать с версией скелета .

Добавление @media для настройки мараметров ширины скелета теперь также довольно просто:

@media screen and (min-width: 47em) {
  :root {
    --card-padding: 32px;
    --card-height: 360px;
  }
}

Внимание: данные свойства и решения имеют очень хорошую поддержку браузерами, но к сожалению не 100%. Такие «жемчужины» как IE/Edge немного отстают в этом вопросе, но это решаемо используя переменные Sass.

Добавляем анимацию

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

Вот полный пример, того что у нас сегодня получилось:

/*
 * Variables
 */

:root {  
  --card-padding: 24px;
  --card-height: 340px;
  --card-skeleton: linear-gradient(lightgrey var(--card-height), transparent 0);
  
  --avatar-size: 32px;
  --avatar-position: var(--card-padding) var(--card-padding);
  --avatar-skeleton: radial-gradient(circle 16px at center, white 99%, transparent 0
  );
  
  --title-height: 32px;
  --title-width: 200px;
  --title-position: var(--card-padding) 180px;
  --title-skeleton: linear-gradient(white var(--title-height), transparent 0);
  
  --desc-line-height: 16px;
  --desc-line-skeleton: linear-gradient(white var(--desc-line-height), transparent 0);
  --desc-line-1-width:230px;
  --desc-line-1-position: var(--card-padding) 242px;
  --desc-line-2-width:180px;
  --desc-line-2-position: var(--card-padding) 265px;
  
  --footer-height: 40px;
  --footer-position: 0 calc(var(--card-height) - var(--footer-height));
  --footer-skeleton: linear-gradient(white var(--footer-height), transparent 0);
  
  --blur-width: 200px;
  --blur-size: var(--blur-width) calc(var(--card-height) - var(--footer-height));
}

/*
 * Card Skeleton for Loading
 */

.card {
  width: 280px; //demo
  height: var(--card-height);
  
  &:empty::after {
    content:"";
    display:block;
    width: 100%;
    height: 100%;
    border-radius:6px;
    box-shadow: 0 10px 45px rgba(0,0,0, .1);

    background-image:
      linear-gradient(
        90deg, 
        rgba(lightgrey, 0) 0, 
        rgba(lightgrey, .8) 50%, 
        rgba(lightgrey, 0) 100%
      ),                          //animation blur
      var(--title-skeleton),      //title
      var(--desc-line-skeleton),  //desc1
      var(--desc-line-skeleton),  //desc2
      var(--avatar-skeleton),     //avatar
      var(--footer-skeleton),     //footer bar
      var(--card-skeleton)        //card
    ;

    background-size:
      var(--blur-size),
      var(--title-width) var(--title-height),
      var(--desc-line-1-width) var(--desc-line-height),
      var(--desc-line-2-width) var(--desc-line-height),
      var(--avatar-size) var(--avatar-size),
      100% var(--footer-height),
      100% 100%
    ;
    
    background-position:
      -150% 0,                      //animation
      var(--title-position),        //title
      var(--desc-line-1-position),  //desc1
      var(--desc-line-2-position),  //desc2
      var(--avatar-position),       //avatar
      var(--footer-position),       //footer bar
      0 0                           //card
    ;

    background-repeat: no-repeat;
    animation: loading 1.5s infinite;
  }
}

@keyframes loading {
  to {
    background-position:
      350% 0,        
      var(--title-position),  
      var(--desc-line-1-position),
      var(--desc-line-2-position),
      var(--avatar-position),
      var(--footer-position),
      0 0
    ;
  }
}


/* 
 * Demo Stuff
 */

body {
  min-height:100vh;
  background-color:#FFF;
  display:flex;
  justify-content:center;
  align-items:center;
}

И выглядит это всё примерно так:

Улучшаем юзабилити в вебе или создание  Skeleton Screens с CSS

Перевод статьи автора MAX BÖCK: Building Skeleton Screens with CSS Custom Properties 

Улучшаем юзабилити в вебе или создание  Skeleton Screens с CSS

Гик, хакинтошник, линуксоид, считаю что немного умею в вебдизайн и сайтостроение

Топ 10 JavaScript и CSS библиотек октября 2018 года

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

1. Direction Reveal

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

Топ 10 JavaScript и CSS библиотек октября 2018 года

2. Toast UI Editor

Это markdown и WYSIWYG редактор , легко переключаемый между режимами markdown и WYSIWYG во время использования. Он предлагает просмотр в реальном времени визуализированного HTML, немедленную проверку синтаксических ошибок и синхронизацию прокрутки между режимами markdown и предварительного просмотра. Поддерживает ряд полезных расширений, таких как color picker, блок диаграмм, блок кода UML и многие другие.

Топ 10 JavaScript и CSS библиотек октября 2018 года

3. Micron.js

Micron — это js библиотека, которая позволяет добавлять различные CSS анимации  в элементы DOM. Интеракции могут управляться HTML атрибутами  или путем привязки методов JavaScript для изменения различных параметров, как то скорость, интенсивность и прочие.

Топ 10 JavaScript и CSS библиотек октября 2018 года

4. BaguetteBox

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

Топ 10 JavaScript и CSS библиотек октября 2018 года

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

5. Sticky-Kit

Sticky-kit — это плагин jQuery, который позволяет прикреплять элементы к определенной области на странице, заставляя их придерживаться своих границ. Используя его , вы можете закрепить сайдбар, чтобы он оставался всегда на виду при скролинге.

Топ 10 JavaScript и CSS библиотек октября 2018 года

6. Pretty Checkbox

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

Топ 10 JavaScript и CSS библиотек октября 2018 года

7. Bulma

Это бесплатный CSS фреймворк с открытым исходным кодом базирующийся на Flexbox. У Bulma есть 39 файлов .sass, которые можно импортировать отдельно. Вы можете легко его настроить  и создать свои собственные темы. Каждый элемент в Bulma является мобильно-ориентированным и оптимизирован для небольших экранов.

8. T-scroll

Мощная и простая в использовании библиотека прокрутки с полезными опциями и анимациями. Он поставляется с ванильным Sass и включает в себя большое количество CSS3 анимаций , таких как bounceIn, fadeIn, flip, rotate, zoom и многое другое. T-scroll совместим с большинством современных браузеров, включая IE 10+, Firefox, Chrome и Safari.

Топ 10 JavaScript и CSS библиотек октября 2018 года

9. Iconate

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

Топ 10 JavaScript и CSS библиотек октября 2018 года

10. Simple Icons

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

Топ 10 JavaScript и CSS библиотек октября 2018 года

А чем пользуетесь Вы? Если у вас есть на примете какие-то интересные Javascript и CSS библиотеки, просьба поделиться в комментариях.

Топ 10 JavaScript и CSS библиотек октября 2018 года

Гик, хакинтошник, линуксоид, считаю что немного умею в вебдизайн и сайтостроение