9

This post brings up a few questions I've encountered pertaining to the recent changes around stylesheet enqueueing methods brought up in this thread and this thread.

The issues I encountered came up in a general use-case scenario, using a widely used and well-maintained parent theme that is specifically child-theme ready on a WP 4.0 install. My child theme's functions.php only contains the wp_enqueue_style function as detailed in the Codex.

Please note that while the code referenced below is specific to this theme, much of it uses current coding conventions used by parent themes. Additionally, my areas of concern are most likely duplicatable on a large number of established parent themes currently in the wild. Also, the questions these raise are applicable on a universal level, regardless of which parent theme is being used.

ISSUE 1: Twoqueueing

The Recommended Setup:

Parent theme is enqueueing styles and scripts using the wp_enqueue_scripts hook, the relevent portion being as follows:

add_action('wp_enqueue_scripts', 'parent_theme_function_name');
function parent_theme_function_name() {
    wp_register_style( 'avia-style' ,  $child_theme_url."/style.css", array(),  '2', 'all' );
    wp_enqueue_style( 'avia-base');
    if($child_theme_url !=  $template_url) { wp_enqueue_style( 'avia-style'); }
}

My child theme functions.php enqueues styles per recent codex changes:

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

Note the following IDs as used by the referenced code:

  • id='dm-parent-style-css' is the parent theme's stylesheet, as enqueued by my child theme function
  • id='avia-style-css' is my child theme's stylesheet, as enqueued by the parent theme function
  • id='dm-child-style-css' is my child theme's stylesheet, as enqueued by my child theme function

The Results:

On first glance, everything was fine, with the <head> showing the following order:

<link rel='stylesheet' id='dm-parent-style-css' href='testinstall.dev/wp-content/themes/enfold/style.css?ver=4.0' type='text/css' media='all' />
<!-- Multiple individual parent theme styles here -->
<link rel='stylesheet' id='avia-style-css' href='testinstall.dev/wp-content/themes/child-theme/style.css?ver=2' type='text/css' media='all' />

After installing a plugin, the enqueue order now changed as follows:

<link rel='stylesheet' id='dm-parent-style-css' href='testinstall.dev/wp-content/themes/enfold/style.css?ver=4.0' type='text/css' media='all' />
<!-- Multiple individual parent theme styles here -->
<link rel='stylesheet' id='avia-style-css' href='testinstall.dev/wp-content/themes/child-theme/style.css?ver=2' type='text/css' media='all' />
<!-- Pesky plugin styles -->

Ultimately, I need my child theme's css to load after any plugins, so I was forced to add a priority number to the function in my child theme (see previous discussion regarding priority number).

Because my function only enqueues the parent theme's css, however, the result is that now the parent theme css gets moved to the end, leaving my child theme's css in an even worse predicament than before.

<!-- Multiple individual parent theme styles here -->
<link rel='stylesheet' id='avia-style-css' href='testinstall.dev/wp-content/themes/child-theme/style.css?ver=2' type='text/css' media='all' />
<!-- Pesky plugin styles -->
<link rel='stylesheet' id='dm-parent-style-css' href='testinstall.dev/wp-content/themes/enfold/style.css?ver=4.0' type='text/css' media='all' />

Now I am forced to resort to enqueueing my child theme style as well, to ensure it gets moved back to the front of the line, causing the aforementioned issue of twoqueueing (new term? lol) the child theme css.

The Deprecated Setup:

Revised function in child theme:

add_action( 'wp_enqueue_scripts', 'enqueue_parent_theme_style', 99 );
function enqueue_parent_theme_style() {
    wp_enqueue_style( 'dm-parent-style', get_template_directory_uri().'/style.css' );
    wp_enqueue_style( 'dm-child-style', get_stylesheet_directory_uri().'/style.css' );
}

The Results:

Producing the following order in the <head>:

<!-- Multiple individual parent theme styles here -->
<link rel='stylesheet' id='avia-style-css' href='testinstall.dev/wp-content/themes/child-theme/style.css?ver=2' type='text/css' media='all' />
<!-- Pesky plugin styles -->
<link rel='stylesheet' id='dm-parent-style-css' href='testinstall.dev/wp-content/themes/enfold/style.css?ver=4.0' type='text/css' media='all' />
<link rel='stylesheet' id='dm-child-style-css' href='testinstall.dev/wp-content/themes/child-theme/style.css?ver=2' type='text/css' media='all' />

Even though including the child stylesheet in my function caused it to be enqueued twice, IMHO that is preferable over coding under the assumption that the parent theme will properly enqueue our child stylesheet for us. Based on the ID's assigned to each enqueued style, it appears that the parent theme enqueues it, not anything in WP Core.

My Shivm:

Though I would hardly suggest this be the recommended means (and I'm sure devs with more coding experience than myself will groan at this solution), I dequeued the parent theme's ID (used to enqueue my child theme's style) right above my own enqueue in my child theme's functions file as shown:

add_action( 'wp_enqueue_scripts', 'enqueue_parent_theme_style', 99 );
function enqueue_parent_theme_style() {
    wp_enqueue_style( 'dm-parent-style', get_template_directory_uri().'/style.css' );
    wp_dequeue_style( 'avia-style' );
    wp_enqueue_style( 'dm-child-style', get_stylesheet_directory_uri().'/style.css' );
}

The Results:

This solved the issues at hand, resulting in :

<!-- Multiple individual parent theme styles here -->
<!-- Plugin styles -->
<link rel='stylesheet' id='dm-parent-style-css' href='testinstall.dev/wp-content/themes/enfold/style.css?ver=4.0' type='text/css' media='all' />
<link rel='stylesheet' id='dm-child-style-css' href='testinstall.dev/wp-content/themes/child-theme/style.css?ver=2' type='text/css' media='all' />

Of course, this required knowing the ID used by the parent theme - something more generic would be needed to be used as standard child theme development methodology.

ISSUE 2: Relocated child stylesheets

(It seems hard to believe this hasn't come up in another thread, though I didn't see any specific ones when looking...if I missed it, feel free to bring it to my attention.)

I never use the default style.css in the child theme root directory for my theme styles - it obviously has to be there, but all my actual styles are compiled from SCSS as a minified .css file in a /css/ directory. Although I realize this is not "the expected norm" on a universal level for child theme development, most serious WordPress developers I know do something similar. This, of course, requires manually enqueueing that stylesheet in my function regardless of if the parent theme enqueued it or not.

To sum it all up...

  1. Is it safe to include the assumption that parent themes properly enqueue the child theme styles, from the standpoint of child theme standards?
  2. Removing the priority could potentially create more confusion for part of the WordPress community, when child theme styles start getting overwritten by a plugin. We expect themes to overwrite styles, but not so much with plugins.
  3. When using a custom stylesheet for the actual child theme styles (as supposed to putting them in the predefined style.css), manually enqueueing that file becomes necessary. In terms of maintaining continuity across a wide spectrum of developers, wouldn't it make sense to encourage manually enqueueing the child stylesheet regardless of the possible duplicate?
  • I'm sure there is a debate about how to structure the child-parent-theme relationship. I don't think it is safe to just assume anything about the parent theme. I do personally prefer to manually load styles in a child theme. But, those are decisions you need to make about the nature of the child theme and clearly communicate that. If the child themes are just for simple visual tweaks, then the parent loading the child's stylesheet is probably fine. But if the parent theme is a framework, then I would go towards the child theme loading the stylesheets. – Seamus Leahy Nov 9 '14 at 16:31
5

QUESTION 1

Is it safe to include the assumption that parent themes properly enqueue the child theme styles, from the standpoint of child theme standards?

General rule of thumb, yes. But, you should never assume. Most disasters and failures in live are due to assumptions or facts based on an assumption

FACTS WITHOUT ASSUMPTIONS

  • A child theme's functions.php is loaded first, then the parent's functions.php. This ensures that the the parent theme's main stylesheet is loaded before the child theme's main stylesheet from the updated code in the codex

  • Lets look at the bundled theme, twentytwelve. The magic happens here wp_enqueue_style( 'twentytwelve-style', get_stylesheet_uri() );. This is how the main stylesheet is enqueued. When the theme is active as a parent theme, the style.css will be loaded from the parent theme as get_stylesheet_uri() will be pointed to the parent directory's style.css.

  • When you switch to a child theme, get_stylesheet_uri() "changes" its path to point to the child theme's style.css, meaning now that instead that wp_enqueue_style( 'twentytwelve-style', get_stylesheet_uri() ); loading the parent style.css, it now loads the child style.css

  • All other styles from the parent theme are loaded as per normal in the order that they written

POTHOLES

  • Inline styles and stylesheets that are added directly to your header template. I have done some testing on this issue. If the parent stylesheet is not enqueued using wp_enqueue_scripts and directly loaded in the header, then the child theme's main stylesheet is loaded first. As a workaround here, I have previously recommended to copy the header.php of the parent to the child theme and removing those calls. You will then have to enqueueu both the parent and child theme styles and any other stylesheets that was directly loaded in the header.php as decribed in the OP depreciated function

  • I have came across this once or twice where styles (and scripts) are directly loaded in the header, and because of this the call to wp_head is omitted. This will make you enqueue action fail silently, so your styles will simply not show up.

  • Wrong priorities set. It is not necessary to set priorities is either parent and child actions when you hook your enqueueu functions. When both have the same default priority, the rule of first come, first served apply. This will ensure that the loading order is correct

NOTE TO PARENT THEME AUTHORS

The proper accepted method to add styles and scripts to a theme is through the wp_enqueue_scripts action hook. Never add styles and scripts directly in the header template, and don't set any priority in your action when hooking your function

Always also load the main stylesheet as follows:

wp_enqueue_style( 'twentytwelve-style', get_stylesheet_uri() );

This will ensure that the child's main stylesheet is loaded when a child theme is in use

YOUR RESPONSIBILTY AS A CHILD THEME AUTHOR

  • Take your time and work through the parent theme. Know your parent theme, make sure you are comfortable with the theme structures and how functions and hooks are used in the theme. You cannot create a successful child theme if you don't have inside knowledge of how the parent theme works. It is your responsibilty to make sure that styles and scripts are properly loaded in order for your code to work as expected.

  • Always make the parent theme author alert of any code you are not happy with. For instance, if the author added his styles directly to the header, make him alert of that and make him aware that this is the wrong way of doing it, and ask him to correct this in a future release

QUESTION 2

Removing the priority could potentially create more confusion for part of the WordPress community, when child theme styles start getting overwritten by a plugin. We expect themes to overwrite styles, but not so much with plugins

Unfortunately there are no direct method to safegaurd against this. The point of fact here is, plugin styles should never overwrite default theme styles without the consent of the end user. In my opinion, this is just bad practice or neglet from the plugin author. I would suggest that in a case like this, contact the plugin author and make him alert about this

You also always have the option to dequeue and deregister a style (and script) that you don't need, or which you need to change the priority of and requeueing and reregistering them as in your code above (which is perfectly fine). Just a note on your shivm, it is best practice to dequeue and to deregister a style and script.

QUESTION 3

When using a custom stylesheet for the actual child theme styles (as supposed to putting them in the predefined style.css), manually enqueueing that file becomes necessary. In terms of maintaining continuity across a wide spectrum of developers, wouldn't it make sense to encourage manually enqueueing the child stylesheet regardless of the possible duplicate?

I don't think there is any direct black and white answer to this issue. I would answer by saying, do what you are comfortable with as long as it is within a certain guideline which governs the action.

Stylesheets are not there to add functionality, but are there to add visual experience to the user. Styles are also directly send as-is to the browser were it is processed. Wordpress plays no role here.

Based on this fact, I really don't see any threatening red flags in loading a stylesheet twice. This might cost a few miliseconds in performance though. To be honest, apart from this, I'm not really sure how are duplicates handled across diffirent browsers. This is something that you as a reader can go and test

IMHO, duplicates are never good and should always be avoided. I would suggest that if you really want to manually enqueue the child's main stylesheet for what ever reason, you should make use of your code in your shivm. Dequeue and deregister the duplicate added by default and then requeueing the stylesheet as normal.

Just one thing to remember as well, the enqueue and register functions have a $dependancy parameter that you can also make use of. So it is easy to load a secondary stylesheet and making it dependant on the main stylesheet of your child theme

IN CONCLUSION

Since the recent update of the codex, the feedback has been amazing and I would like to thank everyone's feedback on this. I would like to encourage everyone to participate in any type of feedback to this question in particular. If you have anything to add or comment on, please do.

  • Pieter, thx for your thorough reply. Been swamped today but I have some thoughts based on what you said which I hope to add later this evening. – dMcClintock Nov 10 '14 at 23:07
  • Please do so. I would really like to hear other thoughts on this. My answer is my opinion based on my test, so this is surely not the alpha and omega. Looking forward to your insight :-) – Pieter Goosen Nov 11 '14 at 5:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.