Адаптивная вёрстка, урок третий. Сетка из блоков
В этом уроке мы рассмотрим создание макета страницы портфолио на основе плиточной сетки. Для создания сетки используются библиотеки Masonry и imagesLoaded Dave DeSandro. Изображения, представленные в демо-версии, взяты с сайта Unsplash.com.
Masonry представляет собой сетку, базирующуюся на колонках. В отличие от сетки, созданной с помощью обтекания float, Masonry-сетка не имеет фиксированной высоты строк, что обеспечивает оптимальное использование пространства внутри веб-страницы, уменьшая любые ненужные пробелы. Такая сетка будет уместна на страницах-портфолио, страницах с галереями изображений, а также страницах с записями блога.
1. Метатеги и раздел <head>
1) Раздел <head> должен содержать ссылки на необходимые файлы — используемые шрифты и таблицу стилей.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Галерея Masonry</title>
<link href="https://fonts.googleapis.com/css?family=Muli:400,600,700|Radley" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" rel="stylesheet">
<link href="style.css" rel="stylesheet">
</head>
<body>
2. Шапка страницы
Шапка страницы — раздел <header> содержит следующие элементы-контейнеры:
- логотип <div class="logo">;
- главное меню <ul id="menu">;
- кнопку для показа/скрытия главного меню <div class="burger">.
<header>
<div class="container">
<div class="header-row">
<div class="logo">
<a href="">
<span class="logo-name">Helen Parker</span>
<span class="logo-description">
<span>personal photographer</span>
</span>
</a>
</div>
<ul id="menu">
<li>
<a href="">Blog</a>
</li>
<li class="current">
<a href="">Portfolio</a>
</li>
<li>
<a href="">About</a>
</li>
</ul>
<div class="burger">
<span></span>
</div>
</div>
</div>
</header>
3. Сетка с фотографиями
Основная часть страницы состоит из блоков с фотографиями, для которых задан фильтр grayscale, придающий им эффект черно-белых фотографий. При наведении этот эффект исчезает.
<div class="main">
<div class="container">
<div class="row">
<div class="grid">
<div class="grid-item">
<a class="grid-link" href="">
<img class="grid-img" src="images/image-1.jpg" alt=""/>
</a>
</div>
<div class="grid-item">
<a class="grid-link" href="">
<img class="grid-img" src="images/image-2.jpg" alt=""/>
</a>
</div>
<div class="grid-item">
<a class="grid-link" href="">
<img class="grid-img" src="images/image-3.jpg" alt=""/>
</a>
</div>
<div class="grid-item">
<a class="grid-link" href="">
<img class="grid-img" src="images/image-4.jpg" alt=""/>
</a>
</div>
<div class="grid-item">
<a class="grid-link" href="">
<img class="grid-img" src="images/image-5.jpg" alt=""/>
</a>
</div>
<div class="grid-item">
<a class="grid-link" href="">
<img class="grid-img" src="images/image-6.jpg" alt=""/>
</a>
</div>
<div class="grid-item">
<a class="grid-link" href="">
<img class="grid-img" src="images/image-7.jpg" alt=""/>
</a>
</div>
<div class="grid-item">
<a class="grid-link" href="">
<img class="grid-img" src="images/image-8.jpg" alt=""/>
</a>
</div>
<div class="grid-item">
<a class="grid-link" href="">
<img class="grid-img" src="images/image-9.jpg" alt=""/>
</a>
</div>
<div class="grid-item">
<a class="grid-link" href="">
<img class="grid-img" src="images/image-10.jpg" alt=""/>
</a>
</div>
</div>
</div>
</div>
</div>
4. Подвал сайта
Нижний колонтитул содержит сведения о копирайте и ссылки на социальные сети.
<footer>
<div class="container">
<div class="footer-row">
<div class="footer-col">
<p>Copyright © 2020 Helen Parker</p>
</div>
<div class="footer-col">
<div class="social-icons-wrapper">
<a class="social-icon" target="_blank" href=""><i class="fa fa-facebook"></i></a>
<a class="social-icon" target="_blank" href=""><i class="fa fa-twitter"></i></a>
<a class="social-icon" target="_blank" href=""><i class="fa fa-google-plus"></i></a>
</div>
</div>
</div>
</div>
</footer>
5. Файл style.css
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
body {
font-family: 'Muli', sans-serif;
font-size: 14px;
line-height: 1.5;
color: #19121e;
background-color: white;
}
ul {
list-style: none;
}
a {
text-decoration: none;
outline: none;
}
.container {
width: 100%;
max-width: 1120px;
padding: 0 10px;
margin: 0 auto;
}
.row {
margin: 0 -10px;
}
/*************************************************************/
/* HEADER */
/*************************************************************/
header {
margin-bottom: 20px;
}
.header-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20px 0;
position: relative;
border-bottom: 2px solid #d9d9d9;
}
.logo-name {
display: block;
font-size: 26px;
line-height: 1;
font-family: 'Radley', serif;
text-transform: uppercase;
color: #19121e;
}
.logo-description {
position: relative;
display: block;
text-align: right;
font-size: 10px;
text-transform: uppercase;
color: #a1787e;
}
.logo-description:before {
content: "";
position: absolute;
top: 50%;
left: 0;
right: 0;
height: 1px;
background-color: #a1787e;
z-index: -1;
}
.logo-description span {
padding-left: 10px;
background-color: white;
}
#menu {
position: absolute;
top: calc(100% + 1px);
left: 0;
right: 0;
z-index: 10;
visibility: hidden;
opacity: 0;
background-color: white;
transition: .3s linear;
}
#menu.show {
visibility: visible;
opacity: 1;
}
#menu li a {
display: block;
padding: 10px 0;
position: relative;
color: #19121e;
font-size: 18px;
}
#menu li.current a {
color: #a1787e;
}
.burger {
position: relative;
width: 28px;
height: 19px;
cursor: pointer;
}
.burger span {
position: absolute;
top: 8px;
width: 28px;
height: 3px;
background-color: #19121e;
transition: background-color .3s ease-in-out;
}
.burger span:before, .burger span:after {
content: "";
position: absolute;
width: 28px;
height: 3px;
background-color: #19121e;
transform: rotate(0deg);
transition: background-color .3s ease-in-out, transform .4s ease-in-out, top .4s ease-in-out;
}
.burger span:before {
top: -8px;
}
.burger span:after {
top: 8px;
}
.burger.close span {
background-color: transparent;
}
.burger.close span:before {
background-color: #a1787e;
transform: rotate(45deg);
top: 0;
}
.burger.close span:after {
background-color: #a1787e;
transform: rotate(-45deg);
top: 0;
}
/*************************************************************/
/* PORTFOLIO GRID */
/*************************************************************/
.grid {
margin-bottom: 20px;
}
.grid-item {
width: 100%;
padding: 10px;
}
.grid-item a {
display: block;
}
.grid-item img {
display: block;
width: 100%;
-webkit-filter: grayscale(100%);
filter: grayscale(100%);
transition: .5s ease-in-out;
}
.grid-item a:hover img {
-webkit-filter: grayscale(0%);
filter: grayscale(0%);
}
/*************************************************************/
/* FOOTER */
/*************************************************************/
.footer-row {
padding: 20px 0;
border-top: 2px solid #d9d9d9;
}
.footer-col {
padding: 0 10px;
}
.footer-col:first-child {
text-align: center;
}
.social-icons-wrapper {
display: flex;
justify-content: center;
align-items: center;
margin-top: 20px;
}
.social-icon {
display: block;
width: 24px;
height: 24px;
line-height: 24px;
border-radius: 50%;
margin-left: 12px;
text-align: center;
font-size: 15px;
color: #a1787e;
background-color: rgba(20, 20, 20, 0);
transform: scale(1);
transition: .3s linear;
}
.social-icon:hover {
transform: scale(1.2);
background: #a1787e;
color: #fff;
}
/*************************************************************/
/* MEDIA QUERIES */
/*************************************************************/
@media (min-width: 480px) {
.grid, .footer-row {
display: flex;
}
.grid-item, .footer-col {
width: 50%;
}
.social-icons-wrapper {
justify-content: flex-end;
margin-top: 0;
}
.footer-col:first-child {
text-align: left;
}
}
@media (min-width: 768px) {
.grid-item {
width: 33.33333333333333%;
}
.burger {
display: none;
}
.header-row {
display: flex;
align-items: center;
justify-content: space-between;
}
#menu {
display: flex;
position: static;
visibility: visible;
opacity: 1;
}
#menu li {
padding-left: 40px;
}
#menu li a {
padding: 0;
}
#menu li a:before {
content: "";
position: absolute;
bottom: -4px;
right: 0;
left: auto;
width: 0;
height: 1px;
z-index: 2;
background-color: #19121e;
transition: .25s cubic-bezier(.694, .048, .335, 1) .15s;
}
#menu li a:hover:before, #menu li.current a:before {
width: 100%;
left: 0;
}
#menu li.current a:before {
background-color: #a1787e;
}
}
6. Скрипты
Для полноценной работы нужно подключить следующие скрипты:
<script src="js/jquery-2.2.4.min.js"></script>
<script src="js/imagesloaded.min.js"></script>
<script src="js/masonry.min.js"></script>
<script src="js/main.js"></script>
</body>
</html>
Проблема с накладыванием изображений сетки решается с помощью плагина imagesloaded. Он определяет, когда изображение загружено и после этого строит сетку Masonry.
6.1. Файл main.js
(function ($) {
$(window).on("load", function () {
var masonryGrid = $(".grid");
masonryGrid.imagesLoaded(function () {
masonryGrid.masonry({
itemSelector: ".grid-item",
percentPosition: true
});
});
});
$(document).on("click", ".burger", function () {
$(".burger").toggleClass("close");
$("#menu").toggleClass("show");
});
})(jQuery);