Using Child Themes in WordPress is a great way to modify an existing theme, however the CSS @import
directive is slower than it has to be, so you should try and avoid it. Here’s why.
If it takes 200ms to load the child theme’s stylesheet, and 200ms to load the parent theme’s CSS, a modern web browser should take approximately 200ms to load both of them, because modern browsers load assets in parallel.
Unfortunately this is not true for CSS @import
. Let me quote Google:
The browser must download, parse, and execute first.css before it is able to discover that it needs to download second.css.
Which means that instead of 200ms, with @import
it’ll take the web browser approximately 400ms to load both stylesheets. Here’s a typical child theme’s CSS:
/** * Theme Name: My Child Theme * Template: parent-theme */ @import url(../parent-theme/style.css); /* My Child Theme CSS */
We can drop the @import
statement, and make good use of functions.php and the wp_enqueue_style()
function:
// Faster than @import add_action( 'wp_enqueue_scripts', 'my_child_theme_scripts' ); function my_child_theme_scripts() { wp_enqueue_style( 'parent-theme-css', get_template_directory_uri() . '/style.css' ); }
And we don’t need to re-declare dependencies because the child theme’s functions.php is loaded before the parent theme’s. Unless, of course, the parent theme uses a different action priority, in which case we should just match it.
That’s +1 to our PageSpeed score :)
Wow, kudos to this. I always heard using @import was not the best idea but now I understand the reasoning behind it. You have a great solution. Now what about adding Google Fonts that the spreadsheet requires? Would you suggest enqueueing them too?
Absolutely. Core has a great example of doing it the right way with Open Sans.
I was thinking the same thing and this is how I load all the styles from parent theme now. SUFFIX mean .min files.
I did almost the same with you Sami, enqueing the child theme stylesheet in parent theme.
Hey Sami, thanks for your comment! Doing it from the parent theme is certainly an option, but only if you’re in control of the parent theme itself. Then again, you’ll have to somehow tell your users that there’s no need to reimport or re-enqueue stylesheets when creating a child theme, otherwise they may be loading it twice, especially if they use a different version number in the enqueue function.
In premade child theme style.css there big text: DO NOT USE @IMPORT RULE TO LOAD PARENT THEME STYLES. THEY ARE LOADED AUTOMATICALLY. ENTER YOUR STYLES AFTER THIS COMMENT.
In my opinion this way it’s better because average user don’t have a clue how to add wp_enqueue_style function in their child themes functions.php.
Thanks for the posts Kovshenin,
My very basic skill is front-end web dev, I knew @import is really bad for performance but I thought we should always follow the official guide(codex) to use @import in child theme
Using @import is easier because you don’t have to deal with PHP. I guess that’s the reason why it’s used in the Codex examples in the first place. Also note that the codex is a wiki that anybody could change it, so there’s no guarantee it’s 100% correct.
I just went in to add a note about @import in CSS, turns out somebody already did it last night :) Yey community!
Great advice
Since it’s important for the parent theme’s CSS to get loaded before the child theme’s, does this cause the parent stylesheet to load before the child theme’s stylesheet?
Hey Dave, given that both the parent theme and the child theme enqueue their styles during the same priority in
wp_enqueue_scripts
, your child theme’s stylesheet will be correctly loaded after the parent theme’s.That’s because the child theme’s functions.php is executed before the parent, and we’re loading our parent CSS in the child theme, and our child CSS (with
get_stylesheet_uri()
) in the parent theme (confusing, eh?).You will, however, need to adjust the priority accordingly, if the parent theme runs its
wp_enqueue_script
callbacks at a lower (than 10) priority.That makes sense.
Thanks for the clarification and this great advice. Will be doing it this way from now on!
Excellent solution! I use genesis and I solved it this way:
Nice tip :) Was thinking about it for quite sometime.
i’ve made a post about it, but it is in portuguese: http://origgami.com.br/blog/como-criar-child-themes-no-wordpress-de-forma-otimizada/
I think you are right but you could improve it a little bit, like this:
Like this, you make sure the child style is loaded after the parent.
And it is always a good idea to remove not used fonts from being loaded, like this:
Thanks for your comment Pablo! Re child/parent, as mentioned earlier, the child theme functions.php is executed before the parent theme, which already makes sure the parent CSS is enqueued before the child, but sure, you can take that little extra step.
Also good point about dequeuing/deregistering styles, though I wouldn’t deregister Open Sans because it’s still used by the WordPress Dashboard, admin bar, etc.
Do you think it would be handy if core handles the parent theme loading as well as the child ? This way no action is needed by the user beyond specifying the parent theme.
Not really. It already does handle the loading of both themes, just not style.css. Also, many child themes don’t use the parent theme’s CSS file at all, and build their CSS from scratch.