Ein Child-Theme ist eigentlich nichts anderes als eine Kopie des auserkorenen Themes, in dem jedoch nur die eigenen Anpassungen vorhanden sind. Der Rest wird vom eigentlichen Theme hergenommen. So kann dieses nach Belieben Updates erfahren, ohne auf die eigenen Anpassungen achten zu müssen.

Wie erstelle ich ein solches Child-Theme

Das ist einfacher als man denkt. Natürlich braucht es ein klein wenig Erfahrung im Umgang mit HTML, CSS und PHP, da in einem Child-Theme ja die eigentlichen Funktionen des Originalthemes überlagert werden.

Ausgehend davon, dass das Originaltheme den schönen Namen “Demotheme” trägt und demnach auch unter /wp-content/themes/ im Ordner “demotheme” liegt, wird hier nun unter  ein Ordner “demotheme-child” erstellt. Dieser Ordner enthält das spätere Child-Theme. Wichtig ist hier, dass die gleiche Struktur wir im Originaltheme übernommen wird. Also, alles was überlagert werden soll, muss auch im Ordner des Child-Themes vorhanden sein, und zwar in der selben Struktur wie im Original. Dies betrifft sowohl Dateien als auch Ordner.

Child-Theme bei WordPress bekannt machen

Da dies nun soweit geklärt ist, geht es an die wichtigste Datei eines Child-Themes. Die styles.css. Aus dieser Datei liest WordPress alle Informationen zum Theme aus. Hier muss also auch definiert werden, wo sich das Originaltheme befindet. Also sieht die styles.css des Child-Themes im Grundaufbau folgendermaßen aus (Diese Zeilen müssen die ersten Zeilen in der styles.css sein.):

1
2
3
4
5
6
7
8
9
10
11
/*
Theme Name: Child-Theme von "Demotheme"
Theme URI: http: //demotheme.de/
Description: Child-Theme des verwendeten Demothemes.
Author: Name des Autors des Originalthemes (Child-Theme von: Euer Name)
Author URI: URL des Autors
Template: demotheme
Version: 0.1
*/

@charset "UTF-8";
@import url("../demotheme/style.css");

Die Bedeutung dieser Zeilen ist schnell erklärt:

Theme Name
(benötigt) Der Name des Child-Themes

Theme URI
(optional) Die Webseite des Child-Themes

Description
(optional) Eine kurze Beschreibung eures Child-Themes. Ist ganz nett, wenn mehrere Themes installiert sind. So weiß man immer wieso das erstellt wurde.

Author
(optional) Der Autor des Themes. hier wäre es freundlich von euch, wen nihr den Autor des Originalthemes mit nennen würdet. Tut nicht weh, wird auch nirgendwo in WordPress weiter verwendet, ist nur fair dem Autor gegenüber.

Author URI
(optional) Die Webseite des Autors.

Template
(benötigt) Verzeichnis des Originalthemes innerhalb /wp-content/themes/. An dieser Stelle wird definiert, wo sich das Originaltheme befindet. Also in diesem Beispiel “demotheme”.

Version
(optional) Die Version des Child-Themes.

Durch die @import-Regel im CSS wird das CSS des Originalthemes an erster Stelle eingebunden. Somit gehören Änderungen und Erweiterungen am CSS nach diese Zeile. Dies ist der Teil, der etwas CSS-Kenntnisse erfordert :-)

Wenn nun alles richtig gemacht wurde, findet sich im Dashboard unter dem Menüpunkt Design -> Themes nun das Child-Theme. Dies kann an diesem Punkt bereits aktiviert werden. Auffalen wird, dass es für das Child-Theme noch kein Vorschaubildchen gibt. Um dies zu ändern kopiert man einfach die screenshot.png aus dem Originaltheme in das Child-Theme.

Funktionen des Originalthemes überlagern

Da WordPress nun das neue Child-Theme kennt, wird es Zeit die Funktionen zu überlagern. Diese finden sich in der Datei functions.php und somit wird auch innerhalb des Child-Themes diese Datei gebraucht.

Schaut euch am besten zuerst die functions.php des Originalthemes an. Denn ihr könnt nur die Funktionen überlagern, bei denen auch abgefragt wird, ob sie bereits existieren. Ist dies nicht der Fall, kann diese Funktion nicht fehlerfrei überlagert werden, bzw es kann dazu führen, dass ein PHP-Fehler ausgegeben wird. Der Grund dafür liegt in der Hierarchie der Themes. Da das Child-Theme nun zuerst geladen wird, werden auch zuerst dessen Funktionen deklariert. Erst danach wird das Originaltheme mit seinen Funktionen geladen. Sollte hierbei nun versucht werden Funktionen zu laden, die bereits durch das Child-Theme deklariert sind, kommt es zu Fehlern, da eine Funktion nur einmal in PHP deklariert werden kann. Dies ist der Teil der Arbeit, der etwas PHP-Kenntnisse verlangt :-)

Da WordPress diverse Konstanten verwendet, ist es sinnvoll, diese ebenfalls zu verwenden, oder aufbauend auf diesen eigene zu erstellen. TEMPLATEPATH ist zum Beispiel eine solche Konstante. Diese zeigt auf den Pfad des verwendeten Themes, des verwendeten Originalthemes. Daher ist es sinnvoll eine Konstante namens CHILDTHEME_PATH zu erstellen.

1
define('CHILDTHEME_PATH', TEMPLATEPATH . '-child');

Der Vorteil liegt auf der hand. Oftmals beziehen sich Pfadangaben auf den Pfad des Themes. Werden nun Funktionen überlagert, die diese Pfadangaben nutzen um zum Beispiel Hintergrundbilder nicht von Updates überschreiben zu lassen, so sollte im Child-Theme diese Konstante ausgetauscht werden.

Beispiel:

1
$var_sPathHeaderpics = TEMPLATEPATH . '/images/headers';

Sucht im Verzeichnis /images/headers/ des Originalthemes. Soll WordPress nun aber im Verzeichnis des Child-Themes suchen, so muss dieser Aufruf geändert werden in:

1
$var_sPathHeaderpics = CHILDTHEME_PATH . '/images/headers';

Nun wird WordPress dazu veranlasst, durch die neue Konstante, das Verzeichnis /images/headers/ innerhalb des Child-Themes zu suchen.

Ich möchte eine komplette Funktionsünerlagerung nun anhand des der Headerbildfunktion des Grey-Opaque Themes (ab Version 1.3.0) zeigen. Im Original wird eine Funktion greyopaque_custom_header() erstellt, welche die Möglichkeit bietet das Headerbild zu ändern. Dabei wird das Verzeichnis /images/headers/ innerhalb des Themes durchsucht und alle gefundenen Bilder werden aufgelistet.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/**
 * Custom Header Business
 * Now in a seperate function for better override in a child theme.
 *
 * @since Grey Opaque 1.3.0
 */
if(!function_exists('greyopaque_custom_header')) {
    function greyopaque_custom_header() {
        // Your changeable header business starts here
        if(!defined('HEADER_TEXTCOLOR')) {
            define('HEADER_TEXTCOLOR', '');
        }

        // No CSS, just IMG call. The %s is a placeholder for the theme template directory URI.
        if(!defined('HEADER_IMAGE')) {
            define('HEADER_IMAGE', '%s/images/headers/clouds.jpg');
        }

        // The height and width of your custom header. You can hook into the theme's own filters to change these values.
        // Add a filter to greyopaque_header_image_width and greyopaque_header_image_height to change these values.
        define('HEADER_IMAGE_WIDTH', apply_filters('greyopaque_header_image_width', 960));
        define('HEADER_IMAGE_HEIGHT', apply_filters('greyopaque_header_image_height', 200));

        // We'll be using post thumbnails for custom header images on posts and pages.
        // We want them to be 960 pixels wide by 200 pixels tall.
        // Larger images will be auto-cropped to fit, smaller ones will be ignored. See header.php.
        set_post_thumbnail_size(HEADER_IMAGE_WIDTH, HEADER_IMAGE_HEIGHT, true);

        // Don't support text inside the header image.
        if(!defined('NO_HEADER_TEXT')) {
            define('NO_HEADER_TEXT', true);
        }

        // Add a way for the custom header to be styled in the admin panel that controls
        // custom headers. See greyopaque_admin_header_style(), below.
        $array_GreyOPaqueThemeOptions = greyopaque_get_theme_options('greyopaque-options');
        if(isset($array_GreyOPaqueThemeOptions['show-headerimage']) && $array_GreyOPaqueThemeOptions['show-headerimage'] == 'on') {
            add_custom_image_header('', 'greyopaque_admin_header_style');
        }

        // ... and thus ends the changeable header business.

        // Default custom headers packaged with the theme. %s is a placeholder for the theme template directory URI.
        /**
         * Checking for headerimages.
         *
         * @since Grey Opaque 1.0.0
         */
        $var_sPathHeaderpics = TEMPLATEPATH . '/images/headers';
        $var_sType = 'file';
        $var_bRecursive = false;
        $array_headerImagesList = greyopaque_scan_directory($var_sPathHeaderpics, $var_sType, $var_bRecursive);
        $array_Headers = array();

        if(is_admin()) {
            for($count_i = 0; count($array_headerImagesList) > $count_i; $count_i++) {
                if(!strstr($array_headerImagesList[$count_i], '-thumbnail')) {
                    $array_HeaderImageParts = explode('.', $array_headerImagesList[$count_i]);

                    // do we have a thumbnail?
                    if(in_array($array_HeaderImageParts['0'] . '-thumbnail.' . $array_HeaderImageParts['1'], $array_headerImagesList)) {
                        $array_Headers[$array_HeaderImageParts['0']] = array(
                            'url' => '%s/images/headers/' . $array_HeaderImageParts['0'] . '.' . $array_HeaderImageParts['1'],
                            'thumbnail_url' => '%s/images/headers/' . $array_HeaderImageParts['0'] . '-thumbnail.' . $array_HeaderImageParts['1'],
                            'description' => $array_headerImagesList[$count_i]
                        );
                    }
                } else {
                    continue;
                }
            }
        }

        register_default_headers($array_Headers);
    }

    add_action('after_setup_theme', 'greyopaque_custom_header');
}

Wie nun in der Zeile 7 zu erkennen ist, wird hier explizit geprüft, ob diese Funktion bereits deklariert wurde. Da diese Prüfung stattfindet, kann diese Funktion auch gefahrlos überlagert werden. In Zeile 49 findet sich die Konstante TEMPLATEPATH, welche im Child-Theme geändert werden muss. Im Child-Theme sähe die Funktion demnach wie folgt aus:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/**
 * Custom Header Business
 * Diese Funktion überlagert die gleichnamige Funktion des Originalthemes.
 *
 * @since Grey Opaque 1.3.0
 */
if(!function_exists('greyopaque_custom_header')) {
    function greyopaque_custom_header() {
        // Your changeable header business starts here
        if(!defined('HEADER_TEXTCOLOR')) {
            define('HEADER_TEXTCOLOR', '');
        }

        // No CSS, just IMG call. The %s is a placeholder for the theme template directory URI.
        if(!defined('HEADER_IMAGE')) {
            define('HEADER_IMAGE', '%s/images/headers/clouds.jpg');
        }

        // The height and width of your custom header. You can hook into the theme's own filters to change these values.
        // Add a filter to greyopaque_header_image_width and greyopaque_header_image_height to change these values.
        define('HEADER_IMAGE_WIDTH', apply_filters('greyopaque_header_image_width', 960));
        define('HEADER_IMAGE_HEIGHT', apply_filters('greyopaque_header_image_height', 200));

        // We'll be using post thumbnails for custom header images on posts and pages.
        // We want them to be 960 pixels wide by 200 pixels tall.
        // Larger images will be auto-cropped to fit, smaller ones will be ignored. See header.php.
        set_post_thumbnail_size(HEADER_IMAGE_WIDTH, HEADER_IMAGE_HEIGHT, true);

        // Don't support text inside the header image.
        if(!defined('NO_HEADER_TEXT')) {
            define('NO_HEADER_TEXT', true);
        }

        // Add a way for the custom header to be styled in the admin panel that controls
        // custom headers. See greyopaque_admin_header_style(), below.
        $array_GreyOPaqueThemeOptions = greyopaque_get_theme_options('greyopaque-options');
        if(isset($array_GreyOPaqueThemeOptions['show-headerimage']) && $array_GreyOPaqueThemeOptions['show-headerimage'] == 'on') {
            add_custom_image_header('', 'greyopaque_admin_header_style');
        }

        // ... and thus ends the changeable header business.

        // Default custom headers packaged with the theme. %s is a placeholder for the theme template directory URI.
        /**
         * Checking for headerimages.
         *
         * @since Grey Opaque 1.0.0
         */
        $var_sPathHeaderpics = CHILDTHEME_PATH . '/images/headers';
        $var_sType = 'file';
        $var_bRecursive = false;
        $array_headerImagesList = greyopaque_scan_directory($var_sPathHeaderpics, $var_sType, $var_bRecursive);
        $array_Headers = array();

        if(is_admin()) {
            for($count_i = 0; count($array_headerImagesList) > $count_i; $count_i++) {
                if(!strstr($array_headerImagesList[$count_i], '-thumbnail')) {
                    $array_HeaderImageParts = explode('.', $array_headerImagesList[$count_i]);

                    // do we have a thumbnail?
                    if(in_array($array_HeaderImageParts['0'] . '-thumbnail.' . $array_HeaderImageParts['1'], $array_headerImagesList)) {
                        $array_Headers[$array_HeaderImageParts['0']] = array(
                            'url' => '%s/images/headers/' . $array_HeaderImageParts['0'] . '.' . $array_HeaderImageParts['1'],
                            'thumbnail_url' => '%s/images/headers/' . $array_HeaderImageParts['0'] . '-thumbnail.' . $array_HeaderImageParts['1'],
                            'description' => $array_headerImagesList[$count_i]
                        );
                    }
                } else {
                    continue;
                }
            }
        }

        register_default_headers($array_Headers);
    }

    add_action('after_setup_theme', 'greyopaque_custom_header');
}

Im Prinzip ist es eine 1:1 Kopie der Funktion aus dem Originaltheme, jedoch mit einer kleinen Änderung in Zeile 49. hier wird die neue Konstante CHILDTHEME_PATH verwendet. Nun sucht WordPress die Headerbilder innerhalb des Verzeichnisses des Child-Themes.

Auf diese Art und Weise kann jede Funktion eines Themes durch ein Child-Theme überlagert werden. Einzige Voraussetzung ist, es wird im Originaltheme geprüft, ob diese Funktion bereits deklariert wurde.

Überlagern von Templates

Dies funktioniert genau so wie bei den Funktionen. Das Template welches überlagert werden soll, wird einfach aus dem Originaltheme in das Child-Theme kopiert. Hierbei ist zu beachten, dass die Ordnerstruktur erhalten bleibt. Mit anderen Worten, das Template muss im Child-Theme an genau der selben Stelle liegen wie auch im Originaltheme. Nun kann das Template nach Belieben angepasst werden, denn WordPress erkennt, ob ein Template bereits vorhanden ist und versucht dieses nicht noch einmal zu laden. Dadurch wird das entsprechende Template im Originaltheme schlichtweg ignoriert. Dies ist der Teil, der einige HTML-Kenntnisse erfordert :-)

Fazit

Child-Themes sind ein recht einfacher und durchaus sicherer Weg, ein Theme anzupassen, ohne Angst haben zu müssen, dass die Anpassungen bei einen Update des Themes gleich wieder flöten gehen. Und wer sich nicht so richtig traut, dem kann ich nur sagen, keine Angst, durch ein Child-Theme könnt ihr euch euer Originaltheme nicht kaputt machen, denn in dem wird ja nichts geändert und es kann notfalls schnell wieder über das Dashboard aktiviert werden.

Dennoch gilt auch hier – wie eigentlich bei allen Änderungen und Erweiterungen – immer erst auf einer Testumgebung alles ausgiebig testen und schauen, ob auch alles so läuft wie man es haben will.

Ich wünsche euch viel Spaß!

Artikel / Seite weiterempfehlen

3 Meinungen zu “WordPress: Child-Theme erstellen

  1. Tolle Wurst – 2 Wochen nachdem ich mich mühselig durch die off. Anleitung gewurschtet hab, kommst du nun mit dieser super nachvollziehbaren einfachen Anleitung um die Ecke *gnarf*
    Dennoch, danke dafür – so den einen oder anderen “Trick” werd ich wohl nun doch noch (anders) umsetzen – besten Dank dafür :-)

  2. Hallo H.-Peter,

    vielen Dank für die Anleitung – die habe sogar ich verstanden. :-)

    Soeben habe ich meinen Blog ebenfalls auf ein “Child Theme” umgestellt, und es scheint alles zu funktionieren.

    LG
    Martina

Hinterlasse eine Antwort

Ihre Email-Adresse wird nicht veröffentlicht. Pflichtfelder sind durch * markiert.

Sie können folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>