Адаптивный Pixel Perfect

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

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

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

Ниже будет немного текста про поиск решения. Если кому лень читать, можно сразу пойти поиграться на демо-странице.

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

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

Первым делом я конечно вспомнила про плагин Pixel Perfect (он как минимум есть для Chrome и Firefox), но он не подходит по ряду причин. Например, загруженные макеты не умеют меняться при переходе между страницами и при изменении окна браузера, а переключать их каждый раз руками довольно быстро надоест. Тем более, что есть медиавыражения, которые прекрасно могут переключать макеты за нас.

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

<style>
  BODY {
    background-repeat: no-repeat;
    background-position: 50% 0;
    background-image: url( 'img/index-mobile.png' );
  }

  @media (min-width: 768px) {
    BODY {
      background-image: url( 'img/index-tablet.png' );
    }
  }

  @media (min-width: 1024px) {
    BODY {
      background-image: url( 'img/index-desktop.png' );
    }
  }
</style>

Этот код вставляется в <head> каждой страницы. В нём задаются нужные медиавыражения, а ссылки на картинки меняются на актуальные макеты для каждой конкретной страницы.

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

Но по мере написания стилей на странице появляются свои фоны и картинки, и макеты в нижнем слое становятся не видны. Как быть?

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

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

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

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

Если макеты задать фоном для <body>, при изменении прозрачности <body> макеты тоже станут полупрозрачными, поэтому в качестве слоя с макетами лучше использовать элемент <html>:

<style>
  HTML {
    background-repeat: no-repeat;
    background-position: 50% 0;
    background-image: url( 'img/index-mobile.png' );
  }

  @media (min-width: 768px) {
    HTML {
      background-image: url( 'img/index-tablet.png' );
    }
  }

  @media (min-width: 1024px) {
    HTML {
      background-image: url( 'img/index-desktop.png' );
    }
  }
</style>

Как и в предыдущем случае, макеты будут лежать под разметкой, но сейчас если у <body> задан фон, их не будет видно. Сделаем слой с разметкой полупрозрачным, добавив opacity для <body>:

<style>
  /* Используем &lt;html> как слой с макетами */
  HTML {
    background-repeat: no-repeat;
    background-position: 50% 0;
    background-image: url( 'img/index-mobile.png' );
  }

  @media (min-width: 768px) {
    HTML {
      background-image: url( 'img/index-tablet.png' );
    }
  }

  @media (min-width: 1024px) {
    HTML {
      background-image: url( 'img/index-desktop.png' );
    }
  }

  /* Делаем слой с разметкой полупрозрачным */
  BODY {
    opacity: .5;
  }
</style>

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

Она позволяет управлять прозрачностью <body> (в данном случае вместо макетов просто полосатый фон), её можно таскать по странице и можно выключить, если не нужна.

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

Установка в итоге выглядит вот так:

  1. Установите пакет в папку с проектом через npm:
    npm i pixel-glass --save-dev
  2. Положите картинки с макетами в ваш проект в папку img (или в другую папку с картинками внутри проекта).
  3. Вставьте в <head> страницы такой код:
    <!-- Pixel Glass -->
    <style>
      HTML {
        background-repeat: no-repeat;
        background-position:  50% 0;
        /* По умолчанию мобильный макет */
        background-image: url( "img/index-mobile.png" );
      }
      /* Планшет */
      @media ( min-width: 760px ) {
        HTML {
          /* Планшетный макет */
          background-image: url( "img/index-tablet.png" );
        }
      }
      /* Десктоп */
      @media ( min-width: 960px ) {
        HTML {
          /* Десктопный макет */
          background-image: url( "img/index-desktop.png" );
        }
      }
    
      BODY {
        opacity: .5;
      }
    </style>
    
    <link rel="stylesheet" href="../node_modules/pixel-glass/styles.css">
    <script src="../node_modules/pixel-glass/script.js"></script>
    <!-- // Pixel Glass -->

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

  4. Обновите страницу и пользуйтесь.

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

UPD: библиотека переехала на npm, спасибо всем участникам обсуждения.

FAQ

  • Зачем в <head> такая колбаса кода? Почему бы медиавыражения и пути к картинкам не убрать в конфиг/настройки скрипта?

    Базовая часть — переключение макетов при изменении размеров окна — легко может быть сделана с помощью медиавыражений, для этого не нужен JavaScript. Такой код любой верстальщик может написать сам, своими руками. Pixel Glass просто делает управление прозрачностью чуть более удобным.

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

  • Мне вообще не нравится как вы всё сделали, я бы сделал всё по-другому!

    Сделайте : ) Будет здорово, если появятся новые удобные инструменты.

Ссылки по теме:
Репозиторий проекта
Демо страница с макетами
Логотип не отвечает или временно недоступенРазмеры в SVG
Наверх