Создаем адаптивный CSS-шаблон с плавными переходами

На этом уроке мы будем создавать адаптивный CSS-макет с 100% шириной и высотой  и с плавными переходами страниц. Идея состоит в создании секций с содержанием и навигации, которая позволит переключаться между этими секциями. Мы будем использовать радио-кнопки для навигации и создавать анимацию для содержания, создавая эффект "плавной прокрутки". Эта идея может быть полезна для веб-страниц или веб-приложения, где содержание должно строго соответствовать размеру экрана (ширина и высота).

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

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

Разметка

Структура макета будет состоять из основного контейнера с классом st-container, который будет содержать радио-кнопки и ссылки, а блок с классом st-scroll, который будет содержать секции с контентом:

{geshi lang="xml"}
<div class="st-container">

<input type="radio" name="radio-set" checked="checked" id="st-control-1"/>
<a href="#st-panel-1">Serendipity</a>

<input type="radio" name="radio-set" id="st-control-2"/>
<a href="#st-panel-2">Happiness</a>

<input type="radio" name="radio-set" id="st-control-3"/>
<a href="#st-panel-3">Tranquillity</a>

<input type="radio" name="radio-set" id="st-control-4"/>
<a href="#st-panel-4">Positivity</a>

<input type="radio" name="radio-set" id="st-control-5"/>
<a href="#st-panel-5">Passion</a>

<div class="st-scroll">

<section class="st-panel" id="st-panel-1">
<div class="st-deco" data-icon="H"></div>
<h2>Serendipity</h2>
<p>Banksy adipisicing eiusmod banh mi sed...</p>
</section>

<section class="st-panel st-color" id="st-panel-2">
<!-- ... -->
</section>

<!-- ... st-panel-3, st-panel-4, st-panel-5 -->

</div><!-- // st-scroll -->

</div><!-- // st-container --> {/geshi}

Итак, что мы хотим сделать: переместить блок-оболочку, изменяя его значение top и показывая соответствующую секцию в окне просмотра. Это можно сделать выбрав соответствующую радио-кнопку, которая ссылается на соответствующую секцию в блоке с классом st-scroll.

Причина, по которой мы используем ссылки, а не как обычно лэйблы (тег label), является то, что мы хотим иметь возможность создать своего рода "fallback" для старых браузеров (родственные комбинаторы (sibling combinators) не работают в старых браузерах). Ссылки имеют аттрибут href с идентификатором соответствующий секции, таким образом мы просто скрываем радио-кнопки, делая ссылки кликабельными.

Теперь давайте перейдем к стилям!

CSS

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

Так как мы будем создавать навигацию по контенту с помощью анимации секции-оболочки, то мы установим для body свойство overflow:hidden:

{geshi lang="css"}
body {
overflow: hidden;
}{/geshi}

Давайте посмотрим на стили основного контейнера:

{geshi lang="css"}
.st-container {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
font-family: 'Josefin Slab', 'Myriad Pro', Arial, sans-serif;
}{/geshi}

Мы поместим "навигацию" в нижнюю часть страницы, задав ей фиксированное положение (position: fixed). Обратите внимание, что мы устанавливаем одинаковую ширину и высоту для радио-кнопок и ссылок. Идея состоит в том, чтобы наложить радио-кнопки на ссылки, чтобы они были кликабельными, но задаем им прозрачность равную 0, чтобы они не были видны. Также важно то, что мы устанавливаем z-index для радио-кнопок больше, чем для ссылок:

{geshi lang="css"}
.st-container > input,
.st-container > a {
position: fixed;
bottom: 0px;
width: 20%;
cursor: pointer;
font-size: 16px;
height: 34px;
line-height: 34px;
}

.st-container > input {
opacity: 0;
z-index: 1000;
}

.st-container > a {
z-index: 10;
font-weight: 700;
background: #e23a6e;
color: #fff;
text-align: center;
text-shadow: 1px 1px 1px rgba(151,24,64,0.2);
}{/geshi}

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

{geshi lang="css"}
.st-container:before {
content: '';
position: fixed;
width: 100%;
height: 34px;
background: #e23a6e;
z-index: 9;
bottom: 0;
}{/geshi}

Наши ссылки и радио-кнопки все еще не расположены как нужно, так что давайте зададим им соответствующия значения для свойства left:

{geshi lang="css"}
#st-control-1, #st-control-1 + a {
left: 0;
}

#st-control-2, #st-control-2 + a {
left: 20%;
}

#st-control-3, #st-control-3 + a {
left: 40%;
}

#st-control-4, #st-control-4 + a {
left: 60%;
}

#st-control-5, #st-control-5 + a {
left: 80%;
}{/geshi}

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

{geshi lang="css"}
.st-container > input:checked + a,
.st-container > input:checked:hover + a{
background: #821134;
}{/geshi}

Давайте также добавим маленький треугольник с помощью псевдо-класса :after, и зададим ему тот же цвет:

{geshi lang="css"}
.st-container > input:checked + a:after,
.st-container > input:checked:hover + a:after{
bottom: 100%;
border: solid transparent;
content: '';
height: 0;
width: 0;
position: absolute;
pointer-events: none;
border-bottom-color: #821134;
border-width: 20px;
left: 50%;
margin-left: -20px;
}{/geshi}

Вы можете также использовать CSS Arrow, Please!, если вы хотите быстро создавать подобные стрелки.

Давайте также определим стили при наведении на ссылку:

{geshi lang="css"}
.st-container > input:hover + a{
background: #AD244F;
}

.st-container > input:hover + a:after {
border-bottom-color: #AD244F;
}{/geshi}

Оболочка для секций и секции будут иметь относительное позиционирование, и мы зададим им ширину и высоту 100%. Для оболочки также зададим top и left равные 0.

Transitions будет анимировать значение свойства transform для соответствующей позиции:

{geshi lang="css"}
.st-scroll,
.st-panel {
position: relative;
width: 100%;
height: 100%;
}

.st-scroll {
top: 0;
left: 0;
transition: all 0.6s ease-in-out;

/* Let's enforce some hardware acceleration */
-webkit-transform: translate3d(0, 0, 0);
-webkit-backface-visibility: hidden;
}

.st-panel{
background: #fff;
overflow: hidden;
}{/geshi}

Хотя я обычно не добавляю префикс браузера к свойствам, я оставил эти Webkit-префиксы, т.к. они помогут в создании сглаживания.

Давайте определим позиции для каждой выбранной радио-кнопки для оболочки st-scroll. Так как мы знаем, что каждая секция имеет высоту 100%, мы знаем её точное положение. Мы будем использовать свойство transform, чтобы переместить секцию-обертку по Y-измерению (вверх и вниз):

{geshi lang="css"}
#st-control-1:checked ~ .st-scroll {
transform: translateY(0%);
}
#st-control-2:checked ~ .st-scroll {
transform: translateY(-100%);
}
#st-control-3:checked ~ .st-scroll {
transform: translateY(-200%);
}
#st-control-4:checked ~ .st-scroll {
transform: translateY(-300%);
}
#st-control-5:checked ~ .st-scroll {
transform: translateY(-400%);
}{/geshi}

Теперь давайте зададим стили для содержания. Для верхнего треугольника с иконой, мы просто повернем блок с классом st-deco. Мы разместим его в центре верхней части экрана, установив top:0, и left:50%, и придав ему отрицательный левый отступ равный половине его ширины. translateY(-50%) позволит видеть только половину блока, таким образом создавая треугольник:

{geshi lang="css"}
.st-deco{
width: 200px;
height: 200px;
position: absolute;
top: 0px;
left: 50%;
margin-left: -100px;
background: #fa96b5;
transform: translateY(-50%) rotate(45deg);
}{/geshi}

Для иконки мы будем использовать шрифт Raphaël Icon-Set via @font-face и data-attribute/pseudo-class технику. Псевдо-элемент :after будет вставлять иконку в HTML-код для этого элемента. Обратите внимание, что нам нужно повернуть её обратно в противоположном направлении от родительского элемента, чтобы видеть её в "нормальном" положении:

{geshi lang="css"}
[data-icon]:after {
content: attr(data-icon);
font-family: 'RaphaelIcons';
color: #fff;
text-shadow: 1px 1px 1px rgba(151,24,64,0.2);
position: absolute;
width: 200px;
height: 200px;
line-height: 200px;
text-align: center;
font-size: 90px;
top: 50%;
left: 50%;
margin: -100px 0 0 -100px;
transform: rotate(-45deg) translateY(25%);
}{/geshi}

Заголовок будет размещен в центре экрана с отрицательным верхним отступом:

{geshi lang="css"}
.st-panel h2 {
color: #e23a6e;
text-shadow: 1px 1px 1px rgba(151,24,64,0.2);
position: absolute;
font-size: 54px;
font-weight: 900;
width: 80%;
left: 10%;
text-align: center;
line-height: 50px;
margin: -70px 0 0 0;
padding: 0;
top: 50%;
-webkit-backface-visibility: hidden;
}{/geshi}

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

{geshi lang="css"}
#st-control-1:checked ~ .st-scroll #st-panel-1 h2,
#st-control-2:checked ~ .st-scroll #st-panel-2 h2,
#st-control-3:checked ~ .st-scroll #st-panel-3 h2,
#st-control-4:checked ~ .st-scroll #st-panel-4 h2,
#st-control-5:checked ~ .st-scroll #st-panel-5 h2{
animation: moveDown 0.6s ease-in-out 0.2s backwards;
}

@keyframes moveDown{
0% {
transform: translateY(-40px);
opacity: 0;
}
100% {
transform: translateY(0px);
opacity: 1;
}
}{/geshi}

Параграфы будут иметь следующие стили:

{geshi lang="css"}
.st-panel p {
position: absolute;
text-align: center;
font-size: 16px;
line-height: 22px;
color: #8b8b8b;
z-index: 2;
padding: 0;
width: 50%;
left: 25%;
top: 50%;
margin: 10px 0 0 0;
-webkit-backface-visibility: hidden;
}{/geshi}

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

{geshi lang="css"}
#st-control-1:checked ~ .st-scroll #st-panel-1 p,
#st-control-2:checked ~ .st-scroll #st-panel-2 p,
#st-control-3:checked ~ .st-scroll #st-panel-3 p,
#st-control-4:checked ~ .st-scroll #st-panel-4 p,
#st-control-5:checked ~ .st-scroll #st-panel-5 p{
animation: moveUp 0.6s ease-in-out 0.2s backwards;
}

@keyframes moveUp{
0% {
transform: translateY(40px);
opacity: 0;
}
100% {
transform: translateY(0px);
opacity: 1;
}
}{/geshi}

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

{geshi lang="css"}
/* Colored sections */

.st-color,
.st-deco{
background: #fa96b5;
}
.st-color [data-icon]:after {
color: #fa96b5;
}
.st-color .st-deco {
background: #fff;
}
.st-color h2 {
color: #fff;
text-shadow: 1px 1px 1px rgba(0,0,0,0.1);
}
.st-color p {
color: rgba(255,255,255,0.8);
}{/geshi}

И последнее, но не менее важное, мы добавим некоторые media queries для контроля положения и размера шрифта элементов для небольших экранов:

{geshi lang="css"}
@media screen and (max-width: 520px) {
.st-panel h2 {
font-size: 42px;
}

.st-panel p {
width: 90%;
left: 5%;
margin-top: 0;
}

.st-container > a {
font-size: 13px;
}
}

@media screen and (max-width: 360px) {
.st-container > a {
font-size: 10px;
}

.st-deco{
width: 120px;
height: 120px;
margin-left: -60px;
}

[data-icon]:after {
font-size: 60px;
transform: rotate(-45deg) translateY(15%);
}
}{/geshi}

Для старых браузеров, которые не поддерживают некоторые селекторы мы хотим вернуться к классическому "target jump". Мы можем сделать это изменив некоторые стили (simple.css). В частности, мы установим свойство overflow для body равное "auto" и спрячем радио-кнопки, делая ссылки кликабельными (в аттрибуте href они имеют ID соответствующей панели):

{geshi lang="css"}
body {
overflow: auto;
}
.st-container > input{
display: none;
}{/geshi}

И это все! Я надеюсь, вам понравился этот урок!

Демонстрация

Скачать исходные файлы

Перевод статьи с http://tympanus.net/codrops