How to Fix Color Contrast and Text Readability Failures on Your Website
An audit flagged low contrast or text that breaks when zoomed. Learn how contrast is calculated, how to measure it, and how to fix brand colors, overlays and global styles.
You edited a template, a header or theme.json and nothing changed. Learn how block themes layer database overrides over theme files, and how to see which one wins.
You changed the header in Appearance, Editor, clicked Save, and the live site still shows the old header. Or a developer edited parts/header.html or theme.json on the server and nothing moved. Or the Save button seems to work, but when you come back the next day the change is gone, or it shows on some pages and not others.
Block themes build every page from templates and template parts, and WordPress keeps two copies of each one that has ever been edited: the original file in the theme folder and your edited copy in the database. The database copy always wins. Global styles work the same way, with your Site Editor choices layered on top of theme.json. Most “not saving” and “not showing” reports come from editing one layer while a different layer is the one being displayed. This guide shows you how to tell which is which and put things right.
When WordPress renders a page with a block theme, it works out which template the page needs (for example page, single, front-page or home) using the template hierarchy, then looks for that template in this order:
| Priority | Source | Where it lives |
|---|---|---|
| 1 (wins) | Your customized copy | A wp_template or wp_template_part post in the database, tagged with the active theme’s slug |
| 2 | Child theme file | templates/SLUG.html or parts/SLUG.html in the child theme folder |
| 3 | Parent theme file | The same paths in the parent theme folder |
Styles are merged rather than replaced, in four layers: WordPress core defaults, the parent theme’s theme.json, the child theme’s theme.json, and finally your Site Editor Styles changes, which are stored in a single wp_global_styles post per theme (named wp-global-styles-THEMESLUG). A setting in a higher layer overrides the same setting below it. WordPress documentation describes the user layer as a kind of “grandchild” theme that lives in the database.
Three consequences catch people out:
You need an administrator account (the Site Editor requires the edit_theme_options capability). For the database checks you need SSH with WP-CLI, or phpMyAdmin from your hosting panel. Back up the database before resetting or deleting anything, because a reset throws away the customized copy for good unless you export it first.
How to run commands in this guide:
wp-config.php). Your host may name the tool wp or wp-cli.wp-content/themes/THEMESLUG/.This is the most common cause of “my change is not showing”, and it needs no server access.
page-about or category-news) beats the general one.To confirm from the front end, view the page source and look at the body element’s classes. Block themes add classes such as page-template-TEMPLATE_SLUG when a custom template is assigned, and the template part wrappers carry classes such as wp-block-template-part. If the class names a template you did not edit, you have found the cause.
Go to Appearance, Editor, Templates (and Patterns, Template Parts, for headers and footers). Open the three-dot actions menu for an item. A Reset option appears only for templates that have a database copy; if there is no Reset option, the theme file is in use. Older WordPress versions labeled this action Clear customizations. Inside an open template, the same option sits in the three-dot menu at the top of the Template settings sidebar, with a confirmation that reads “Reset to default and clear all customizations”.
wp eval 'foreach ( array( "wp_template", "wp_template_part" ) as $type ) { foreach ( get_block_templates( array(), $type ) as $t ) { echo $type, " ", $t->slug, " source=", $t->source, " theme=", $t->theme, "\n"; } }'
Run this over SSH in the site folder. It asks WordPress the same question the front end does and lists every template and template part with where it comes from. There are no placeholders.
source=theme means the theme file (parent or child) is being used.source=custom means a database copy is overriding the file, or the template only exists in the database because it was created in the Site Editor.theme= shows the theme slug the copy belongs to.If the template you edited in a file shows source=custom, that is why your file edit is invisible. If the template you edited in the Site Editor shows source=theme, your save never reached the database (see Step 6).
wp db query "SELECT p.ID, p.post_type, p.post_name, t.slug AS theme, p.post_modified FROM PREFIX_posts p JOIN PREFIX_term_relationships tr ON tr.object_id = p.ID JOIN PREFIX_term_taxonomy tt ON tt.term_taxonomy_id = tr.term_taxonomy_id AND tt.taxonomy = 'wp_theme' JOIN PREFIX_terms t ON t.term_id = tt.term_id WHERE p.post_type IN ('wp_template','wp_template_part','wp_global_styles') ORDER BY p.post_modified DESC;"
Run this over SSH in the site folder.
PREFIX_ is your database table prefix. Run wp db prefix to get it; on many sites it is wp_, so PREFIX_posts becomes wp_posts.Good output shows rows whose theme column matches your active theme’s folder name (from wp theme list --status=active). Rows tagged with the parent’s slug while a child theme is active are edits that no longer apply, which explains changes that “vanished” after a child theme was activated.
When you want the theme file to win (because a developer updated it, or a theme update fixed something), reset the database copy. In Appearance, Editor, Templates, open the actions menu and choose Reset, or open the template and use Reset from the Template settings sidebar. The template part list works the same way for headers and footers.
Save a copy first if there is anything in the customized version you want to keep:
wp post get TEMPLATE_POST_ID --field=post_content > template-backup-TEMPLATE_SLUG.html
Run this over SSH in the site folder.
TEMPLATE_POST_ID is the ID from the query in Step 2.TEMPLATE_SLUG is the template’s name (the post_name column), used here only to name the file.--field=post_content prints the block markup, which you can paste back into the Code editor view later or hand to a developer to put in the theme file.Good output is a file full of block comments such as <!-- wp:template-part {"slug":"header"} /-->. An empty file means you picked the wrong ID.
After the reset, reload the front end (clear caches as in Step 5). The theme file’s version should now show.
If colors, fonts, spacing or block styles will not change, the same layering applies. A value set in Appearance, Editor, Styles is stored in the wp_global_styles post and beats the same value in theme.json.
theme.json are hidden in the same way.To inspect the user layer directly:
wp post list --post_type=wp_global_styles --post_status=any --fields=ID,post_name,post_modified
wp post get GLOBAL_STYLES_ID --field=post_content | python3 -m json.tool | head -n 60
Run these over SSH in the site folder.
post_name is wp-global-styles-THEMESLUG.GLOBAL_STYLES_ID is the ID of the active theme’s row. python3 -m json.tool pretty-prints the JSON (skip it if Python is not installed) and head -n 60 shows the first 60 lines.A short result such as {"version":3,"isGlobalStylesUserThemeJSON":true} means there are no user overrides, so theme.json is fully in charge. A long result with settings and styles keys shows exactly which values the Site Editor is overriding.
Block themes add a few caches of their own on top of the usual page and browser caches.
?nocache=RANDOM_TEXT, where RANDOM_TEXT is any word. FG-50 covers every cache layer and how to purge them.theme.json over SFTP does not always do so on sites with a persistent object cache (Redis or Memcached). Run wp cache flush over SSH after file edits.On development and staging copies, add define( 'WP_DEVELOPMENT_MODE', 'theme' ); to wp-config.php above the “That’s all, stop editing” line. With this set, WordPress skips its theme.json and pattern caches so file edits show straight away. Do not leave it on in production, where the caches exist for speed.
If the template still shows source=theme after you “saved”, or the editor reports an error, the save did not reach the database.
/wp-json/wp/v2/templates/, /wp-json/wp/v2/template-parts/ or /wp-json/wp/v2/global-styles/. A 200 response means it saved. A 401, 403, 500 or an HTML response instead of JSON means the REST API is being blocked or broken; FG-21 covers that in full, and FG-49 covers 403 blocks from firewalls.A block child theme inherits every parent template and part, plus the parent theme.json. To override one, add a file with the same name in the child, for example templates/single.html or parts/footer.html. The child theme.json only needs the settings you want to change; everything else comes from the parent. FG-90 covers creating child themes and the errors they cause.
Remember the database layer sits above both. If you add a file to the child but the template was customized in the Site Editor while the child was active, the database copy still wins. Reset it to see your child file.
Also check the file name exactly. A child file named template/single.html (missing the “s”) or parts/Header.html (wrong case on a case-sensitive server) is silently ignored.
On sites where a developer maintains the theme, the healthiest arrangement is no long-lived database overrides at all. Periodically move Site Editor changes into the theme, then reset them.
In Appearance, Editor, open the three-dot menu and choose Export under Tools. WordPress downloads a zip of the active theme with your customized templates, template parts and styles merged into the files. Compare it with the theme in version control:
diff -ru THEME_FOLDER_FROM_REPO EXPORTED_THEME_FOLDER
Run this on your own computer (macOS or Linux terminal, or WSL on Windows) after unzipping the export.
THEME_FOLDER_FROM_REPO is your current theme folder, and EXPORTED_THEME_FOLDER is the unzipped export.-r compares folders recursively and -u prints a unified diff with a few lines of context.Lines starting with + exist only in the export (the Site Editor changes). No output means the database adds nothing. Merge what you want into the theme, deploy it, and reset the templates so the files take over.
The official Create Block Theme plugin does the same job from inside WordPress: it can write your Site Editor changes into the active theme’s files and clear the database copies in one go. Use it on staging, because it changes theme files on the server.
Recent WordPress versions keep revisions for templates, template parts, global styles and Navigation menus. If a change went wrong, open the template and look for a revisions entry in its sidebar, or use Styles, Revisions, to step back to a known good state instead of resetting everything.
If part of a template will not change at all, check whether the area is a synced pattern (edits must be made to the pattern itself) or a block with a content lock set by the theme. The List View shows both with distinct icons.
Open a ticket if the Site Editor’s save requests return 403 or 500 errors you cannot trace to a plugin, if you need an older database backup to recover a template that was reset by mistake, or if file edits never appear even after wp cache flush. Include:
For a quick outside check of what visitors see, use our diagnostic tools.
Did this fix it?
Still stuck? Start again from what you can see in the Emergency Room.
Still stuck?
Print a free one-page checklist to keep, or open the Emergency Room if the symptom does not match.
Get the free checklistsKeep reading
Search the field manual
Or jump straight to a symptom
Press / to search from any page, Esc to close