
Table of Contents
Use a WordPress child theme for template overrides and CSS; put features (post types, shortcodes, API calls) in a plugin; never edit parent theme files. Done right: deactivating the plugin removes only features, switching themes keeps content intact, and updating the parent changes nothing you wrote. Verify by running a parent update on staging and confirming your customizations survive.
Comparison: child theme, editing theme, plugin
| Dimension | Child Theme | Editing Parent Theme | Plugin |
|---|---|---|---|
| Survives parent update | Yes | No | Yes |
| Template overrides | Yes (copy file to child) | Yes but lost on update | Limited via hooks |
| Functionality / business logic | Technically yes, wrong practice | Yes, worst practice | Correct place |
| CSS tweaks | style.css or Additional CSS | Lost on update | Enqueue from plugin |
| Rollback effort | Remove child files | Reinstall theme, redo work | Deactivate plugin |
| Use when | Design/layout changes | Never in production | Features independent of theme |
For teams selecting a build partner, our WordPress Theme Development Guide 2026 explains how agencies structure parent and child theme handoffs.
What each breaks
Editing parent theme files directly breaks the update path: the next theme release overwrites wp-content/themes/parent-theme/ and your changes vanish. It also breaks support, since vendors refuse to debug modified core files. A child theme breaks nothing in the parent, but if you copy a template wholesale you inherit bugs from the old version and must re-diff after updates. A badly written plugin breaks sitewide: a fatal error in plugins/my-feature/my-feature.php triggers a white screen because plugins load before themes, so you lose admin access until you rename the folder via SFTP or wp plugin deactivate my-feature with WP-CLI.
How to verify what broke
Enable WP_DEBUG and WP_DEBUG_LOG in wp-config.php:
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', WP_CONTENT_DIR . '/debug.log' );
define( 'WP_DEBUG_DISPLAY', false ); Get a Quote
Email + requirement + budget range — we reply with a quote within 24 hours.
Then tail wp-content/debug.log. If the log shows errors from themes/parent-theme/, you edited the wrong layer. If it shows plugins/, deactivate that plugin first.
Rollback
- Child theme: delete the copied file from
wp-content/themes/parent-theme-child/and the override reverts. - Parent edit: reinstall the theme from wordpress.org or your vendor zip, then move the change into a child or plugin.
- Plugin:
wp plugin deactivate my-featureor rename the directory over SFTP.
Losing code on theme update
Any edit inside wp-content/themes/parent-theme/ is destroyed when the theme updates from version 1.2.3 to 1.3.0 in 2026. The updater replaces the entire directory; only wp-content/themes/parent-theme-child/ and wp-content/uploads/ are untouched. To test, clone to staging, run wp theme update parent-theme, and diff your working tree with git. If your CSS or functions disappear, they were in the wrong place.
Safe process to move edits out
- Create
wp-content/themes/parent-theme-child/style.csswith aTemplate: parent-themeheader. - Enqueue the parent stylesheet in the child
functions.phpusingwp_enqueue_style()withget_template_directory_uri(). - Copy only the template files you must change (for example
single.php) from parent to child and edit there. - Move any
add_action()oradd_filter()that defines features into a small plugin. - Run
wp theme update parent-themeon staging and confirm the child still renders.
This ordered list is the structured step sequence: Step Process to migrate edits safely uses those five steps so both humans and schema parsers see the method.
Functionality belongs in plugins
Features must live in wp-content/plugins/ so they survive theme switches. Register post types with register_post_type(), shortcodes with add_shortcode(), and cron with wp_schedule_event() inside a plugin, never in functions.php. If you switch from Theme A to Theme B and the portfolio section disappears, it was wrongly coupled to the theme. Our Custom Post Types and Taxonomies guide shows how to model that data so it is theme-independent.
Concrete plugin skeleton
<?php
/**
* Plugin Name: Site Features
* Version: 1.0.0
*/
add_action( 'init', function () {
register_post_type( 'case_study', [
'public' => true,
'label' => 'Case Studies',
] );
} );
Activate with wp plugin activate site-features. Verify by going to Posts and seeing Case Studies in admin. Pitfall: wrapping this in a theme check or if ( function_exists( 'x' ) ) from the parent creates dependency; keep it standalone. Rollback: wp plugin deactivate site-features. For hook ordering mistakes that break features, see our hooks priority and removal reference.
Recommended way to change CSS

Put small CSS in the Customizer Additional CSS box (wp-admin/customize.php) or in the child theme style.css. For larger work, enqueue a separate stylesheet from the child functions.php so you control cascade order. Do not edit parent-theme/style.css.
add_action( 'wp_enqueue_scripts', function () {
wp_enqueue_style(
'child-style',
get_stylesheet_directory_uri() . '/assets/css/main.css',
[ 'parent-style' ],
'1.0.0'
);
} );
Verify with browser dev tools: the rule should list main.css and override the parent. Pitfall: missing get_stylesheet_directory_uri() (points to parent) or forgetting the parent handle dependency, so your CSS loads too early. Rollback: remove the enqueue block or empty the file.
Action checklist
- Audit
wp-content/themes/for direct parent edits and move them out. - Create a child theme with
style.cssheader and enqueued assets. - Extract every feature into a plugin under
wp-content/plugins/. - Run
wp theme update parent-themeon staging and confirm nothing is lost. - Keep parent and child in git with separate branches.
Need expert help structuring themes and plugins? See our theme development services for audits, child theme builds and plugin extraction.
Frequently asked questions
Does a child theme slow down my site?
No measurable impact in 2026; the loader does one extra file lookup and stylesheet enqueue, negligible on modern stacks.
Can I put functions.php code in a plugin instead?
Yes, and you should for anything not purely presentational. Use add_action() in the plugin the same way.
What if the parent theme has no hooks?
Copy the template into the child and edit there, or pick a theme that exposes filters; see the official child theme documentation.
