WordPress как на ладони
wordpress jino

Дочерние темы WordPress

Дочерняя тема WordPress (подтема) — это дополнительная тема, которая позволяет изменять/дополнять функции и внешний вид основной темы. При этом основная тема остается не тронутой, а значит её можно обновлять, не опасаясь, что внесенные изменения потеряются.

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

Оглавление:

Зачем нужна дочерняя тема?

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

Поэтому, если вы используете готовую тему WordPress, автор которой не бросил разработку, то не редактируйте файлы темы напрямую, а создайте дочернюю тему и изменяйте основную тему через дочернюю.

Что можно изменить в  дочерней теме?

В ней можно изменить практически все, но нужно понимать что и как работает (см. ниже). Однако, чтобы изменять некоторые вещи, родительская тема должна быть создана с учетом возможных изменений. Если разработчик родительской темы, не продумывает возможные изменения, то изменить некоторые моменты будет или сложно, или невозможно.

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

Был вопрос по подтемам, рекомендую прочитать: Как вносить изменения в шаблоны дочерней темы?

к началу

Создание дочерней темы

Создать подтему легко! Ниже создается дочерняя к twentyfifteen тема.

  1. Создайте папку с любым названием в каталоге тем: wp-content/themes. Пусть twentyfifteen-child

  2. Создайте в новой папке файл style.css. С содержимым:

    /*
    Theme Name: Моя дочерняя тема
    Template: twentyfifteen
    
    Не обязательные параметры:
    Theme URI: http://site.ru/
    Description: Дочерняя тема для темы twentyfifteen
    Author: Kama
    Author URI: http://site.ru/about/
    Version: 1.0
    */
    
    /* импортируем стили родительской темы */
    @import url("../twentyfifteen/style.css");
    
    /* Свои дополнительные стили */
    .foo{ color:red; }
  3. Зайдите во Внешний вид › Темы и активируйте новую тему «Моя дочерняя тема».

Обязательно нужно указать строку Template: twentyfifteen, (строка регистрозависима) она указывает что это подтема темы twentyfifteen.

Директива @import должна быть первым правилом в style.css. Если написать правила перед ней, то она не сработает и стили родительской темы не подключаться.

В результате у нас должна получиться такая структура:

wp-content
   └── themes
		 ├── twentyfifteen (родительская тема)
		 └── twentyfifteen-child (подтема; может иметь любое название)
				 └── style.css

twentyfifteen-child может содержать и другие файлы, среди них:

  • style.css — (обязательный) полностью заменяет такой же файл родительской темы.

  • functions.php — дополняет functions.php родительской темы (загружается перед ним).

  • файлы шаблонаindex.php, home.php и т.д., которые есть/нет в родительской теме. Если файл есть в дочерней теме, то этот файл полностью заменит родительский файл. Например: создав footer.php и скопировав в него содержимое footer.php из родительской темы, мы можем изменять вывод, не меняя файл родительской темы.

  • другие файлы — любые другие файлы/папки/что угодно. Например, подтема может использовать новые изображения, которые подключаются в дополнительных CSS правилах.
к началу

Файл style.css

style.css — единственный обязательный файл в подтеме. Дает информацию WordPress, чтобы опознать дочернюю тему.

style.css дочерней темы полностью заменяет style.css родительской темы, т.е. файл стилей родительской темы вообще не загружается.

В информационном заголовке, который должен быть в начале файла, является обязательным параметр Template:. Именно по нему WP понимает, что это дочерняя тема и как называется родительская.

Пример style.css дочерней темы.

/*
Theme Name: Моя дочерняя тема
Template: twentyfifteen
Theme URI: http://site.ru/
Description: Дочерняя тема для темы twentyfifteen
Author: Kama
Author URI: http://site.ru/about/
Version: 1.0
*/

// стили родительской темы
@import url("../twentyfifteen/style.css");

// дополнительные стили
.foo{ color:red; }
  • Theme Name  —  (обязательно) название дочерней темы.
  • Template — (обязательно) регистрозависимое название папки родительской темы.

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

  • Theme URI — адрес сайта дочерней темы.
  • Description — описание дочерней темы.
  • Author URI  — адрес сайта автора дочерней темы.
  • Author — имя автора дочерней темы.
  • Version  — версия дочерней темы.
к началу

Файл function.php

Рекомендую ознакомится со статьей: файл шаблона functions.php в WordPress.

В отличие от других файлов подтемы, functions.php не заменяет родительский файл, а дополняет его: он загружается прямо перед родительским и другими файлами подтемы.

Это значит, что для изменения родительской темы, в functions.php можно использовать хуки и можно «переопределять» функции, если они на это рассчитаны.

Использование хуков

В файле footer.php в теме twentyfifteen есть событие twentyfifteen_credits. Чтобы добавить свой текст в подвал, можно использовать это событие, для этого добавим следующий код в functions.php дочерней темы:

add_action( 'twentyfifteen_credits', function() {
	echo 'Компания © 2015';
} );

Переопределение функции

В файле functions.php родительской темы twentyfifteen есть функция twentyfifteen_fonts_url() - регистрирует шрифты google. Выглядит она так:

if( ! function_exists( 'twentyfifteen_fonts_url' ) ){
	function twentyfifteen_fonts_url(){
		// код функции ...
	}
}

Условие if( ! function_exists( 'twentyfifteen_fonts_url' ) ){ ... } (если функция существует), позволяет нам определить такую же функцию в functions.php дочерней темы.

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

Например, добавив такой код в functions.php дочерней темы, мы отключим подключение шрифтов:

function twentyfifteen_fonts_url() {
	return '';
}

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

if( ! function_exists('theme_function') ){
	function theme_function() {
		// Код.
	}
}

В этом случае, дочерняя тема может переопределить функцию родительской темы просто объявив ее в своем functions.php.

к началу

Файлы шаблона

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

Файл шаблона в дочерней теме как и style.css, заменяет файл родительской темы. Т.е. в подтеме можно заменить любой родительский файл, просто создав файл с таким же названием.

Несколько примеров создания файла шаблона в дочерней теме:

#1 Добавление шаблона, отсутствующего в родительской теме

Создадим шаблон для страницы "карта сайта". Для этого в подтеме создадим файл page-sitemap.php, а на сайте создадим страницу с ярлыком sitemap. Готово!

#2 Изменение шаблона, имеющегося в родительской теме

Допустим, у нас есть home.php в родительской теме и нам нужно его изменить.

  1. Создаем home.php в подтеме.

  2. Скопируем в него код файла из родительской темы.

  3. Изменим скопированный код как нужно.
к началу

Как это работает: шаг за шагом

Процесс работы дочерней темы со стороны WordPress:

  1. WP открывает style.css темы установленной в настройках системы и считывает заголовки.

  2. Директива Template: объявляет что у темы есть родительская тема и указывает её название. Теперь WP работает с темой как с дочерней.

  3. Дальше все файлы, кроме functions.php, подключаются с помощью locate_template(): проверяет существует ли файл в подтеме, если не существует, то подключается из родительской темы.

Локализация подтем

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

Для подключения есть спец. функция: load_child_theme_textdomain(). Используем её в functions.php подтемы:

function my_child_theme_setup() {
	load_child_theme_textdomain( 'my_child_theme', get_stylesheet_directory() . '/languages' );
}
add_action( 'after_setup_theme', 'my_child_theme_setup' );

Также, нужно создать файл перевода в дочерней теме: languages/en_US.mo.

Теперь можно использовать функции локализации WordPress в подтеме:

_e( 'Это нужно перевести на англ.', 'my_child_theme' );

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

к началу

Заметки

Функции WordPress связанные с дочерними темами

  • get_stylesheet_directory_uri() — получает URL текущей темы (дочерней, не родительской).

  • get_template_directory_uri() — получает URL текущей темы (родительской, не дочерней).

  • get_stylesheet_directory() — получает путь до текущей темы (дочерней, не родительской).

  • get_template_directory() — получает путь до текущей темы (родительской, не дочерней).

  • get_stylesheet() — получает название каталога текущей темы (дочерней, не родительской).

  • get_template() — получает название каталога текущей темы (родительской, не дочерней).

  • get_stylesheet_uri() — получает готовый URL на файл стилей style.css текущей темы. Если используется дочерняя тема, то получит ссылку на стили доч. темы. В этом случае для родительской темы такой функции в WordPress нет.

Т.е. если нужно получить ссылку на файл темы, но при этом используется дочерняя тема, то УРЛы от: get_stylesheet_directory_uri() и get_template_directory_uri() буду отличаться: первый будет на дочернюю тему, а второй на родительскую...

Форматы записей

Функция add_theme_support('post-formats') переопределит форматы, заданные родительской темой, а не дополнит их.

@import в style.css дочерней темы

Несмотря на то что везде пишут использовать @import в style.css подтемы. Делать это я не рекомендую. Потому что в этом случае браузер не может параллельно загрузить оба файла стилей: от родительской темы и от дочерней... Ему придется загрузить их последовательно: сначала стили дочерней темы, там он увидит @import и только потом начнет загружать стили родительской темы... В итоге получается, что мы теряем в скорости загрузки страницы порядка 200мс. Столько уходит на загрузку файла стилей. Под загрузкой подразумевается отправка запроса на сервер, ожидание ответа, загрузка файла...

Лучше подключить файлы стилей по-отдельности в HTML: сначала стили родительской темы, а затем дочерней, чтобы они были ниже в HTMl коде и перебивали родительские стили. Делается это так:

add_action('wp_enqueue_scripts', 'my_theme_styles' );
function my_theme_styles() {
	wp_enqueue_style('parent-theme-css', get_template_directory_uri() .'/style.css' );
	wp_enqueue_style('child-theme-css', get_stylesheet_directory_uri() .'/style.css', array('parent-theme-css') );
}

В результате в HEAD части HTML документа мы получим 2 ссылки на 2 файла стилей, которые при загрузке будут загружаться параллельно, а не последовательно. Это сэкономит нам время на один запрос к серверу от бразуера.

Плагин для быстрого создания дочерних тем

Чтобы не возиться с созданием папок и файлов, можно воспользоваться плагином One-Click Child Theme.

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

Дочерние темы WordPress 33 комментария
Полезные 3 Вопросы 2 Все
  • campusboy1381 cайт: wp-plus.ru
    @

    Спасибо за статью! Жаль, что большинство разработчиков тем пишут их так, что потом без вмешательства в неё не обойтись sad

    Ответить1.4 года назад #
    2
    • Otshelnik-Fm192 cайт: across-ocean.otshelnik-fm.ru

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

      Ответить1.4 года назад #
      • Kama4192

        Это проще, но ведь не всегда правильно. Допустим, в теме "дырка" окажется, создатель её затрет и тут очень нужно обновиться, но вы обновления закрыли... Вот это казус... И это совсем неправильно, если нужно было изменить мелочи, которые можно было сделать с помощью подтемы...

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

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

        Ответить1.4 года назад #
        2
        • Otshelnik-Fm192 cайт: across-ocean.otshelnik-fm.ru

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

          Ответить1.4 года назад #
          3
          • Bahus-6 cайт: dendrblog.ru/must-have-dlya-blogera/gde-...

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

            Ответить1.3 года назад #
            1
      • campusboy1381 cайт: wp-plus.ru
        @

        Кстати, а как отключить обновления как-то определенной темы? Поделитесь инфой, пожалуйста.

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

        Ответить1.4 года назад #
        1
        • Otshelnik-Fm192 cайт: across-ocean.otshelnik-fm.ru

          Переименовывайте в style.css темы Theme Name:
          Theme URI: и т.д. . Тогда вордпресс не сможет предложить обновления. Вроде так.

          Ответить1.4 года назад #
        • Kama4192

          Варианты:

          1 ---
          Увеличить версию темы в style.css до например 99999 и все обновления будут старые smile

          2 ---
          Отключим обновления всех тем. Добавим код в function.php. Получиться когда тема активна, обновления тем отключены:

          // отключаем обновление тем
          remove_action( 'load-update-core.php', 'wp_update_themes' );
          add_filter( 'pre_site_transient_update_themes', '__return_null' );
          
          // отключаем авто обновления
          add_filter( 'auto_update_theme', '__return_false' ); 
          
          // спрячем имеющиеся уведомления
          add_action('admin_menu','hide_admin_notices');
          function hide_admin_notices() {
          	remove_action( 'admin_notices', 'update_nag', 3 );
          }

          Фильтры их этого файла: /wp-includes/update.php

          3 ---
          Используем плагин Easy Updates Manager. Плагин по коду меня не впечатлил, но написан конечно грамотно, только кажется не особо производительно...

          Ответить1.4 года назад #
          1
  • Anatoliy cайт: facknet.ru

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

    Ответить1.3 года назад #
    • Kama4192

      Нет, так нельзя. Для отдельных страниц можно создать отдельный шаблон. А зачем нужна дочерняя тема, читайте в начале статьи...

      Ответить1.3 года назад #
  • Егор cайт: filwebs.ru
    @

    Здравствуйте, а почему вы пишете, что

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

    Если он дополняет? Если бы он заменял, то пустой style.css дочерки что бы в итоге показал на выходе?

    Ответить1.3 года назад #
    • Kama4192

      Он именно заменяет, а не дополняет (style.css род. темы уже не подключается никуда), поэтому в style.css подтемы нужно импортировать style.css родительской темы, чтобы были стили родительской темы.

      Дополняет functions.php. Т.е. подключается сначала functions.php подтемы, а затем functions.php родительской.

      Ответить1.3 года назад #
      • Егор cайт: filwebs.ru
        @

        Точно. В статье ведь подкл. через @import А я хуком подключал. Да, в моем случае дополняет. Как лучше?

        function fw_enqueue_styles() {
         wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
         wp_enqueue_style( 'child-style', get_stylesheet_directory_uri() . '/style.css', array('parent-style') );
        }
        
        add_action( 'wp_enqueue_scripts', 'fw_enqueue_styles' );
        Ответить1.3 года назад #
        • Kama4192

          Как лучше?

          Нет разницы... ну через импорт наверное удобнее, сразу в css видно что от чего зависит, ну и лишние php операции не происходит (хотя это мелочи вообще).

          Ответить1.3 года назад #
          • campusboy1381 cайт: wp-plus.ru
            @

            Уже несколько раз сталкиваюсь, что советую избегать в CSS употребление import. Не знаешь почему? Вроде что-то где-то это не поддерживается (браузеры).

            Ответить1.3 года назад #
          • campusboy1381 cайт: wp-plus.ru
            @

            Посмотрел спецификацию - да он ещё в CSS1 был. Единственный баг:

            Браузер Internet Explorer до версии 7.0 включительно не поддерживает типы носителей при импорте стилевого файла. Более того, при добавлении типа носителя стилевой файл вообще не загружается.

            Но я вот не уверен, что программы автоматической минификации и объединения CSS файлов в WP обрабатывают такие CSS. Потому я всегда подключаю CSS через function.php

            Ответить1.3 года назад #
            • Kama4192

              Обрабатывается он отлично!

              Причина не использовать - это +1 лишний запрос (но в случае <link> подключения он все равно будет) и это не страшно, но да - не желательно, в связи со всеобщей паранойей ускорения загрузки smile Плагины минификации просто обязаны обрабатывать, иначе это не плагин, а УГ...

              Еще одна причина, пожалуй самая веская: @import должен идти в самом начале, перед остальными правилами и если ошибиться, стили не импортируются...

              Но, почему пишут не используйте я не понимаю! Я бы сказал, используйте но будьте осторожны... Вот бородатая статья (оригинал) почему не надо использовать @import: потому что IE 6 7 8 ослы и в них нет параллельной загрузки файлов - это не актуально уже... В остальном нет разницы... Главное не ошибиться и подключить в начале.

              Ответить1.3 года назад #
    • Серж cайт: learn-wordpress-plugins.blogspot.com/p/b...

      Где-то я видел, вроде здесь вордпресс, функции, плагины, если без импорта css то не будет работать.

      Ответить1.2 года назад #
      -1
  • Andrey
    @

    Здравствуйте, Тимур! Скажите, пожалуйста, есть ли решение следующей задачи. Иногда у юзеров нужно сбросить css кэш. Обычно я делаю так style.css?a=1
    А вот как это сделать в wordpress? Спасибо.

    Ответить1.2 года назад #
    • Kama4192
      wp_enqueue_style( $handle, $src, $deps, $ver, $media );

      На параметр $ver смотрите... Он в конце аналогичное выводит...

      Ответить1.2 года назад #
  • Роман cайт: r0ma.ru

    По моему здесь ошибка: "Если файл есть в родительской теме, то этот файл полностью заменит родительский файл. "

    Ответить1.1 года назад #
  • garri832 cайт: clubwp.ru
    @

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

    if ( function_exists( 'add_image_size' ) ){
    	add_image_size( 'tie-small'     ,110,  75,  true );
    	add_image_size( 'tie-medium'    ,310,  165, true );
    	add_image_size( 'tie-large'     ,310,  205, true );
    	add_image_size( 'slider'          ,660,  330, true );
    	add_image_size( 'big-slider'    ,1050, 525, true );
    }

    Как эту функцию переназначить?

    • Andrey
      @

      Вот по этой функции тема: http://wp-kama.ru/function/add_image_size

    • Kama4192

      Переназначить невозможно в данном случае, но можно отключить эти размеры с помощью remove_image_size() и добавить нужные с помощью add_image_size()

      При удалении, используйте какой-нибудь хук, потому что functions.php доч. темы вызывается раньше родительской. А вам нужно вызвать remove_image_size() после объявления. Попробуйте хук init

      1
      • garri832 cайт: clubwp.ru
        @

        Спасибо большое, сделал как вы посоветовали, через хук init и всё сработало.

  • garri832 cайт: clubwp.ru
    @

    А можно как-то из функции переподключить на файл из дочерней темы?

    include_once( get_template_directory() . '/inc/activate-plugins.php' );
    это прописано в родной теме. Знаю можно прописать так
    include_once( get_stylesheet_directory() . '/inc/activate-plugins.php' );
    Будит грузится из дочерней, но как сделать так, что бы это запись не затерлась при обновлении?

    • Kama4192

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

  • Zen

    Еще такой важный момент есть(работает и без него, но при пользовании Loco Translate и подобными, обязателен). При создании дочерней темы нужно обязательно в хедере CSS файла прописывать домен перевода для этой дочерней темы. Иначе у меня отказывался Loco признавать и работать с файлами перевода дочерней темы. Т.е. вордпресс перевод подхватывал, а вот через интерфейс локо я зайти и поменять перевод не мог - он берет домен из CSS.

  • Виталий

    Добрый день.
    Поставил тему Shop Isle. Сделал дочернюю тему. Хотел поправить header, но он подключен странным образом. В functions require get_template_directory() . '/inc/init.php'; а в init пути к файлам. Копирование в дочернюю тему не помогает, просто перекопировать все файлы тогда или как тут поступить?

  • Nika

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

    Ответить2 месяца назад #

Здравствуйте, !

Ваш комментарий