Используем Masonry для добавления сеточного стиля записей в WordPress

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

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

Masonry-Tutorial-Screenshot

Шаг 1. Добавляем необходимые библиотеки к своей теме.

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

WordPress включает в себя Masonry 2, однако вместе с WordPress 3.7 библиотека не была обновлена до 3. В результате нам придется отменить регистрацию Masonry, что я обычно не делаю, но в данном случае поступить иначе не получится. Как вы можете заметить в функции ниже, мы просто добавляем Masonry 3 к фронт-энду, а не к области администратора, где библиотека по сути не требуется.

Вот функция, а также действие для добавления двух библиотек и таблицы стилей для Masonry:

if (! function_exists('slug_scripts_masonry') ) :
if ( ! is_admin() ) :
function slug_scripts_masonry() {
    //deregister built in masonry since it is old version 3.
    wp_deregister_script('jquery-masonry');
    wp_enqueue_script('imagesLoaded', get_template_directory_uri().'/js/imagesloaded.pkgd.min.js', false, null, true);
    wp_enqueue_script('jquery-masonry', get_template_directory_uri().'/js/masonry.pkgd.min.js', array( 'imagesLoaded'), null, true );
}
    wp_enquqe_style('masonry’, get_template_directory_uri().'/css/’);
add_action( 'wp_enqueue_scripts', 'slug_scripts_masonry' );
endif; //! is_admin()
endif; //! slug_scripts_masonry exists

Единственное, что стоит отметить здесь: мы передаем хэндл imagesLoaded в качестве третьего параметра wp_enqueue_scripts(), который определяет зависимости. С его помощью мы убедимся в том, что Masonry будет загружаться всегда после imagesLoaded. Также отметьте для себя то, что мы не добавляем jQuery в качестве зависимостей для них. Одно из преимуществ Masonry 3 над Masonry 2 заключается в том, что версия 3 не требует библиотеки jQuery, но может использоваться с ней. Как показывает мой опыт, инициализация Masonry без jQuery более надежная, и открывает возможность пропуска загрузки jQuery, что позволяет решить проблемы с совместимостью и временем загрузки страниц.

Шаг 2. Инициализируем Javascript.

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

Вот функция и действия, которые будут выводить скрипт инициализации в футере страницы:

if ( ! function_exists( 'slug_masonry_init' )) :
function slug_masonry_exists() { ?>
<script>
    //set the container that Masonry will be inside of in a var
    var container = document.querySelector('#masonry-loop');
    //create empty var msnry
    var msnry;
    // initialize Masonry after all images have loaded
    imagesLoaded( container, function() {
        msnry = new Masonry( container, {
            itemSelector: '.masonry-entry'
        });
    });
</script>
<?php }
//add to wp_footer
add_action( 'wp_footer', 'slug_masonry_init' );
endif; // ! slug_masonry_init exists

Все действия функции описаны в комментариях. Что делает Javascript-функция? Она говорит Masonry, что нужно искать элементы с классом «masonry-entry» внутри контейнера с id «masonry-loop», и вычислять сетку после того, как все изображения будут загружены. Внешний контейнер мы определяем в querySelector, а внутренний – в itemSelector.

Шаг 3. Создаем цикл Masonry.

Вместо того чтобы добавлять HTML-разметку для Masonry напрямую в шаблон, мы поступим несколько иначе: мы создадим отдельную часть шаблона для него. Для этого нам нужно создать новый файл под названием content-masonry.php и добавить его к теме. Это позволит нам подключить Masonry-цикл к неограниченному количеству разных шаблонов.

В наш новый файл нам нужно добавить код, представленный ниже. Разметка напоминает стандартный вывод превью контента. Вы всегда можете изменить ее, если вам это потребуется. Сейчас же нам важно убедиться в том, что у крайнего элемента имеется класс masonry-entry, который мы установили как itemSelector на последнем шаге.

<article class="masonry-entry" id="post-<?php the_ID(); ?>" <?php post_class(); ?> >
<?php if ( has_post_thumbnail() ) : ?>
    <div class="masonry-thumbnail">
        <a href="<?php the_permalink(' ') ?>" title="<?php the_title(); ?>"><?php the_post_thumbnail('masonry-thumb'); ?></a>
    </div><!--.masonry-thumbnail-->
<?php endif; ?>
    <div class="masonry-details">
        <h5><a href="<?php the_permalink(' ') ?>" title="<?php the_title(); ?>"><span class="masonry-post-title"> <?php the_title(); ?></span></a></h5>
        <div class="masonry-post-excerpt">
            <?php the_excerpt(); ?>
        </div><!--.masonry-post-excerpt-->
    </div><!--/.masonry-entry-details -->  
</article><!--/.masonry-entry-->

В разметке установлены классы для всех основных частей. Вы можете изменить разметку так, как вам удобно, чтобы она соответствовала вашей теме. Мне нравится добавлять красивые закругленные границы к .masonry-entry. Еще одно хорошее решение – отсутствие границ у .masonry-entry, однако присутствие легкой тени. Это смотрится особенно красиво, когда миниатюра записи занимает всю ширину контейнера, что может быть достигнуто путем установки всех отступов и полей в 0 для .masonry-thumbnail. Вы можете добавить эти стили в файл masonry.css, который находится в папке css вашей темы.

Шаг 4. Добавляем цикл Masonry к шаблонам.

Теперь, когда у нас имеется необходимая часть шаблона, мы можем использовать ее в любом шаблоне темы. К примеру, мы можем добавить ее к index.php, но не добавлять к category.php, чтобы сеточное представление не использовалось для архивов рубрик. Если вы хотите использовать сетку только для главной страницы вашей темы, где выводятся записи блога, то в таком случае вам понадобится добавить нашу часть шаблона к home.php. Вне зависимости от того, какой шаблон вы выбрали, вам понадобится обернуть ваш цикл в контейнер с id masonry-loop и добавить часть шаблона в цикл, используя get_template_part(). Убедитесь в том, что контейнер цикла Masonry начинается до while (have_posts() ).

В качестве примера возьмем основной цикл из файла index.php темы twentythirteen:

<?php if ( have_posts() ) : ?>

    <?php /* The loop */ ?>
    <?php while ( have_posts() ) : the_post(); ?>
        <?php get_template_part( 'content', get_post_format() ); ?>
    <?php endwhile; ?>

    <?php twentythirteen_paging_nav(); ?>

<?php else : ?>
    <?php get_template_part( 'content', 'none' ); ?>
<?php endif; ?>

А вот измененный код, позволяющий использовать наш Masonry-цикл:

<?php if ( have_posts() ) : ?>
<div id="masonry-loop">
    <?php /* The loop */ ?>
    <?php while ( have_posts() ) : the_post(); ?>
        <?php get_template_part( 'content', 'masonry' ?>
    <?php endwhile; ?>
</div><!--/#masonry-loop-->
    <?php twentythirteen_paging_nav(); ?>

<?php else : ?>
    <?php get_template_part( 'content', 'none' ); ?>
<?php endif; ?>

Шаг 5. Задаем адаптивную ширину для Masonry-элементов.

Есть несколько способ установить ширину для каждого Masonry-элемента. Вы можете установить ширину при инициализации Masonry, используя пиксельное значение. Я не фанат такого действия, поскольку я использую адаптивные темы, а они требуют достаточно сложных медиа-запросов, чтобы добиться корректного отображения разметки на небольших экранах. Для адаптивного дизайна я нашел лучший способ: я задаю значение width для .masonry-entry в процентах, основываясь на том, сколько элементов я хочу вывести в ряд. Остальное уже делает Masonry.

Все, что нужно сделать – это поделить число 100 на количество пунктов, которые вы хотите видеть в ряд. К примеру, если вы хотите видеть 4 пункта в каждой строке, то в таком случае вам нужно указать в файле masonry.css следующее:

.masonry-entry{width:25%}

Шаг 6. Мобильная оптимизация.

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

Я не думаю, что экран мобильного телефона имеет так много пространства, чтобы вместить все компоненты, добавленные нами в часть шаблона content-masonry. Решение для мобильных телефонов заключается в том, чтобы либо урезать цитаты элементов, либо полностью убрать их. Вот дополнительная функция, которую вы можете добавить в файл functions.php вашей темы, чтобы сделать это. Я не думаю, что такая проблема актуальна для планшетов, поэтому я использую прекрасный плагин Mobble во всех примерах данной секции для определения мобильных телефонов. Я также выполняю проверку активности Mobble перед его использованием, и, если нужно, совершаю откат назад к более общему мобильному обнаружению, которое производится с помощью встроенной в ядро WP функции wp_is_mobile.

if (! function_exists('slug_custom_excerpt_length') ) :
function slug_custom_excerpt_length( $length ) {
    //set the shorter length once
    $short = 10;
    //set long length once
    $long = 55;
    //if we can only set short excerpt for phones, else short for all mobile devices
    if (function_exists( 'is_phone') {
        if ( is_phone() ) {
            return $short;
        }
        else {
            return $long;
        }        
    }
    else {
        if ( wp_is_mobile() ) {
            return $short;
        }
        else {
            return $long;
        }
    }
}
add_filter( 'excerpt_length', 'slug_custom_excerpt_length', 999 );
endif; // ! slug_custom_excerpt_length exists

Как вы можете видеть, мы сохраняем длину большой цитаты и длину урезанной цитаты в соответствующих переменных, поскольку нам понадобится обращаться к ним впоследствии. Затем мы проверяем, можем ли мы использовать is_phone() от плагина Mobble. Если да, то мы задаем короткую цитату для мобильных телефонов; иначе мы задаем длинную цитату. Затем мы делаем практически то же самое, только уже с помощью функции wp_is_mobile, которая охватывает все мобильные устройства. Делается это тогда, когда is_phone() не получилось использовать. Ветвь else этой функции скорее всего не будет выполняться никогда, но лучше создать бэкап на всякий случай. Как только логическое условие определения длины цитаты будет пройдено, дальше пойдет подцепление функции к фильтру excerpt_length.

Урезание цитаты – один из вариантов решения проблемы, однако есть и другой путь. Мы можем вообще отказаться от цитаты. Вот новая версия content-masonry, где цитата полностью опущена для мобильных телефонов:

<article class="masonry-entry" id="post-<?php the_ID(); ?>" <?php post_class(); ?> >
<?php if ( has_post_thumbnail() ) : ?>
    <div class="masonry-thumbnail">
        <a href="<?php the_permalink(' ') ?>" title="<?php the_title(); ?>"><?php the_post_thumbnail('masonry-thumb'); ?></a>
    </div><!--.masonry-thumbnail-->
<?php endif; ?>
    <div class="masonry-details">
        <h5><a href="<?php the_permalink(' ') ?>" title="<?php the_title(); ?>"><span class="masonry-post-title"> <?php the_title(); ?></span></a></h5>
        <?php 
            //put the excerpt markup in variable so we don't have to repeat it multiple times.
            $excerpt = '<div class="masonry-post-excerpt">';
            $excerpt .= the_excerpt();
            $excerpt .= '</div><!--.masonry-post-excerpt-->';
//if we can only skip for phones, else skip for all mobile devices
            if (function_exists( 'is_phone') {
                if ( ! is_phone() ) {
                    echo $excerpt;
                }
            }
            else {
                if ( ! wp_is_mobile() ) {
                    echo $excerpt;
                }
            }
        ?>
    </div><!--/.masonry-entry-details -->  
</article><!--/.masonry-entry-->

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

Также вы, возможно, захотели бы увеличить ширину пунктов Masonry для мобильных устройств, что привело бы к сокращению количества пунктов в одном ряду. Чтобы сделать это, мы добавим разные строчные стили к заголовку, основываясь на механизме обнаружения устройств. Поскольку эта функция использует wp_add_inline_styles, все будет зависеть от определенной стилевой таблицы. Я использую в таком случае masonry.css, вы при желании можете воспользоваться любой другой зарегистрированной стилевой таблицей.

if ( ! function_exists ( 'slug_masonry_styles' ) ) :
function slug_masonry_styles() {
    //set the wide width
    $wide = '25%';
    //set narrow width
    $narrow = '50%';
    /**Determine value for $width**/
    //if we can only set narrow for phones, else narrow for all mobile devices
    if (function_exists( 'is_phone') {
        if ( is_phone() ) {
            $width = $narrow;
        }
        else {
            $width = $wide;
        }        
    }
    else {
        if ( wp_is_mobile() ) {
            $width = $narrow;
        }
        else {
            $width = $wide;
        }
    }
    /**Output CSS for .masonry-entry with proper width**/
    $custom_css = ".masonry-entry{width: {$width};}";
    //You must use the handle of an already enqueued stylesheet here.
    wp_add_inline_style( 'masonry', $custom_css );
}
add_action( 'wp_enqueue_scripts', 'slug_masonry_styles' );
endif; // ! slug_masonry_styles exists

Функция подключает произвольную стилевую таблицу, после чего задается значение для ширины с уже знакомой нам логикой. Затем мы создаем переменную $custom_css, передавая значение для ширины в виде CSS. После этого мы применяем wp_add_inline_style для вывода наших строчных стилей в области хэдера всякий раз, когда стилевая таблица Masonry будет использоваться. Наконец, мы подцепляем всю функцию к wp_enqueue_scripts.

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

if ( is_home() || is_archive() ) {
    add_action( 'wp_enqueue_scripts', 'slug_scripts_masonry' );
}

Два последних примера должны родить в вашей голове новые идеи. Допустим, вы можете использовать аналогичную логику, чтобы вообще убрать Masonry для мобильных устройств. Функция wp_add_inline_style() используется не слишком часто, но при этом остается очень полезной, поскольку она позволяет программно устанавливать разные стили в зависимости от любых условий. С ее помощью вы можете радикально изменить стиль любого элемента, основываясь не только на обнаружении устройств, но и на других факторах – к примеру, менять стиль в зависимости от используемого шаблона или в зависимости от того, залогинился пользователь или нет.

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

Источник: wpbeginner.com

Блог про WordPress
Комментарии: 3
  1. Jimmy Exploit

    создал блок с контентом, внутри которого Masonry динамически его форматирует, если меняется размер окна. но вот проблема. сайдбар у меня сворачивается при нажатии на кнопку, а за ним и изменяется и размер расположения контента, при этом Masonry его не форматирует((. что нужно вписать в кнопку, чтобы она сворачивала сайдбар и вместе с этим перезапускала форматирование контента?

  2. VicKey

    Спасибо! Нигде больше не находил подробной установки, как у вас)))

  3. Root

    Вы сами хоть пытались с «вашего» урока подключить этот скрипт? У меня одни ошибки!
    Начнем с того, что с мобильной оптимизацией что-то накосячино. Плюс ко всему, ошибка в функции вывода скрипта в footer… :(

Добавить комментарий для Jimmy Exploit Отменить ответ

Получать новые комментарии по электронной почте.