Изучаем шаблоны отзывчивого навигационного меню: Закадровые шаблоны

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

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

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

Шаблоны

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

Шаблоны с «закадровыми» меню работают аналогично переключаемым: меню скрывается, когда нам нужно сохранить пространство и затем раскрывается с помощью кнопки. Вместо того чтобы полностью скрывать панель, она просто отображается вне экрана, и может быть даже частично видна.

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

  • Навигация в боковой панели (Sidebar Navigation) — меню скрывается в боковой панели слева. Навигация выезжает в сайдбар по нажатию кнопки. Мы будем использовать хак чекбокса для этого события;
  • Навигация в боковой панели с использованием Javascript (Sidebar Navigation JS) — тот же самый шаблон, но для его реализации мы используем Javascript вместо хака для чекбокса;
  • Панели (Panels) — в этом шаблоне размещаем контент в панелях. Навигация, расположенная в заголовке страницы, прокручивает страницу к нужной её части. Для обработки нажатия мыши мы будем использовать >checkbox;
  • Сайдбар + (Sidebar+) — шаблон работает так же, как и предыдущий, за исключением того, что дает больше свободы при скрытии и отображении контента. Для обработки события нажатия кнопки мыши мы будем использовать Javascript.

В этом уроке мы рассмотрим несколько различных вариантов HTML-разметки для перемещения разделов с контентом за пределы экрана и обратно. CSS – стили для каждого варианта будут похожи, но с некоторыми отличиями. Для обработки события щелчка мыши будем использовать как CSS (чекбокс и радио-кнопки), так и Javascript:

steven-rwd-nav-patterns-sidebar-nav-closed-600

Шаблон с навигацией в боковой панели

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

Введение: На маленьких экранах мы прячем меню и выводим кнопку «Меню». Кнопка связана с чекбоксом и получает сведения о двух его состояниях – отмеченном или нет. При нажатии на кнопку содержимое страницы съезжает вправо, открывая полное меню.

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

Шаг 1: HTML

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

<input id="toggle" type="checkbox" />
<nav>
  <label class="close" for="toggle" onclick><span>X</span> Закрыть</label>
  <ul id="nav">
    <li><a href="">Назад к публикациям</a></li>
    <li class="current"><a href="sidebar-nav.html">Навигация в сайдбаре</a></li>
    <li><a href="sidebar-nav-js.html">Навигация в сайдбаре с JS</a></li>
    <li><a href="sidebar+.html">Сайдбар+</a></li>
    <li><a href="panels.html">Панели</a></li>
  </ul>
</nav>
 
<div class="wrapper">
  <div class="inner">
    <header>
      <label class="btn" for="toggle" onclick>Меню</label>
    </header>
         
    <div class="container main-content">
      <div id="content"></div>
      <div id="sidebar"></div>
    </div>
       
    <section class="subfooter"></section>
    <div id="footer"></div>
  </div>
</div>

Обратите внимание, что большая часть контента обернута в два дополнительных блока div. Кнопка «Меню» находится внутри заголовка, который размещен внутри этих дополнительных блоков div. Это означает, что кнопка будет «съезжать» вправо вместе с остальным контентом.

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

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

Шаг 2: CSS - стили

Если вы прочитали предыдущее руководство на тему шаблонов с переключаемым меню, вы «узнаете» здесь кнопку и CSS для нее. Стили используют те же цвета, радиус границы и градиент, что и в предыдущем уроке.

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

Поэтому, когда все содержимое страницы сдвигается вправо, кнопка также сдвигается в эту сторону:

.btn {
  float: left;
  margin: 1.5em 0 0 0;
  background: #999;
  padding: 0.25em 2%;
  color: #fff;
  cursor: pointer;
  border-radius: 0.25em;
  background-color: #5b5756;
  background-image: -webkit-linear-gradient(top, #6b6766, #5b5756);
  background-image:    -moz-linear-gradient(top, #6b6766, #5b5756);
  background-image:     -ms-linear-gradient(top, #6b6766, #5b5756);
  background-image:      -o-linear-gradient(top, #6b6766, #5b5756);
  background-image:         linear-gradient(top, #6b6766, #5b5756);
}

.btn:hover {
  background-color: #7b7776;
  background-image: -webkit-linear-gradient(top, #8b8786, #7b7776);
  background-image:    -moz-linear-gradient(top, #8b8786, #7b7776);
  background-image:     -ms-linear-gradient(top, #8b8786, #7b7776);
  background-image:      -o-linear-gradient(top, #8b8786, #7b7776);
  background-image:         linear-gradient(top, #8b8786, #7b7776);
Чекбокс нам нужен ради его функционала, но нам не нужно видеть его. Поэтому размещаем его далеко за пределами экрана.
	#toggle {
  position: absolute;
  left: -999em;
}

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

Когда меню становится видимым, нет необходимости в том, чтобы оно заполняло всю страницу по горизонтали. Установив ширину 75%, при выдвинутом меню мы сможем отображать только часть контента. Чтобы поместить меню обратно за пределы экрана, установим значение left равное -75%. И настроим переход, чтобы скольжение меню осуществлялось плавно.

Остальные строки CSS добавляют фон и отступы:

nav {
  position: fixed;
  left: -75%;
  width: 75%;
  height: 100%;
  padding: 5em 0 0 0;
  background: #3b3736;

  -webkit-transition: left 0.5s;
     -moz-transition: left 0.5s;
      -ms-transition: left 0.5s;
       -o-transition: left 0.5s;
          transition: left 0.5s;
}

Нам нужно, чтобы label «вел» себя как кнопка, поэтому мы устанавливаем значения для свойства cursor. Стоит обратить внимание на то, как стилизован символ «X» внутри закрывающего label. Для создания окружности вокруг «Х» я добавил границу и установил радиус границы 50%. А чтобы еще закруглить его, я настроил значения отступов для топа/низа и левого/правого краев на глаз.

При использовании другого шрифта потребуется подкорректировать значения отступов:

.close {
  cursor: pointer;
  color: #fff;
}

.close:hover {
  color: #999;
}

.close span {
  border: 2px solid #fff;
  border-radius: 50%;
  padding: 0.2em 0.4em;
}

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

В качестве фона для ссылок используется градиент, а их высота увеличена до 4em, чтобы расширить область для нажатия:

#nav {
  margin: 0.1875em 0 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid #777;
}

#nav a {
  text-decoration: none;
  color: #fff;
  padding: 1em 0 1em 5%;
  display: block;
  border-bottom: 1px solid #777;
  height: 4em;
  background-image: -webkit-linear-gradient(top, #4b4746, #3b3736);
  background-image:    -moz-linear-gradient(top, #4b4746, #3b3736);
  background-image:     -ms-linear-gradient(top, #4b4746, #3b3736);
  background-image:      -o-linear-gradient(top, #4b4746, #3b3736);
  background-image:         linear-gradient(top, #4b4746, #3b3736);
}

#nav a:hover {
  background: #4b4746;
  background-image: -webkit-linear-gradient(top, #5b5756, #4b4746);
  background-image:    -moz-linear-gradient(top, #5b5756, #4b4746);
  background-image:     -ms-linear-gradient(top, #5b5756, #4b4746);
  background-image:      -o-linear-gradient(top, #5b5756, #4b4746);
  background-image:         linear-gradient(top, #5b5756, #4b4746);
}

На первый взгляд CSS внешнего и внутреннего блоков не играют большой роли. У обоих установлена ширина 100% и у внешнего блока задан overflow: hidden. Это пригодится, когда в следующем разделе мы сдвинем содержимое вправо. Внутренний блок выровнен с помощью свойства float: right.

Также мы делаем переход, чтобы совместить его с элементом nav, находящимся выше:

.wrapper {
  width: 100%;
  overflow: hidden;
}

.inner {
  float: right;
  width: 100%;

  -webkit-transition: 0.5s;
     -moz-transition: 0.5s;
      -ms-transition: 0.5s;
       -o-transition: 0.5s;
          transition: 0.5s;
}
steven-rwd-nav-patterns-sidebar-nav-open-600.png

Шаг 3: CSS-стили для отображения навигационной панели

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

Для элемента nav свойство left установим 0. Только с помощью одного этого изменения меню будет выезжать в видимую часть окна, и заполнять 75% экрана (так как ширина установлена 75%). Теперь, когда нужно отображать кнопку закрытия меню, мы зафиксируем ее слева вверху:

:checked ~ nav {
  left: 0;
}

:checked ~ nav .close {
  position: fixed;
  top: 1.5em;
  left: 4%;
}

Для того чтобы сдвинуть контент вправо мы задаем свойство margin -75%. Важно, чтобы блок-контейнер имел свойство overflow: hidden. Если этого не сделать, то общая ширина страницы увеличится. С правой стороны контент отображаться не будет, но мы сможем прокручивать его влево и вправо, чтобы показывать и скрывать его.

Но нам это не нужно. А с помощью свойства overflow: hidden мы сможем скрыть ту часть контента, которая находится за пределами экрана:

:checked ~ .wrapper .inner {
  margin-right: -75%;
}
steven-rwd-nav-patterns-sidebar-nav-1200.png

Шаг 4: CSS-стили медиа-запросов

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

Мы скроем кнопку «Меню», так как она сейчас не нужна, а логотип переместим влево. Все элементы заголовка будут выровнены либо с помощью свойства float, либо с помощью свойства position, поэтому нам нужно предотвратить наезды элементов друг на друга.

Сделаем это с помощью отступов:

@media screen and (min-width: 48em) {
  header {
    padding-bottom: 5em;
  }

  .logo {
    float: left;
    margin: 1.25em 0;
  }

  .btn {
    display: none;
  }
}

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

@media screen and (min-width: 48em) {
  :checked ~ .wrapper .inner {
    margin-right: 0%;
    -webkit-transition: 0;
       -moz-transition: 0;
        -ms-transition: 0;
         -o-transition: 0;
            transition: 0;
  }
}

Чтобы сместить панель навигации мы установим свойство float: right. А также вернем свойство position в значение static, и сделаем фон прозрачным. Затем сбросим значения высоты, отступов и ширины, и выключим переходы.

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

@media screen and (min-width: 48em) {
  nav,
  :checked ~ nav {
    float: right;
    position: static;
    background: transparent;
    padding: 0;
    height: auto;
    width: 100%;
    -webkit-transition: 0;
       -moz-transition: 0;
        -ms-transition: 0;
         -o-transition: 0;
            transition: 0;
  }
}

Нам не нужно видеть кнопку закрытия меню, когда навигация открыта, поэтому для ее свойства display выставляем значение none. Имейте в виду, что это настраивается для состояний «отмечено» и «не отмечено»:

@media screen and (min-width: 48em) {
  nav .close,
  :checked ~ nav .close {
    display: none;
  }
}

Теперь мы изменим положение списка на горизонтальное. Используем абсолютное позиционирование, к элементам списка применяем свойство float, а свойству display задаем значение inline. В конце настроим отступы для ссылок, сбросим значение свойств border и background:

@media screen and (min-width: 48em) {
  #nav {
    position: absolute;
    top: 1.5em;
    right: 2%;
    border: 0;
  }

  #nav li {display: inline; float: left;}
  #nav li.current a {color: #7b7776;}

  #nav a {
    padding: 0 1.5em;
    display: inline;
    border: 0;
    background: transparent;
  }

  #nav a:hover {background: transparent;}

  #sidebar {
    margin-top: 5.5em;
  }
}

Шаг 5: Исправления для iOS и Android

Элемент чекбокс имеет некоторые особенности при работе на iOS ниже шестой версии и Android ниже версии 4.1.2.

Исправление для iOS касается события onlclick для label, присоединенного к чекбоксу. Если вы вернетесь к началу статьи, то увидите пустое событие onclick в html-разметке в начале описания этого шаблона. Исправление для Android касается анимации элемента body:

body {
  -webkit-animation: bugfix infinite 1s;
}

@-webkit-keyframes bugfix { 
  from {padding:0;} 
  to {padding:0;} 
}

На этом мы заканчиваем разработку первого шаблона закадрового меню.

Мысли

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

Работа шаблона основана на событии нажатия кнопки мыши и хаке чекбокса. В зависимости от состояния чекбокса свойства left, right, margin-left, или margin-right могут быть настроены так, как вам необходимо. В нашем случае меню занимает 75% от видимой части экрана, но может быть легко настроено на значения 100%, 50% и другое.

Мы устанавливаем свойство overflow:hidden блока-контейнера, чтобы быть уверенным в том, что внутренний блок полностью скрыт и не может быть прокручен вне экрана.

Шаблон навигации в боковой панели с использованием Javascript

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

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

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

Шаг 1: HTML

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

<nav>
  <a class="close"><span>X</span> Закрыть</a>
  <ul id="nav">
    <li><a href="">Назад к публикациям</a></li>
    <li><a href="sidebar-nav.html">Навигация в сайдбаре</a></li>
    <li class="current"><a href="sidebar-nav-js.html"> Навигация в сайдбаре на JS</a></li>
    <li><a href="sidebar+.html">Сайдбар+</a></li>
    <li><a href="panels.html">Панели</a></li>
  </ul>
</nav>

<div class="wrapper">
  <div class="inner">
    <header>
      <a class="btn">Меню</a>
    </header>

    <div class="container main-content">
      <div id="content"></div>
      <div id="sidebar"></div>
    </div>

    <section class="subfooter"></section>
    <div id="footer"></div>
  </div>
</div>

Шаг 2: CSS-стили по умолчанию

Здесь без изменений:

steven-rwd-nav-patterns-js-sidebar-nav-open-600.png

Шаг 3: CSS для открытого меню

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

Мы будем добавлять и удалять класс .open у элемента nav. В предыдущей версии шаблона нам приходилось использовать дочерний псевдо-селектор :checked элемента nav. И снова мы будем применять его, но уже к блоку .inner (DIV) как к элементу nav, а к классу слоя .wrapper как дочерний элемент:

nav.open {
  left: 0;
}

nav.open .close {
  position: fixed;
  top: 1.5em;
  left: 4%;
  display: block;
}

.open ~ .wrapper .inner {
  margin-right: -75%;
}

Свойства и их значения не меняются.

Шаг 4: CSS- стили для медиа - запросов

Элемент :checked ~ nav заменяется на класс nav.open, а :checked ~ .wrapper .inner заменяется на .open ~ .wrapper .inner. Как в предыдущей секции.

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

Шаг 5: JavaScript (jQuery)

Начнем с перехватывания события нажатия кнопки классом .btn. Нам нужно добавлять и удалять класс для элемента nav. Кнопка (a.btn) находится внутри заголовка, который расположен внутри блока .inner, а он находится внутри контейнера wrapper, который является дочерним по отношению к элементу nav.

Чтобы добраться от кнопки до блока wrapper мы будем использовать функцию jQuery parents(), которая осуществляет поиск всех ближайших предков указанных элементов. И с этого момента мы сможем начать использовать элемент nav.

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

$(document).ready(function() {
  $('a.btn').click(function() {
    if($(this).parents('.wrapper').siblings('nav').hasClass('open')){
      $(this).parents('.wrapper').siblings('nav').removeClass('open');
    } else {
      $(this).parents('.wrapper').siblings('nav').addClass('open');
    }
    return false;
  });

  $('a.close').click(function() {
    if($(this).parent('nav').hasClass('open')){
      $(this).parent('nav').removeClass('open');
    }
    return false;
  });
});

Кнопка «Закрыть» расположена внутри элемента nav. Здесь нам потребуется функция parent(). Кнопка «Закрыть» отображается только в случае наличия класса .open в элементе nav, поэтому нам не нужно его добавлять.

Мысли

Мы убрали чекбокс и заменили label ссылками. В CSS везде, где ранее был :checked ~ nav, сейчас мы используем nav.open, а :checked ~ .wrapper .inner мы заменили на .open ~ .wrapper .inner.

Новый код – функция jQuery для добавления и удаления класса (эквивалент установки и снятия флажка с чекбокса). Затем мы отслеживаем нажатия кнопки мыши и с помощью jQuery функций определяем, какой элемент nav мы хотим модифицировать.
Какая именно версия из двух представленных вам больше подходит, решать вам.

Версия с чекбоксом требует пары поправок, для iOS и Android систем, и не будет работать в старых версиях IE. Версия с использованием JQuery более стабильна и предпочтительна для использования.

Шаблон «Панели»

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

Введение: На маленьких экранах будет отображаться только одна панель с контентом, которая по умолчанию будет видна. В заголовке мы создадим три кнопки, по одной на каждую панель. Для отслеживания нажатия кнопки мыши будем использовать хак, похожий на хак чекбокса (только для radio buttons).

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

Шаг 1: HTML

В html – разметке я внес несколько изменений. В этом шаблоне элемент nav находится внутри блоков .wrapper и .inner. Это позволит нам перемещать все три панели сразу, изменяя их родительский блок .inner.

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

Внутри заголовка у нас есть div, который содержит три label, каждый из которых предназначен для своей панели. Им присвоен класс .btn, который мы использовали ранее, хотя у каждого из них есть и свой собственный класс. Обратите внимание, что каждый label связан с отдельным переключателем или radio buttons. Три входных переключателя находятся вне заголовка. У каждого из них имя - "panel", и каждому присвоен уникальный id.

Так как переключатели расположены вне заголовка, они могут быть дочерними по отношению к .wrapper:

<header>
  <div id="panel-nav">
    <label class="btn btn-1" for="toggle-1" onclick>Меню </label>
    <label class="btn btn-2" for="toggle-2" onclick>Содержимое </label>
    <label class="btn btn-3" for="toggle-3" onclick>Еще ... </label>
  </div>
</header>

<input id="toggle-1" name="panel" type="radio" />
<input id="toggle-2" name="panel" type="radio" />
<input id="toggle-3" name="panel" type="radio" />

<div class="wrapper">
  <div class="inner">

    <nav>
      <ul id="nav">
        <li><a href="">Назад </a></li>
        <li><a href="sidebar-nav.html">Панель навигации </a></li>
        <li><a href="sidebar-nav-js.html">Панель навигации JS </a></li>
        <li class="current><a href="panels.html"> Панели </a></li>
        <li"><a href="sidebar+.html">Сайдбар + </a></li>
      </ul>
    </nav>

    <div class="container main-content">
      <div id="content"></div>
    </div>

    <div id="sidebar"></div>
  </div>
</div>

<section class="subfooter"></section>
<div id="footer"></div>
steven-rwd-nav-patterns-panels-content-600

Шаг 2: CSS – стили по умолчанию

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

Нам нужно скрыть входные radio buttons, и сделаем мы это точно так же, как и в предыдущем шаблоне:

#toggle-1, #toggle-2, #toggle-3 {
  position: absolute;
  left: -999em;
}

Так как мы поместили все три панели внутри одного контейнера, то теперь их нужно позиционировать. Сделаем это с помощью свойства float: left. И каждой панели выделим 1/3 от всей ширины контейнера.

nav {
  float: left;
  padding: 0;
  background: #3b3736;
  width: 33.334%
}

.main-content {
  float: left;
  width: 33.333%
}

#sidebar {
  float: left;
  padding: 0 2%;
  width: 33.333%
}

Почему 33% от всей ширины. Мы задаем блоку-контейнеру 100%, а в случае переполнения любого из элементов внутри скрываем его. Для блока .inner задаем ширину 300% (1/3 которого равно 100%) и по умолчанию задаем отступ от левого края -100%.

После того, как установлено свойство overflow: hidden, только 1/3 от ширины слоя .inner будет отображаться на экране (ширина любой из трех панелей).

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

.wrapper {
  width: 100%;
  overflow: hidden;
}

.inner {
  width: 300%;
  margin-left: -100%;

  -webkit-transition: margin 0.5s;
     -moz-transition: margin 0.5s;
      -ms-transition: margin 0.5s;
       -o-transition: margin 0.5s;
          transition: margin 0.5s;
}

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

steven-rwd-nav-patterns-panels-menu-600.png

Шаг 3: CSS-стили для переключения панелей

Чтобы сменить панель на экране, нам достаточно настроить левый край блока .inner. Нам нужно реализовать доступ к блоку .inner, основанный на состоянии radio button, поэтому мы к каждому слою присоединили свою кнопку:

steven-rwd-nav-patterns-panels-sidebar-600.png

#toggle-1 – для меню, #toggle-2 – для основного содержимого, а #toggle-3 – для сайдбара. Все панели были выровнены с помощью свойства float: left, свойство margin-left равное 0 отобразит первую панель меню. Значение -100% для свойства margin - left уберет меню с экрана и выведет контент.

А значение -200% отобразит сайдбар:

#toggle-1:checked ~ .wrapper .inner {
  margin-left: 0%;
}

#toggle-2:checked ~ .wrapper .inner {
  margin-left: -100%;
}

#toggle-3:checked ~ .wrapper .inner {
  margin-left: -200%;
}
steven-rwd-nav-patterns-panels-menu-768

Шаг 4: CSS для медиа-запросов

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

Так как при этой ширине страницы панель контента будет отображена постоянно - переключатель мы можем убрать. И тут же перенесем две оставшиеся кнопки вверх и вправо.

Я также скорректировал позицию логотипа и добавил отступы в заголовке:

@media screen and (min-width: 48em) {
  #panel-nav {
    float: right;
    margin: 1.75em 3.25% 0 0;
  }

  .btn {
    padding: 0.45em 0.9em;
    margin-left: 0.1em;
  }

  .btn-2 {
    display: none;
  }
}
steven-rwd-nav-patterns-panels-sidebar-768

Нам нужно изменить номера, чтобы показывать больше, чем одну панель в данный момент времени. К примеру, нам нужно чтобы ширина блока .inner была более 100%, но чтобы часть ее была скрыта. Далее нам нужно отобразить 2/3 её части, а не 1/3, как было в предыдущем шаге.

Слой .inner займет 3/2 ширины блока .wrapper, поэтому устанавливаем ширину блока .inner 150%. При меньшей ширине страницы нам была нужна 1/3 от общей ширины слоя .inner, сейчас - 2/3. Поэтому, чтобы две панели отображались одновременно, в сумме их ширина должна быть 67%.

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

Так как градиент фона меню нам не нужен, то делаем его прозрачным. Также сайдбару установим верхний отступ от края (margin-top).

Управление над тем, какая из панелей отображена в данный момент, лежит на радио кнопках. Теперь нам нужно только два их состояния. Если кнопка меню (или скрытая сейчас кнопка контента) нажата, то левый отступ у блока .inner будет равен 0.

Установив отступ -37%, мы отобразим панель с основным контентом и сайдбар:

@media screen and (min-width: 48em) {
  .inner {
    width: 150%;
    margin-left: 0;
  }

  nav {
    width: 25%;
    background: none;
  }

  .main-content {
    width: 40%;
  }

  #sidebar {
    width: 25%;
    margin-top: 3em;
  }

  #toggle-1:checked ~ .wrapper .inner {
    margin-left: 0%;
  }

  #toggle-2:checked ~ .wrapper .inner {
    margin-left: 0%;
  }

  #toggle-3:checked ~ .wrapper .inner {
    margin-left: -37%;
  }
}

Основным минусом использования группы кнопок-переключателей заключается в том, что одна из них обязательно должна быть выбрана. Это значит, что если одна из кнопок выбрана для отображения сайдбара, то у нас есть только один способ снова отобразить меню – «нажать» еще одну кнопку. Но нажатие кнопки «More» снова ни к чему не приведет.

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

steven-rwd-nav-patterns-panels-1200.png

При ширине страницы 75em мы можем отобразить одновременно все три панели. В этом случае нам не нужны кнопки и мы их скрываем.

Теперь нам нужно установить ширину блока .inner 100%. Больше ничего не нужно скрывать. Переходы мы также выключим.

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

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

@media screen and (min-width: 75em) {
  .btn {display: none;}

  .inner {
    width: 100%;

    -webkit-transition: 0;
       -moz-transition: 0;
        -ms-transition: 0;
         -o-transition: 0;
            transition: 0;
    }

  nav {
    width: 20%;
  }

  .main-content {
    width: 53%;
    padding: 0 2% 0 0;
  }

  #sidebar {
    width: 23%;
    padding: 0 1%;
  }

  #toggle-3:checked ~ .wrapper .inner {
    margin-left: 0%;
  }
}

@media screen and (min-width: 80em) {
  .logo {margin-left: -1.4%}
}

Мысли

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

Если вы открывали страницу с демо–режимом на экране шириной менее 48em, то могли заметить, что при отображении меню или сайдбара, остается много свободного пространства над подвалом.

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

Еще одно отличие данного шаблона заключается в том, что вместо кнопок-переключателей вы можете использовать код Javascript. Вместо селекторов :checked вы можете добавлять и удалять классы любой панели тем же способом, что мы использовали в предыдущем шаблоне. В последнем шаблоне мы снова будем использовать jQuery, чтобы работа панелей не зависела друг от друга.

Шаблон Сайдбар+

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

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

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

Шаг 1: HTML

Разметка идентична предыдущему шаблону. Снова все три панели включаем в блоки .wrapper и .inner. Так как теперь мы используем Javascript, то радио-кнопки мы поменяем на ссылки и label.

Нам нужно всего две кнопки вместо трех, поэтому удаляем одну лишнюю, а две оставшихся перемещаем в заголовок к логотипу:

<header>
  <div class="container">
    <a class="btn btn-1">Меню </a>
    <img class="logo" src="images/logo.png" width="252" height="46" />
    <a class="btn btn-2">Еще ... </a>
  </div>
</header>

<div class="wrapper">
  <div class="inner">

    <nav>
      <ul id="nav">
        <li><a href="">Назад </a></li>
        <li><a href="sidebar-nav.html">Сайдбар - навигация </a></li>
        <li><a href="sidebar-nav-js.html">Сайдбар - навигация JS </a></li>
        <li class="current"><a href="sidebar+.html">Сайдбар + </a></li>
        <li><a href="panels.html">Панели </a></li>
      </ul>
    </nav>

    <div class="container main-content">
      <div id="content"></div>
    </div>

    <div id="sidebar"></div>
  </div>
</div>

<section class="subfooter"></section>
<div id="footer"></div>
steven-rwd-nav-patterns-plus-sidebar-content-600.png

Шаг 2: CSS-стили

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

.btn-1 {
    position: absolute;
    top: 1.5em;
    left: 5%;
}

.btn-2 {
    position: absolute;
    top: 1.5em;
    right: 5%;
}

Так как CSS – стили одинаковы, для переключения панелей будем использовать тот же метод слайда. Ширину блока .wrapper ставим в 100% и устанавливаем свойство overflow: hidden. Ширину блока .inner устанавливаем на 300% , а отступ от левого края (margin-left) - 100%.

Ширину панелей внутри блоков делаем равной 1/3 от общей ширины слоя .inner:

.wrapper {
    width: 100%;
    overflow: hidden;
}

.inner {
    width: 300%;
    margin-left: -100%;

    -webkit-transition: margin 0.5s;
       -moz-transition: margin 0.5s;
        -ms-transition: margin 0.5s;
         -o-transition: margin 0.5s;
            transition: margin 0.5s;
}
steven-rwd-nav-patterns-plus-sidebar-menu-600.png

Шаг 3: CSS-стили переключения меню и сайдбара

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

steven-rwd-nav-patterns-plus-sidebar-sidebar-600.png

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

.inner.menu {
  margin-left: 0;
}

.inner.more {
  margin-left: -200%;   
}
patterns-plus-sidebar-menu-768

Шаг 4: CSS-стили для медиа-запросов

И снова мы повторяем стили из шаблона панелей. При ширине в 48em будет отображаться меню и панель основного контента. Мы меняем лишь #toggle-1:checked ~ .wrapper .inner на .inner.menu и #toggle-3:checked ~ .wrapper .inner на .inner.more. Значения ширины и отступов остаются прежними:

@media screen and (min-width: 48em) {
  nav {
    width: 25%;
    background: none;
  }

  .inner {
    width: 150%;
    margin-left: 0;
  }

  .main-content {
    width: 40%;
  }

  .container {
    padding: 0 2%;
  }

  #content {
    width: 100%;
  }

  #sidebar {
    width: 25%;
    margin-top: 3em;
  }

  .inner,
  .inner.menu {
    margin-left: 0%;
  }

  .inner.more {
    margin-left: -37%;
  }
}
steven-rwd-nav-patterns-plus-sidebar-sidebar-768.png

При ширине страницы в 75em мы отобразим все три столбца и уберем кнопки. Стили остаются почти неизменными. Только лишь селектор :checked меняется на класс.

При ширине страницы от 48em до 75em мы отображаем меню и контент с выключенным сайдбаром. Мы можем убрать кнопку "Меню", оставить кнопку "Еще..." и «повесить» на нее открытие и закрытие сайдбара.

Но я решил оставить кнопку "Меню", которая будет работать при видимом сайдбаре.

Хотя это может привести к путанице при состоянии страницы по умолчанию, так как может заставить посетителей думать, что нажав на кнопку, они включают дополнительное меню. Компромисс заключается в том, что если кто-то просматривает страницу при ширине менее 48em с открытой боковой панелью, а затем увеличивает ширину окна более чем на 48em, то будет меньше путаницы в том, как вернуть меню назад.

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

steven-rwd-nav-patterns-plus-sidebar-1200

Шаг 5: JavaScript

Мы снова будем перехватывать нажатие кнопки и использовать модель DOM, чтобы добавить или удалить класс у блока .inner. С помощью обеих кнопок нам нужно сдвинуть пару контейнеров к заголовку, поэтому мы будем использовать функцию parents(). От блока .wrapper, который является дочерним блоку .inner.

Блок .inner находится внутри блока .wrapper, и найти его мы сможем с помощью функции find().

Кнопки управляют различными панелями, поэтому мы будем добавлять и удалять различные классы. Кнопка .btn-1 связана с меню. Если класс меню присутствует в блоке .inner, мы удаляем его. Если класса нет - добавляем. Но существует вероятность, что класс .more присутствует в тот момент, когда класса .menu нет, поэтому класс .menu также будем удалять.

Для кнопки .btn-2 делаем все то же самое, только меняем классы местами:

$(document).ready(function() {
  $('a.btn-1').click(function() {
    if($(this).parents('header').siblings('.wrapper').find('.inner').hasClass('menu')){
      $(this).parents('header').siblings('.wrapper').find('.inner').removeClass('menu');
    } else {
      $(this).parents('header').siblings('.wrapper').find('.inner').addClass('menu');
      $(this).parents('header').siblings('.wrapper').find('.inner').removeClass('more');
    }
    return false;
  });

  $('a.btn-2').click(function() {
    if($(this).parents('header').siblings('.wrapper').find('.inner').hasClass('more')){
      $(this).parents('header').siblings('.wrapper').find('.inner').removeClass('more');
    } else {
      $(this).parents('header').siblings('.wrapper').find('.inner').addClass('more');
      $(this).parents('header').siblings('.wrapper').find('.inner').removeClass('menu');
    }
    return false;
  });
});

Мысли

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

Этот шаблон не предназначен для работы с множеством панелей. Он будет работать лучше всего, когда у вас есть только один «кусок» контента. Вы можете нажать кнопку, которая будет «заставлять» панели выезжать из-за пределов экрана.

Заключение

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

В принципах работы шаблоны очень схожи друг с другом. Спрятанный контент обычно помещается за пределы экрана с помощью отступов. Когда содержимое страницы стоит на первоначальной позиции, значения левых и правых отступов (верхних или нижних) могут быть заданы так, чтобы убрать контент за пределы страницы. А нажатие различных кнопок задает значение отступов для состояний «вне экрана» и «в пределах экрана».

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

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

Мы изучили три различных техники обработки события click. Используя CSS псевдо-селекторы, хак :target , хак :checkbox и хак радио-кнопки. Также мы применяли jQuery, чтобы добавлять и удалять классы, которые отвечают за различные состояния элементов страницы.

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

Скачать рабочие материалы
Посмотреть демо

Перевод статьи «Examining Responsive Navigation: Off Canvas Patterns» был подготовлен дружной командой проекта Сайтостроение от А до Я.

31 июля 2015 в 12:56
Материалы по теме
{"url":"http://www.fastvps.ru/", "src":"/images/advbanners/fastvps.png", "alt":"Хостинг Fastvps.ru. Наш выбор!"}
Заработок