{"id":312881,"date":"2026-05-22T05:44:24","date_gmt":"2026-05-22T05:44:24","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/advanced-block-attributes\/"},"modified":"2026-05-22T06:09:30","modified_gmt":"2026-05-22T06:09:30","slug":"block-attr-customizer","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/block-attr-customizer\/","author":20914112,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0.0","stable_tag":"1.0.0","tested":"6.9.4","requires":"6.0","requires_php":"7.4","requires_plugins":null,"header_name":"HTML Attributes Customizer for Blocks","header_author":"Neeraj","header_description":"Add custom HTML attributes to any Gutenberg block, with optional dynamic variables on the front end.","assets_banners_color":"","last_updated":"2026-05-22 06:09:30","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"https:\/\/profiles.wordpress.org\/neerajk1409\/","rating":0,"author_block_rating":0,"active_installs":0,"downloads":31,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.0":{"tag":"1.0.0","author":"neerajk1409","date":"2026-05-22 06:09:30"}},"upgrade_notice":[],"ratings":[],"assets_icons":[],"assets_banners":[],"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3543840,"resolution":"1","location":"assets","locale":"","width":222,"height":375},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3543840,"resolution":"2","location":"assets","locale":"","width":269,"height":571},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3543840,"resolution":"3","location":"assets","locale":"","width":1919,"height":880}},"screenshots":[]},"plugin_section":[],"plugin_tags":[148857,4121,250433,148076,263909],"plugin_category":[],"plugin_contributors":[263910],"plugin_business_model":[],"class_list":["post-312881","plugin","type-plugin","status-publish","hentry","plugin_tags-block-editor","plugin_tags-blocks","plugin_tags-custom-attributes","plugin_tags-gutenberg","plugin_tags-html-attributes","plugin_contributors-neerajk1409","plugin_committers-neerajk1409"],"banners":[],"icons":{"svg":false,"icon":"https:\/\/s.w.org\/plugins\/geopattern-icon\/block-attr-customizer.svg","icon_2x":false,"generated":true},"screenshots":[{"src":"https:\/\/ps.w.org\/block-attr-customizer\/assets\/screenshot-1.png?rev=3543840","caption":""},{"src":"https:\/\/ps.w.org\/block-attr-customizer\/assets\/screenshot-2.png?rev=3543840","caption":""},{"src":"https:\/\/ps.w.org\/block-attr-customizer\/assets\/screenshot-3.png?rev=3543840","caption":""}],"raw_content":"<!--section=description-->\n<p>HTML Attributes Customizer for Blocks adds an <strong>HTML attributes<\/strong> panel in the block sidebar. Enter one attribute per line as <code>name=\"value\"<\/code> (double quotes), or a boolean attribute as a single name (for example <code>inert<\/code>).<\/p>\n\n<p>Attributes are stored on the block as JSON objects: <code>htmlbacAttributes<\/code> and <code>htmlbacInnerAttributes<\/code> (for example <code>{\"fetchpriority\":\"high\",\"data-nolazy\":\"0\"}<\/code>). Boolean flags use <code>true<\/code>.<\/p>\n\n<p><strong>Merging:<\/strong> Duplicate names on multiple lines are combined. Values merge with spaces (semicolons for <code>style<\/code>). <code>class<\/code> merges with the block\u2019s existing classes instead of replacing them.<\/p>\n\n<p><strong>Variables:<\/strong> Use tokens such as <code>{{post.title}}<\/code> or <code>{{user.auth_status}}<\/code> inside quoted values. They are replaced when the block renders on the front end.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin folder to <code>\/wp-content\/plugins\/block-attr-customizer\/<\/code>.<\/li>\n<li>Activate through <strong>Plugins<\/strong> in WordPress.<\/li>\n<li>Edit a block, open the sidebar, and expand <strong>HTML attributes<\/strong>.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"will%20variables%20work%20in%20the%20editor%20preview%3F\"><h3>Will variables work in the editor preview?<\/h3><\/dt>\n<dd><p>No. The editor shows raw <code>{{\u2026}}<\/code> tokens; replacement runs on the published front end.<\/p><\/dd>\n<dt id=\"can%20i%20add%20my%20own%20variables%3F\"><h3>Can I add my own variables?<\/h3><\/dt>\n<dd><p>Yes. Register a token in the editor reference, resolve it on the front end, then use it in attribute values as <code>{{my.plugin.token}}<\/code>.<\/p>\n\n<p><strong>1. Register the token (shows in the Variables tab):<\/strong><\/p>\n\n<pre><code>add_filter( 'htmlbac_variable_definitions', function ( $definitions ) {\n    $definitions[] = array(\n        'key'         =&gt; 'my.plugin.token',\n        'group'       =&gt; 'other',\n        'description' =&gt; __( 'Example custom token for HTML attributes.', 'my-plugin' ),\n    );\n    return $definitions;\n} );\n<\/code><\/pre>\n\n<p><strong>2. Resolve the token when the block renders:<\/strong><\/p>\n\n<pre><code>add_filter( 'htmlbac_resolve_variable', function ( $value, $key ) {\n    if ( 'my.plugin.token' === $key ) {\n        return esc_attr( 'hello-from-my-plugin' );\n    }\n    return $value;\n}, 10, 2 );\n<\/code><\/pre>\n\n<p><strong>3. Optional \u2014 override the full replacement map in one place:<\/strong><\/p>\n\n<pre><code>add_filter( 'htmlbac_variable_replacements', function ( $replacements ) {\n    $replacements['my.plugin.token'] = esc_attr( 'hello-from-my-plugin' );\n    return $replacements;\n} );\n<\/code><\/pre>\n\n<p>In the block sidebar, add a line such as <code>data-example=\"{{my.plugin.token}}\"<\/code>.<\/p><\/dd>\n<dt id=\"some%20blocks%20have%20an%20%E2%80%9Cinner%20element%E2%80%9D%20field.%20why%3F\"><h3>Some blocks have an \u201cInner element\u201d field. Why?<\/h3><\/dt>\n<dd><p>Blocks such as Group, Image, and Video output an inner <code>div<\/code>, <code>img<\/code>, or <code>video<\/code> that the outer wrapper cannot target. Use <strong>Inner element<\/strong> for those.<\/p>\n\n<p><strong>Enable inner attributes for more blocks (built-in strategies):<\/strong><\/p>\n\n<p>Built-in strategy keys include <code>group_inner<\/code>, <code>first_img<\/code>, <code>first_video<\/code>, <code>first_a<\/code>, <code>first_figure<\/code>, and others. Map a block name to one of those keys:<\/p>\n\n<pre><code>add_filter( 'htmlbac_inner_target_blocks', function ( $strategies ) {\n    $strategies['core\/cover']  = 'first_img';\n    $strategies['core\/button'] = 'first_a';\n    return $strategies;\n} );\n<\/code><\/pre>\n\n<p><strong>Custom strategy (when no built-in key fits):<\/strong><\/p>\n\n<pre><code>add_filter( 'htmlbac_inner_target_blocks', function ( $strategies ) {\n    $strategies['my-plugin\/my-block'] = 'my_first_button';\n    return $strategies;\n} );\n\nadd_filter( 'htmlbac_apply_inner_strategy', function ( $block_content, $entries, $strategy, $block_name ) {\n    if ( 'my_first_button' !== $strategy || 'my-plugin\/my-block' !== $block_name ) {\n        return $block_content;\n    }\n    if ( ! class_exists( 'WP_HTML_Tag_Processor' ) ) {\n        return $block_content;\n    }\n\n    $processor = new WP_HTML_Tag_Processor( $block_content );\n    if ( ! $processor-&gt;next_tag( 'button' ) ) {\n        return $block_content;\n    }\n\n    foreach ( $entries as $entry ) {\n        $name = isset( $entry['name'] ) ? (string) $entry['name'] : '';\n        if ( '' === $name ) {\n            continue;\n        }\n        if ( null === $entry['value'] ) {\n            $processor-&gt;set_attribute( $name, true );\n            continue;\n        }\n        $processor-&gt;set_attribute( $name, (string) $entry['value'] );\n    }\n\n    return $processor-&gt;get_updated_html();\n}, 10, 4 );\n<\/code><\/pre><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release.<\/li>\n<li>HTML attributes panel in the block sidebar with <code>htmlbacAttributes<\/code> and <code>htmlbacInnerAttributes<\/code> (JSON objects).<\/li>\n<li>Merge duplicate attribute names; boolean attributes without <code>=<\/code>.<\/li>\n<li>Dynamic variable tokens on the front end.<\/li>\n<li>Inner element support for blocks such as Group, Image, and Video.<\/li>\n<\/ul>","raw_excerpt":"Add custom HTML attributes to any block, with optional dynamic variables on the front end.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/312881","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=312881"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/neerajk1409"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=312881"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=312881"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=312881"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=312881"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=312881"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=312881"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}