Korrekte Einbindung von Child Theme Styles

Heute schreibe ich über ein Thema, dass ich bereits in früheren Beiträgen schon einmal beschrieben habe. Es geht um die Einbindung der Styles eines Child Themes. Im CODEX wird empfohlen, die style.css über die functions.php Datei einzubinden und nicht mit @import. Der Code hierzu sieht dabei in der Regel wie folgt aus:

add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_styles' );
function my_theme_enqueue_styles() {
	wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );

}

Diese Einbindung kann aber bei einigen Themes zu unerwarteten Problemen führen, wenn man nicht genau weiß, wie die Einbindung von Parent und Child Theme abläuft.

Falsche Ladereihenfolge

Problematisch ist der Code, wenn das Parent Theme nicht nur eine CSS Datei einbindet und die Hauptdatei (style.css) dabei nicht als erstes geladen wird. Als Beispiel hier mal die eingebundenen Dateien aus dem Graphy Theme:

function graphy_scripts() {
	wp_enqueue_style( 'graphy-font',
		esc_url( graphy_fonts_url() ),
		array(),
		null
	);
	wp_enqueue_style( 'genericons',
		get_template_directory_uri() . '/genericons/genericons.css',
		array(),
		'3.4.1'
	);
	wp_enqueue_style( 'normalize',
		get_template_directory_uri() . '/css/normalize.css',
		array(),
		'4.1.1'
	);
	wp_enqueue_style( 'graphy-style',
		get_stylesheet_uri(),
		array(),
		'2.0.4'
	);
	// ... weitere Styles und Scripts
}
add_action( 'wp_enqueue_scripts', 'graphy_scripts' );

Wie ihr sehen könnt, wird hier unter anderem ein „Normalize CSS“ eingebunden. Die meisten Themes enthalten die Angaben hierzu in der style.css Datei, aber manche Theme binden diese Datei separat ein. Diese muss dann natürlich früher geladen werden. Im HTML-Quellcode sieht das wie folgt aus:

<link rel='stylesheet' id='graphy-font-css'
      href='https://fonts.googleapis.com/...'
      type='text/css' media='all' />
<link rel='stylesheet' id='genericons-css'
      href='.../wp-content/themes/graphy/genericons/genericons.css?ver=3.4.1'
      type='text/css' media='all' />
<link rel='stylesheet' id='normalize-css'
      href='.../wp-content/themes/graphy/css/normalize.css?ver=4.1.1'
      type='text/css' media='all' />
<link rel='stylesheet' id='graphy-style-css'
      href='.../wp-content/themes/graphy/style.css?ver=2.0.4'
      type='text/css' media='all' />

Fügen wir nun den Code zur Einbindung des „Parent Style“ wie oben angegeben ein, dann erhalten wir folgenden HTML Code:

<link rel='stylesheet' id='parent-style-css'
      href='.../wp-content/themes/graphy/style.css?ver=4.6.1'
      type='text/css' media='all' />
<link rel='stylesheet' id='graphy-font-css'
      href='https://fonts.googleapis.com/...'
      type='text/css' media='all' />
<link rel='stylesheet' id='genericons-css'
      href='.../wp-content/themes/graphy/genericons/genericons.css?ver=3.4.1'
      type='text/css' media='all' />
<link rel='stylesheet' id='normalize-css'
      href='.../wp-content/themes/graphy/css/normalize.css?ver=4.1.1'
      type='text/css' media='all' />
<link rel='stylesheet' id='graphy-style-css'
      href='.../wp-content/themes/graphy-bp/style.css?ver=2.0.4'
      type='text/css' media='all' />

Da die Einbindung in der functions.php Datei des Child Theme vor der Funktion im Parent Theme ausgeführt wird, wird die style.css Datei des Parent Theme als erstes eingebunden. Dies hat nun also zur Folge, dass das normalize.css später geladen wird und somit Anweisungen auf Parent und Child Theme überschreibt.

Alternative Parent Style Einbindung

Im CODEX wird noch ein anderer Code zur Einbindung des Parent Theme angegeben. Dieser sieht wie folgt aus:

function my_theme_enqueue_styles() {

	$parent_style = 'graphy-style';

	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 ),
		wp_get_theme()->get('Version')
	);
}
add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_styles' );

Binden wird die Parent Styles mit diesem Code ein, dann erhalten wird folgende Reihenfolge im HTML:

<link rel='stylesheet' id='graphy-style-css'
      href='.../wp-content/themes/graphy/style.css?ver=4.6.1'
      type='text/css' media='all' />
<link rel='stylesheet' id='child-style-css'
      href='.../wp-content/themes/graphy-bp/style.css?ver=0.1.0'
      type='text/css' media='all' />
<link rel='stylesheet' id='graphy-font-css'
      href='https://fonts.googleapis.com/...'
      type='text/css' media='all' />
<link rel='stylesheet' id='genericons-css'
      href='.../wp-content/themes/graphy/genericons/genericons.css?ver=3.4.1'
      type='text/css' media='all' />
<link rel='stylesheet' id='normalize-css'
      href='.../wp-content/themes/graphy/css/normalize.css?ver=4.1.1'
      type='text/css' media='all' />

Also auch diese Einbindung funktioniert nicht. Hier werden sogar beide style.css Dateien vor allen anderen Dateien eingebunden. Wie aber können wir die Dateien nun richtig einbinden? Man könnte jetzt vielleicht überlegen, die Priorität der Callback Funktion zu erhöhen, aber das klappt auch nicht, denn dann wird zweimal die style.css des Child Theme eingebunden.

Lösung: Die richtige Ladereihenfolge

Der Trick ist es, die Datei des Parent Theme zu „deregistrieren“ und dabei die Priorität um 1 zu erhöhen. Dies muss nach dem Laden der functions.php Datei des Parent Theme passieren. Der Code muss also wie folgt aussehen:

function my_theme_enqueue_styles() {

	$parent_style = 'graphy-style';

	wp_deregister_style( $parent_style );
	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 ),
		wp_get_theme()->get('Version')
	);
}
add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_styles', 11 );

Wichtig ist hierbei, dass der „Handle“, also der Wert der Variablen $parent_style mit dem Wert des Strings im Parent Theme übereinstimmt. Mit diesem Code erhalten wir dann schließlich folgende Einbindung im HTML:

<link rel='stylesheet' id='graphy-font-css'
      href='https://fonts.googleapis.com/...'
      type='text/css' media='all' />
<link rel='stylesheet' id='genericons-css'
      href='.../wp-content/themes/graphy/genericons/genericons.css?ver=3.4.1'
      type='text/css' media='all' />
<link rel='stylesheet' id='normalize-css'
      href='.../wp-content/themes/graphy/css/normalize.css?ver=4.1.1'
      type='text/css' media='all' />
<link rel='stylesheet' id='graphy-style-css'
      href='.../wp-content/themes/graphy/style.css?ver=4.6.1'
      type='text/css' media='all' />
<link rel='stylesheet' id='child-style-css'
      href='.../wp-content/themes/graphy-bp/style.css?ver=0.1.0'
      type='text/css' media='all' />

Es werden also zuerst die anderen CSS Dateien eingebunden, dann die style.css des Parent Theme und schließlich die style.css des Child Themes. Somit sollte es dann zu keinen Problemen durch eine falsche Reihenfolge mehr kommen.

Fazit

Wir ihr also sehen könnt, gibt es bei der Verwendung von Child Themes und einer „korrekten“ Einbindung der Stylesheets über die functions.php Datei ein paar Fallstricke, die man beachten sollte. Dennoch ist diese Art der Einbindung immer der @import Variante vorzuziehen.

Selbstverständlich wäre es besser, wenn das Parent Theme von vorn herein nicht mehrere Dateien einbinden würde, sondern diese Dateien kombiniert und in einem Request laden würde. Damit würde es zu diesem Problem gar nicht erst kommen 🙂

Veröffentlicht von

Bernhard ist fest angestellter Webentwickler, entwickelt in seiner Freizeit Plugins, schreibt in seinem Blog über WordPress und andere Themen, treibt sich gerne bei den WP Meetups in Berlin und Potsdam herum und läuft nach Feierabend den ein oder anderen Halbmarathon.

6 Kommentare » Schreibe einen Kommentar

  1. Was mach ich denn wenn das parent theme weitere css-dateien per @import lädt.
    Mit deinem Code klappt das super, dass das style.css des child themes genommen wird – alle eingebundenen css-dateien werden aber weiter aus dem parent theme directory geladen.

    • Du möchtest also die CSS-Dateien, die per @import im Parent-Theme geladen werden, mit dem Child-Theme überschreiben? Das ist so ohne weiteres nicht möglich, da ja das Parent-Theme CSS immer geladen wird und damit auch seine @import Befehle.

      Ich würde in einem solchen Fall einfach zusätzliche Dateien anlegen, die dann Eigenschaften aus den importierten Dateien überschreiben oder erweitern. Sollte das zu aufwändig sein, könntest du auf die Einbindung des Parent-Theme verzichten und alle Styles in dein Child-Theme übernehmen. Dann müsstest du aber bei jedem Update nachvollziehen, was sich im Parent-Theme geändert hat.

      Am besten wäre es wohl, dem Autor des Parent-Theme mal nahezulegen, diese schlechte Einbindung mit @import durch saubere wp_enqueue_style Aufrufe zu ersetzen.

  2. Vielen Dank für deinen informativen Artikel! Wenn ich mein Child-Theme aktiviere, sieht die Seite zwar gut aus, aber im vorhandenen Customizer in WordPress funktionieren viele Funktionen nicht mehr. Was kann ich tun, um den Customizer direkt vom Child-Theme aus zu bedienen zu können?

    • Hallo Katharina,

      ein Child-Theme sollte die Funktionalität des Customizers eigentlich nicht beeinflussen. Welches Theme verwendest du denn? Vielleicht liegt darin ein Programmierfehler vor.

      • Hallo Bernhard,

        ich verwende das Theme Juliet. Meine functions-Datei des zugehörigen Child-Themes sieht so aus:
        get(‚Version‘));
        }
        add_action( ‚wp_enqueue_scripts‘, ‚my_theme_enqueue_styles‘, 11 );
        ?>

        Mit dem Child Theme ist die Ladezeit der Seite auch deutlich länger. Und es gibt keine Reaktion, wenn ich z. B. die Featured Posts auf der Front Page an oder ausschalten möchte. Mit dem Theme Kale hängt der Customizer beim Child auch, wie ich gesehen habe ist das aber vom gleichen Programmierer. Kann ich meinen Code für das Child Theme irgendwie anpassen, um die Themes Juliet oder Kale nutzen zu können (auch mit einer brauchbaren Ladezeit)? Die beiden hätten mir nach langem Überlegen nun gefallen 🙂 Oder ist es doch besser, wenn ich mich nochmal nach einem anderen Theme umsehe?

        Danke!
        Katharina

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert