Всем привет!
Решил накропать маленький пост о том, как в ВП создать главное изображение сайта (hero image), что для этого уже есть в движке и как это использовать.
Если кому-то будет интересно, кто-то узнает что-то новое - буду рад. Увидите ошибки, сообщайте.
Вообще, если подобная тематика ("как сделать?..") зайдет (и не только для ВП), буду чё-нить выкладывать. Если народ не будет против ::)
Несколько слов, вначале...
Я буду использовать последнюю на данный момент версию 5.8.1. В этой версии уже имеется поддержка формата webp. Почти полноценная поддерка - загрузка изображений посредством медиа аплоадера, превьюшки картинок в библиотеке... все дела, в общем. Поэтому, я буду использовать веппи.
Если есть желание попробовать этот формат, посмотреть, реально ли он жмет жипеги на 40%, переходите в их репозиторий https://storage.googleapis.com/downloads.webmproject.org/releases/webp/index.html, качаете самый свежий архив и распаковываете на своем диске.
Так как cwebp - утилита командной строки, установщика не имеет, желательно добавить путь к каталогу, в котором лежит экзешник cwebp в переменную path. Тогда конвертер будет доступен из любого каталога по своему имени.
Маленький лайфхак: если в любой открытой в проводнике папке с зажатым шифтом щелкнуть правой кнопкой мыша по пустому месту, в развернувшемся контекстном меню появится дополнительный пункт "открыть окно команд" (или открыть powershell, если он установлен в качестве командного шела).
После добавления пути в переменную path, конвертировать изображения будет совсем просто: открыли каталог с картинками, с шифтом нажали правую кнопку мыша чтобы открыть командную строку в этом каталоге, в командной строке набрали cwebp file.jpg -o file.webp.
Плюс, в дoкументашке по libwebp есть батники, которые пройдутся по каталогу с картинками рекурсивно.
Далее... Тема Вордпресс.
Значение имеет только один момент: включена ли поддержка пользовательских изображений в используемой вами теме оформления. Если включена, вы можете не проводить экспериментов, а сравнивать реализацию в вашей теме с тем, о чем я буду писать.
Узнать, включена ли поддержка можно так: админ-панель -> внешний вид -> настроить. В открывшемся интерфейсе ищите несколько странный перевод Заголовок. Если Заголовок есть, значит поддержка пользовательских изображений включена.
Да, и я проговорился... Добавлять главное изображение мы будем, задействуя поддержку темой пользовательских изображений.
И чтобы наши ковыряния в коде не были удалены при первом же обновлении темы, работать будем с темой дочерней. В принципе, создать дочернюю ему руками не так сложно. Если умеете - пожалуйста. Если нет, то лучше установить плагин типа child theme generator. Он сделает все за вас. После создания дочерней темы плагин можно удалить.
Далее... Шаблон.
Мы не будем погружаться в иерархию шаблонов ВП. Для дочерней темы с нашей задачей достаточно скопировать (или создать) один единственный шаблон из каталога родительской темы в каталог темы дочерней.
Какой шаблон использовать? Здесь все зависит от того, где вы желаете вывести главное изображение... и что у вас является главной страницей сайта.
Если это блог, то можно создать шаблон home.php, если главная страница будет статической, то можно создать front-page.php (ну, или скопировать их из родительской темы оформления).
Можно поступить еще проще: использовать шаблон header.php (так я и поступлю). Но тогда добавляемый код лучше выводить внутри проверки "а является ли это главной страницей". В противном случае, наше главное изображение будет выводиться на всех страницах сайта.
Далее... Файлы шаблона.
Для дочерней темы достаточно 2-х файлов: style.css (в котором мы сообщаем вордпрессу о том, что это дочерняя тема, и указываем, кто ее родитель) и functions.php (здесь подключаются стили родителя и стили ребенка).
Как я уже сказал, в качестве примера "внедрения" я буду использовать шаблон header.php. Это будет третий файл.
И еще я создаю два каталога: inc (здесь будет функционал, подключаемый к fuctions.php) и page-template (здесь будут "части шаблонов" - я планирую рассмореть пару/тройку способов добавления главного изображения, и чтобы не удалять предыдущий код, я буду писать его в частичном шаблоне и подключать в header.php)
Последнее... Наша задача, по названию этой темы на форуме, состоит в выводе некоторых картинок на сайт. Вопросы "а как добавить форму обратной связи?"/"а как вывести в блоке с изображением свой текст?"/и пр. рассматриваться не будут
Итог... У меня установлен ВП последней версии. В качестве темы для экспериментов я выбираю дефолтную 2021. Она хороша еще тем, что возможность вывести собственное главное изображение в ней отсутствует. Копирую header.php из темы 2021, создаю каталоги, о которых писал чуть выше, получая такую файловую систему
$ tree
.
├── functions.php
├── header.php
├── style.css
├── inc
└── template-parts
├── background-header.php
├── banner.php
├── default-header.php
├── imagetag-header.php
└── markup-header.php
В template-parts - частичные шаблоны, которые буду заполнятся по мере рассмотрения способов создания.
Header.php взят из 2021 и немного изменен (закомментаренные строки для подключения частичных шаблонов)
<div id="page" class="site">
<a class="skip-link screen-reader-text" href="#content"><?php esc_html_e( 'Skip to content', 'twentytwentyone' ); ?></a>
<?php
get_template_part( 'template-parts/header/site-header' );
//get_template_part( 'template-parts/default-header' );
//get_template_part( 'template-parts/imagetag-header' );
//get_template_part( 'template-parts/markup-header' );
//get_template_part( 'template-parts/background-header' );
//get_template_part( 'template-parts/banner' );
?>
<div id="content" class="site-content">
<div id="primary" class="content-area">
<main id="main" class="site-main" role="main">
Приступаем :)
Для добавления главного изображения в ВП существует т.н поддержка темой некоторого свойства, которое именуется custom-header. В общем виде добавление поддержки пользовательских заголовков (custom-header) выглядит так
add_theme_support( 'custom-header', $args );
здесь $args - массив доступных аргументов.
В ВП custom-header - это не только добавление в админ-интерфейс формы, при помощи которой пользователь может добавить/изменить/удалить собственное изображение. Разработчики решили предоставить возможность пользователям управлять цветом текстовых заголовков. На моё ИМХО - сомнительная возможность. Поэтому цветом текста мы озадачиваться не будем.
Что ж, добавляем первый код в функциональный файл functions.php и переходим к...
Способ 1 - "дефолтный"
Дефолтный потому, что это, по сути, единственный вариант, описанный в кодексе - https://codex.wordpress.org/Custom_Headers
Работает это так:
- добавляется поддержка темой выбранного свойства, что мы уже сделали
- описывается набор аргументов
- для вывода на страницах сайта используется специальная ВП-функция header_image()
- включение поддержки добавляет новый пункт "Заголовок" в разделе "Внешний вид" админки для управления пользовательскими изображениями
Значит, набор аргументов (файл functions.php)
add_theme_support( 'custom-header', $args );
$args = array(
'default-image' => '',
'width' => 1920,
'height' => 1080,
'flex-height' => true,
'flex-width' => true,
'uploads' => true
);
Здесь,
default-image оставляем пустым, пользователь сам выберет изображение и сам загрузит его на сайт;
ширина и высота изображения задаются явно, в пикселях;
но если мы для ключей с flex-* установим значение в true, ширина и высота изображения не будут жестко связаны с прописанными нами размерами (в медиа аплоадере для каждого загружаемого изображения будет добавлена кнопка "не обрезать");
uploads позволяет управлять изображением из админки (загрузить/удалить)
Остается прописать вывод изображения в шаблоне. Так как способ дефолтный, то для создания разметки используем частичный шаблон default-header.php. Не забываем снять комментарий со строки /get_template_part( 'template-parts/default-header' ); в header.php
<?php
/**
* Use get_custom_header() function
*/
// Default behavior
if ( get_header_image() ) : ?>
<div id="site-header">
<img src="<?php header_image(); ?>" width="<?php echo absint( get_custom_header()->width ); ?>" height="<?php echo absint( get_custom_header()->height ); ?>" alt="<?php echo esc_attr( get_bloginfo( 'name' ) ); ?>">
</div>
<?php endif; ?>
Всё достаточно просто:
функция header_image возвращает url изображения, поэтому она вставлена в src тега img,
get_custom_header позволяет получить данные загруженного изображения.
Результат будет такой.
Для страницы настроек Заголовка в админке сайта:
(https://res.cloudinary.com/valery/image/upload/v1631083396/Custom%20Header/custom-header-7.png)
Главная страница сайта:
(https://res.cloudinary.com/valery/image/upload/v1631083507/Custom%20Header/custom-header-9.png)
Итак, плюсы данного метода:
- очевидная простота
- возможность вывести нужное изображение в любом месте сайта
- размеры картинок установлены не жестко
Но есть не менее очевидный минус:
изображение, выводимое при помощи рекомендуемой функции header_image(); имеет одну размерность. В моем примере - это 1920х1279 (см. предыдущий скриншот). Но если вы заглянете в каталог uploads (именно туда складируются все картинки, загружаемые через медиа аплоадер), то увидите, что ВП для загруженного изображения создал несколько экземпляров этого изображения в соответствии с теми размерами, которые используются активной темой.
То есть... header_image(); работает с исходным изображением, про существование экземпляров этого изображения других размеров он не знает.
Главная засада с этим способом, на моё ИМХО, в следующем:
если вы подобрали картинку с пропорциями 3 к 1 или 4 к 1 (узкая и длинная), для десктопов она может и будет выглядеть хорошо, но на мобилах вы получите из-за правила для img {max-width: 100%;} узкое и мелкое изображение. Например, на яФонах высота изображения с исходными размерами 1920х640 будет всего 120px, что совсем не торт) Я знаю форумчан, у которых на сайте есть подобный баннер...
Способ 2 - вариация "дефолтного", шаблон - background-header.php
Понятно, что если header_image(); возвращает нам url изображения, мы можем использовать этот url не только как источник (src) для тега img, но и как адрес для фонового изображения.
<?php
/**
* Use get_custom_header() function
*/
?>
<style>
#site-bgheader {
background-size: cover;
background-repeat: no-repeat;
background-position: top right;
min-height: 30rem;
}
</style>
<!--Background Image-->
<?php
if ( get_header_image() ) : ?>
<div id="site-bgheader"
style="
background-image: url('<?php header_image(); ?>');
">
</div>
<?php endif; ?>
То есть... для блока id="site-bgheader" явно прописываем стиль с url('<?php header_image(); ?>').
Inline-стили подбираются в зависимости от изображения. Главное здесь - background-size: cover; При такой установке правила изображение не будет подгоняться под размер родительского контейнера (как при значении contain). Правилом background-position задается размещение картинки в родительском блоке.
Плюсы и минусы такого способа аналогичны + и - "дефолтного". За небольшим исключением:
- на мобильных устройствах ваш баннер не будет масштабироваться под размер экрана; картинка всегда будет большая (точнее, ее видимая часть)
- высота фонового изображения
Я руками прописал минимальную высоту в 480px. И выглядит это примерно так:
(https://res.cloudinary.com/valery/image/upload/v1631158672/Custom%20Header/custom-header-26.png)
P.S. Именно с фонами работают большинство тем, в свойствах которых присутствует поддержка custom-header. Потому, что на малых экранах легко получить большое не масштабированное изображение (в отличии от тега img).
В примере я использую только min-height. Это означает, что и для 2К мониторов мой баннер будет ограничен высотой 480px. Самым простым решением будет добавление @media с высотой под каждый конкретный брейкпоинт.
Еще момент: в примере блок id="site-bgheader" пустой. То есть не содержит ни заголовков, ни форм, ни текстовых описаний, который пользователь может захотеть туда добавить... Решение - добавление своих стилей. Это не сложно)
Способ 3 - использование всего набора изображений, шаблон imagetag-header.php
Перед тем, как писать данный пост, я просмотрел несколько тем с официального сайта. На предмет "а как разработчики кодируют вывод custom header?". Вывод: если исключить шаблоны, использующие элементор или другие пейдж билдеры, в остатке никто не парится размерами картинок, у всех src="<?php header_image(); ?>" :o
Кстати, использование элементора не означает, что ваши баннеры будут адаптивны. Я посмотрел демки двух тем с вп.орг из списка топ: OceanWP и Astra - фигня та же, на мобилах грузятся картинки максимального размера. Например,
Rings от OceanWP - https://rings.oceanwp.org/
Outdoor от Астры - https://websitedemos.net/outdoor-adventure-02/
Они используют background-image, но сути это не меняет: для мобильных устройств грузятся изображения на пару-тройку сотен килобайт.
На самом деле, это странно. Ибо решение простое - ВП функция get_header_image_tag();, добавленная ещё в ВП версии 4.4. Результатом примения будет тег img на выходе с подтянутыми srcset (источниками). В общем, код, добавляемый в выбранный частичный шаблон:
<?php
/**
* Use with get_header_image_tag() (since WP 4.4)
*/
if ( get_header_image() ) :
$img = get_header_image_tag();
echo ' <div id="site-header">';
echo $img;
echo '</div>';
endif;
И результат (инициатор imageset):
(https://res.cloudinary.com/valery/image/upload/v1631164774/Custom%20Header/custom-header-13.png)
Плюс применения данной функции очевиден: для устройств с малым экраном будет прогружаться не исходное изображение, а его экземпляр, наиболее подходящий по размеру.
Способ 4 - the_custom_header_markup(), шаблон markup-header.php
Данная ВП функция появилась в версии 4.7. Используется для вывода (и создания разметки) изображений или видео на страницах сайта. Применительно к нашему случаю: выводу главного изображения сайта - код приобретает очень простой вид
<?php
/**
* Use the_custom_header_markup(); (since WP 4.7)
* если в custom-header используются video и video-active-callback, то добавляется тег video; если нет video - тег img
*/
the_custom_header_markup();
Результат аналогичен предыдущему. Будет создан блок с классом wp-custom-header и изображением, содержащим srcset'ы. Поэтому, скриншот не прилагаю)
Способ 5 - использование кастомайзера
Все рассмотренные до этого момента варианты позволяли вывести в качестве главного выбранное изображение. И если размеры исходной картинки велики, мы можем выводить её фоном (способ с background-image), используя background-size: cover; и размещая относительно top/right/bottom/left родительского блока.
Тогда любой вложенный в родительский блок (id="site-bgheader" из второго способа) элемент (заголовок, форма обраной связи и т.п.) может быть размещен в "пределах" этого фонового изображения при помощи стилей.
Но... Мы можем выводить два главных изображения (естесственно, изначально подготовленных): одно - для десктопов, другое - для мобильных устройств; одно - с ориентацией ландшафт, другое - с ориентацией портрет. Так как функционал custom-header сделать этого не позволяет (так же, как и регистрация множества пользовательских изображений - register_default_headers();) воспользуемся вордпресс-кастомайзером
С помощью ВП-кастомайзера мы сможем
- создать секцию
- в которую выведем наши настройки
После чего пользователю через интерфейс Внешний Вид -> Настроить будет доступна возможность загрузить созданные для разных ориентаций экранов изображения.
Я создаю файл customizer.php в каталоге inc, подключаю его в functions
// Add Customizer functionality
require_once get_stylesheet_directory() . '/inc/customizer.php';
В файл customizer.php прописываю следующий код:
<?php
/**
* Customizer functionality
*/
function child_customizer_settings($wp_customizer) {
// include new section
$wp_customizer->add_section( 'header', array(
'title' => __('Header banners'),
'priority' => 70
) );
// add capability
$wp_customizer->add_setting( 'landscape_image', array(
'capability' => 'edit_theme_options'
) );
$wp_customizer->add_setting( 'portrait_image', array(
'capability' => 'edit_theme_options'
) );
// add controls
$wp_customizer->add_control(
new WP_Customize_Image_Control(
$wp_customizer,
'landscape_image',
array(
'label' => __('Landscape orientation'),
'section' => 'header'
)
)
);
$wp_customizer->add_control(
new WP_Customize_Image_Control(
$wp_customizer,
'portrait_image',
array(
'label' => __('Portrait orientation'),
'section' => 'header'
)
)
);
}
add_action( 'customize_register', 'child_customizer_settings' );
Здесь, Header banners - это заголовок, который появится в "Внешний Вид -> Настроить", класс WP_Customize_Image_Control позволяет добавить в созданную нами секцию header форму для работы с изображениями (загрузить/удалить/изменить).
Остается только загрузить заранее подготовленные изображения через "Внешний Вид -> Настроить -> Header banners". Результат будет примерно такой:
(https://res.cloudinary.com/valery/image/upload/v1631168807/Custom%20Header/custom-header-49.png)
Остается последний штрих - прописать вывод. Здесь возможны два варианта: использовать картинки как фон или выводить при помощи тега img. Я прописал оба варианта (закомментировав вывод бэкграунда). Оба работают, использовать можно любой :)
Итак, частичный шаблон banner.php:
<?php
/**
* Use customized Banner images
*/
?>
<style>
#site-banner {
background-size: cover;
background-repeat: no-repeat;
background-position: top right;
min-height: 30rem;
}
@media screen and (orientation: landscape) {
#site-banner {
background-image: url(<?php echo esc_url(get_theme_mod('landscape_image')); ?>);
}
}
@media screen and (orientation: portrait) {
#site-banner {
background-image: url(<?php echo esc_url(get_theme_mod('portrait_image')); ?>);
}
}
</style>
<!--Background Banner-->
<!--<div id="site-banner">
</div>-->
<!--Images Banner-->
<div id="site-imagesbanner">
<picture>
<source media="(orientation: portrait)" srcset="<?php echo esc_url(get_theme_mod('portrait_image')); ?>" type="image/webp" >
<source media="(orientation: landscape)" srcset="<?php echo esc_url(get_theme_mod('landscape_image')); ?>" type="image/webp" >
<img src="<?php echo esc_url(get_theme_mod('landscape_image')); ?>" >
</picture>
</div>
Здесь, для вывода изображения я использую picture (можно добавить media query). Стили относятся только к блоку id="site-banner". Если решите выводить картинки фоном, то блок id="site-imagesbanner" можно просто удалить.
В общем, результат
(https://res.cloudinary.com/valery/image/upload/v1631170365/Custom%20Header/customizer.jpg)
По итогу...
Итак, пять способов добавления :D
Каждый имеет свои плюсы и минусы. Выбирать, каким методом добавлять главные изображения на сайт - вам (если они, конечно, вам там нужны). Главное - для достижения результата нам не потребовалось ставить никаких плагинов, использовалось только то, что есть в движке ВП. Способы достаточно простые, и не требуют особых познаний.