{"id":125119,"date":"2026-08-05T06:49:35","date_gmt":"2026-08-05T06:49:35","guid":{"rendered":"https:\/\/make.wordpress.org\/core\/?p=125119"},"modified":"2026-08-05T06:49:35","modified_gmt":"2026-08-05T06:49:35","slug":"pseudo-and-custom-style-states-in-wordpress-7-1","status":"publish","type":"post","link":"https:\/\/make.wordpress.org\/core\/2026\/08\/05\/pseudo-and-custom-style-states-in-wordpress-7-1\/","title":{"rendered":"Pseudo and custom style states in WordPress 7.1"},"content":{"rendered":"<h2 class=\"wp-block-heading\">Pseudo states<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In WordPress 7.1, users have more power over styling the pseudo states of blocks. Currently limited to the Button and Navigation Link blocks, users are able to apply styles to \u2018hover\u2019, \u2018focus\u2019, \u2018focus-visible\u2019 and \u2018active\u2019 states. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Pseudo states support definitions in theme.<span tabindex='0' class='glossary-item-container'>json<span class='glossary-item-hidden-content'><span class='glossary-item-header'>JSON<\/span> <span class='glossary-item-description'>JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML.<\/span><\/span><\/span> for themers, and <span tabindex='0' class='glossary-item-container'>block<span class='glossary-item-hidden-content'><span class='glossary-item-header'>Block<\/span> <span class='glossary-item-description'>Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience.<\/span><\/span><\/span> styling in global styles and on block instances for users.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Defining pseudo states for blocks in theme.json <\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Define pseudo states within the block object using the properties \u201c:hover\u201d, \u201c:focus\u201d, \u201c:focus-visible\u201d, and \u201c:active\u201d. Pseudo state names are always prefixed with a <code>:<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"json\" class=\"language-json\">\"styles\": {\n\t\"blocks\": {\n\t\t\"core\/button\": {\n\t\t\t\"color\": {\n\t\t\t\t\"background\": \"black\",\n\t\t\t\t\"text\": \"white\"\n\t\t\t},\n\t\t\t\":hover\": {\n\t\t\t\t\"color\": {\n\t\t\t\t\t\"background\": \"blue\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\":focus\": {\n\t\t\t\t\"color\": {\n\t\t\t\t\t\"background\": \"purple\"\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Pseudo states can also be nested within responsive states:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"json\" class=\"language-json\">\"styles\": {\n\t\"blocks\": {\n\t\t\"core\/button\": {\n\t\t\t\"@mobile\": {\n\t\t\t\t\":hover\": {\n\t\t\t\t\t\"color\": {\n\t\t\t\t\t\t\"background\": \"var:preset|color|contrast\",\n\t\t\t\t\t\t\"text\": \"var:preset|color|base\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Block instance attributes<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The structure for block instance attributes is very similar to the theme.json definition with <code>:hover<\/code> properties used inside the <code>style<\/code> attribute:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"markup\" class=\"language-markup\">&lt;!-- wp:button {\"backgroundColor\":\"accent-3\",\"style\":{\":hover\":{\"color\":{\"background\":\"var:preset|color|accent-2\"}}}} --&gt;\n&lt;div class=\"wp-block-button\"&gt;&lt;a class=\"wp-block-button__link has-accent-3-background-color has-background wp-element-button\"&gt;Button with pseudo state background&lt;\/a&gt;&lt;\/div&gt;\n&lt;!-- \/wp:button --&gt;<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Custom style states<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Custom states are an early feature limited to theme.json definition only (no user facing features are exposed) and only the navigation link block. The navigation block uses this to allow styling of the current menu item \u2013 that is the menu item whose link matches that of the currently viewed page.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Defining custom states for the navigation link block in theme.json<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Styles for the current menu item can be defined using the <code>-current<\/code> property. Custom states always use the <code>-<\/code>prefix.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"json\" class=\"language-json\">\"styles\": {\n\t\"blocks\": {\n\t\t\"core\/navigation-link\": {\n\t\t\t\"-current\": {\n\t\t\t\t\"color\": {\n\t\t\t\t\t\"text\": \"var:preset|color|contrast\"\n\t\t\t\t},\n\t\t\t\t\":hover\": {\n\t\t\t\t\t\"color\": {\n\t\t\t\t\t\t\"text\": \"var:preset|color|accent-1\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">As shown above, pseudo states can be nested within custom states. Custom states can also be nested within responsive states.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Style generation<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The styles defined for custom states generate css that targets a class name selector. For the navigation link block, that would expand to something like <code>.wp-block-navigation-link .current-menu-item { \/\/ styles ... }<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The styles css class name that\u2019s generated in the selector would be declared on supported blocks via a block\u2019s block.json <code>selectors<\/code> property:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"json\" class=\"language-json\">\"selectors\": {\n\t\"states\": {\n\t\t\"-current\": \".wp-block-navigation-link .current-menu-item\"\n\t}\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Opting out of style state editing<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Sites can prevent users from styling block states via the <code>blockStatesEditingEnabled<\/code> editor setting:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"php\" class=\"language-php\">function example_disable_block_states_editing( $settings ) {\n\t$settings['blockStatesEditingEnabled'] = false;\n\treturn $settings;\n}\nadd_filter( 'block_editor_settings_all', 'example_disable_block_states_editing' );<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>blockStatesEditingEnabled<\/code> defaults to <code>true<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When it is <code>false<\/code>, both the state dropdown in the block inspector\u2019s block card, and the pseudo state options in the \u201cStates\u201d dropdown in Global Styles under Styles &gt; Blocks are hidden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The states affected are the pseudo states, Hover, Focus, Focus-visible and Active, which currently apply to the Button and Navigation Link blocks. In the future this will extend to other states present in the dropdown, like the ability for users to set styles for the Navigation Link\u2019s \u2018Current\u2019 state.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This setting does not affect viewport states. Those are controlled separately by <code>responsiveEditingEnabled<\/code>. Set both to <code>false<\/code> to remove the state editing interface entirely.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The setting governs the editing interface only. State styles already saved in <code>theme.json<\/code>, in Global Styles, or in a block\u2019s <code>style<\/code> attribute are left untouched and are still applied, so existing content renders exactly as before both in the Editor and on the front end.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Reviewed by <a href=\"https:\/\/profiles.wordpress.org\/ramonopoly\/\" class=\"mention\"><span class=\"mentions-prefix\">@<\/span>ramonopoly<\/a>, <a href=\"https:\/\/profiles.wordpress.org\/andrewserong\/\" class=\"mention\"><span class=\"mentions-prefix\">@<\/span>andrewserong<\/a>; props <a href=\"https:\/\/profiles.wordpress.org\/wildworks\/\" class=\"mention\"><span class=\"mentions-prefix\">@<\/span>wildworks<\/a><\/p>\n<p class=\"o2-appended-tags\"><a href=\"https:\/\/make.wordpress.org\/core\/tag\/7-1\/\" class=\"tag\"><span class=\"tag-prefix\">#<\/span>7-1<\/a>, <a href=\"https:\/\/make.wordpress.org\/core\/tag\/dev-notes\/\" class=\"tag\"><span class=\"tag-prefix\">#<\/span>dev-notes<\/a>, <a href=\"https:\/\/make.wordpress.org\/core\/tag\/dev-notes-7-1\/\" class=\"tag\"><span class=\"tag-prefix\">#<\/span>dev-notes-7-1<\/a><\/p><nav class='o2-post-footer-actions'><ul class='o2-post-footer-action-row'><li class='o2-post-footer-action'><a href=\"https:\/\/login.wordpress.org\/?redirect_to=https%3A%2F%2Fmake.wordpress.org%2Fcore%2F2026%2F08%2F05%2Fpseudo-and-custom-style-states-in-wordpress-7-1%2F%23respond&#038;locale=en_US\" title=\"Login to Reply\"  class=\"genericon  genericon-reply\"  data-action=\"login-to-reply\"  data-actionstate=\"default\" >Login to Reply<\/a><\/li><\/ul><div class='o2-post-footer-action-likes'><\/div><ul class='o2-post-footer-action-row'><\/ul><\/nav>","protected":false},"excerpt":{"rendered":"<p>Pseudo states In WordPress 7.1, users have more power over styling the pseudo states of blocks. Currently limited to the Button and Navigation Link blocks, users are able to apply styles to \u2018hover\u2019, \u2018focus\u2019, \u2018focus-visible\u2019 and \u2018active\u2019 states. Pseudo states support definitions in theme.jsonJSON JSON, or JavaScript Object Notation, is a minimal, readable format for [&hellip;]<\/p>\n","protected":false},"author":16239218,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"jetpack_seo_schema_type":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[1175],"tags":[5885,1443,5894],"class_list":["post-125119","post","type-post","status-publish","format-standard","hentry","category-general","tag-7-1","tag-dev-notes","tag-dev-notes-7-1","mentions-andrewserong","mentions-ramonopoly","mentions-wildworks","author-talldanwp"],"revision_note":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2AvED-wy3","jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/posts\/125119","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/users\/16239218"}],"replies":[{"embeddable":true,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/comments?post=125119"}],"version-history":[{"count":6,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/posts\/125119\/revisions"}],"predecessor-version":[{"id":125311,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/posts\/125119\/revisions\/125311"}],"wp:attachment":[{"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/media?parent=125119"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/categories?post=125119"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/tags?post=125119"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}