{"id":249575,"date":"2026-01-09T08:59:30","date_gmt":"2026-01-09T08:59:30","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/blockglow-per-block-custom-css\/"},"modified":"2026-05-11T17:54:04","modified_gmt":"2026-05-11T17:54:04","slug":"blockglow","status":"publish","type":"plugin","link":"https:\/\/br.wordpress.org\/plugins\/blockglow\/","author":23123447,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.2.0","stable_tag":"1.2.0","tested":"6.8.5","requires":"5.8","requires_php":"8.2","requires_plugins":null,"header_name":"BlockGlow \u2014 Per-block Custom CSS","header_author":"Mary Rose Elbambo","header_description":"Extend every block with a \"Custom CSS\" inspector field. CSS is scoped to the block instance and printed on the front-end.","assets_banners_color":"3f4e65","last_updated":"2026-05-11 17:54:04","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/wordpress.org\/plugins\/blockglow\/","header_author_uri":"https:\/\/profiles.wordpress.org\/eltresse93\/","rating":0,"author_block_rating":0,"active_installs":0,"downloads":285,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.1.6":{"tag":"1.1.6","author":"eltresse93","date":"2026-01-09 11:11:35"},"1.1.7":{"tag":"1.1.7","author":"eltresse93","date":"2026-01-11 07:50:00"},"1.2.0":{"tag":"1.2.0","author":"eltresse93","date":"2026-05-11 17:54:04"}},"upgrade_notice":{"1.0.0":"<p>First release.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3435790,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3435790,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3435790,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3435790,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.1.6","1.1.7","1.2.0"],"block_files":[],"assets_screenshots":[],"screenshots":{"1":"Inspector panel showing the CodeEditor or fallback textarea.","2":"Live editor preview demonstrating scoped styles.","3":"Example front-end output with linked per-block stylesheet."}},"plugin_section":[],"plugin_tags":[4121,356,2001,1332,148076],"plugin_category":[46,59],"plugin_contributors":[253640],"plugin_business_model":[],"class_list":["post-249575","plugin","type-plugin","status-publish","hentry","plugin_tags-blocks","plugin_tags-css","plugin_tags-custom-css","plugin_tags-editor","plugin_tags-gutenberg","plugin_category-editor-and-writing","plugin_category-utilities-and-tools","plugin_contributors-eltresse93","plugin_committers-eltresse93"],"banners":{"banner":"https:\/\/ps.w.org\/blockglow\/assets\/banner-772x250.png?rev=3435790","banner_2x":"https:\/\/ps.w.org\/blockglow\/assets\/banner-1544x500.png?rev=3435790","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/blockglow\/assets\/icon-128x128.png?rev=3435790","icon_2x":"https:\/\/ps.w.org\/blockglow\/assets\/icon-256x256.png?rev=3435790","generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p>BlockGlow adds a \"BlockGlow \u2014 Custom CSS\" panel to the inspector of every block. Use it to scope custom CSS to a single block instance. The plugin stores CSS in the uploads folder (under uploads\/blockglow\/) and enqueues the generated CSS file when rendering on the front end. If the uploads directory isn't writable or file write fails, BlockGlow will fall back to outputting inline styles.<\/p>\n\n<p>Key features:<\/p>\n\n<ul>\n<li>Adds two block attributes to every block: <code>blockglowCustomCSS<\/code> and <code>blockglowId<\/code>.<\/li>\n<li>Inspector panel with a CodeMirror-backed code editor (if WordPress provides it) or a fallback textarea supporting Tab and Shift+Tab outdent.<\/li>\n<li>Live preview inside the block editor: custom CSS is scoped to the block in the editor so you can see the effect while editing.<\/li>\n<li>CSS files are saved to <code>wp-content\/uploads\/blockglow\/blockglow-&lt;id&gt;.css<\/code> and enqueued on the front end as a linked stylesheet; files are removed automatically when you clear the Custom CSS field.<\/li>\n<li>Graceful fallback to inline styles when file writing isn't possible.<\/li>\n<\/ul>\n\n<p>How scoping works:<\/p>\n\n<p>BlockGlow creates a unique <code>blockglowId<\/code> for each block instance and scopes your CSS with a wrapper selector like:<\/p>\n\n<pre><code>[data-blockglow-id=\"bg-xxxxxxx\"] { \/* your declarations *\/ }\n<\/code><\/pre>\n\n<p>For convenience you can use <code>&amp;<\/code> as the wrapper shorthand in the editor. Example:<\/p>\n\n<pre><code>&amp; .my-class { color: red; }\n<\/code><\/pre>\n\n<p>The plugin will replace <code>&amp;<\/code> with the wrapper selector for both editor preview and front-end output.<\/p>\n\n<h3>Arbitrary section<\/h3>\n\n<p>Development notes:<\/p>\n\n<ul>\n<li>Editor script: <code>assets\/js\/blockglow-editor.js<\/code> \u2014 registers attributes, provides the inspector panel and injects editor-scoped styles.<\/li>\n<li>Main plugin file: <code>blockglow.php<\/code> \u2014 enqueues editor assets and filters <code>render_block<\/code> to attach per-block CSS files or inline styles.<\/li>\n<li>Upload path: <code>wp_upload_dir()<\/code> + <code>\/blockglow\/<\/code>.<\/li>\n<li>File writes\/deletes: BlockGlow uses the WordPress Filesystem API (WP_Filesystem) when available for compatibility with hosts using FTP\/SFTP; when unavailable it will attempt direct writes. Editing capability is required (edit_posts) or operations performed via REST save.<\/li>\n<li>Per-post bundling: BlockGlow now generates a single stylesheet per post (<code>blockglow-post-&lt;ID&gt;.css<\/code>) on post save which contains the combined CSS from all blocks in that post. This reduces HTTP requests and improves performance.<\/li>\n<li>Admin UI: A new submenu under Tools \u2192 \"BlockGlow CSS\" lists generated files and allows administrators (capability is filterable) to delete them.<\/li>\n<li>Capability: File generation\/deletion is restricted by a filterable capability <code>blockglow_manage_files_cap<\/code> (default <code>manage_options<\/code>). You can change this capability via the filter if you want other roles to manage files.<\/li>\n<li>If you'd like help preparing the plugin for WordPress.org (example <code>readme.txt<\/code> adjustments, SVN packaging, or adding screenshots), ping me and I can prepare the required assets and instructions.<\/li>\n<\/ul>\n\n<h3>Source Code<\/h3>\n\n<p>The plugin includes built\/minified assets under <code>assets\/dist\/<\/code> for distribution. The human-readable source for JavaScript is included in the plugin under <code>assets\/js\/<\/code> (e.g. <code>assets\/js\/blockglow-editor.js<\/code> and <code>assets\/js\/blockglow-admin.js<\/code>). The plugin also contains a <code>package.json<\/code> and <code>vite.config.js<\/code> in the plugin root describing how to rebuild these assets locally using <code>npm install<\/code> and <code>npm run build<\/code> or <code>npm run watch<\/code>.<\/p>\n\n<p>If you need the sources to be hosted externally, provide a URL and I will add it here (for example an upstream GitHub repository).<\/p>\n\n<h3>Installation Notes for WordPress.org<\/h3>\n\n<p>To publish on WordPress.org you will need:<\/p>\n\n<ul>\n<li>A fully-formed <code>readme.txt<\/code> (this file) using the plugin directory readme format.<\/li>\n<li>Screenshots (1.png, 2.png, etc.) placed in the assets\/ directory when committing to SVN, or uploaded via the plugin admin UI after publishing.<\/li>\n<li>A stable tag or commit to <code>trunk\/<\/code> in SVN. Typical workflow:\n\n<ol>\n<li>Create a new plugin slug on https:\/\/wordpress.org\/plugins\/ and follow the email to get SVN access.<\/li>\n<li>Check out the plugin SVN repository, add your plugin files into <code>trunk\/<\/code>, put screenshots into <code>assets\/<\/code>, and tag a version.<\/li>\n<li>Commit and wait for the plugin page to become live.<\/li>\n<\/ol><\/li>\n<\/ul>\n\n<h3>Support<\/h3>\n\n<p>If you find issues or want improvements (for example: limiting who can edit per-block CSS, collecting styles into a single head include, or adding an admin UI to manage generated CSS files), open an issue in the repository or reply here and I will assist.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the <code>blockglow<\/code> folder to the <code>\/wp-content\/plugins\/<\/code> directory.<\/li>\n<li>Activate the plugin through the 'Plugins' menu in WordPress.<\/li>\n<li>Ensure the uploads folder is writable by WordPress so BlockGlow can create <code>wp-content\/uploads\/blockglow\/<\/code> and write CSS files. If uploads aren't writable, the plugin will still work but will output inline styles instead of linked CSS files.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"where%20are%20the%20css%20files%20stored%3F\"><h3>Where are the CSS files stored?<\/h3><\/dt>\n<dd><p>Files are stored in <code>wp-content\/uploads\/blockglow\/<\/code> and are named like <code>blockglow-&lt;id&gt;.css<\/code>.<\/p><\/dd>\n<dt id=\"will%20the%20css%20affect%20other%20blocks%20or%20pages%3F\"><h3>Will the CSS affect other blocks or pages?<\/h3><\/dt>\n<dd><p>No \u2014 BlockGlow scopes the CSS to the block instance using a data attribute. If you write global selectors inside the editor (for example <code>body { ... }<\/code>), those will still be global \u2014 be careful.<\/p><\/dd>\n<dt id=\"how%20do%20i%20delete%20generated%20css%20files%3F\"><h3>How do I delete generated CSS files?<\/h3><\/dt>\n<dd><p>If you clear the Custom CSS field in the block inspector and update the post\/page, the plugin will attempt to delete the corresponding CSS file automatically.<\/p><\/dd>\n<dt id=\"what%20if%20the%20code%20editor%20%28codemirror%29%20doesn%27t%20appear%3F\"><h3>What if the Code Editor (CodeMirror) doesn't appear?<\/h3><\/dt>\n<dd><p>Some WordPress setups don't expose the <code>wp.components.CodeEditor<\/code> component. In that case BlockGlow falls back to a textarea with Tab\/Shift+Tab support.<\/p><\/dd>\n<dt id=\"is%20there%20any%20capability%20check%3F\"><h3>Is there any capability check?<\/h3><\/dt>\n<dd><p>At present BlockGlow does not add extra capability checks beyond the normal block editing capabilities. If you need a role-based restriction, consider adding custom checks or ask for an enhancement.<\/p><\/dd>\n<dt id=\"is%20this%20safe%20for%20production%3F\"><h3>Is this safe for production?<\/h3><\/dt>\n<dd><p>BlockGlow only writes CSS files and outputs styles. It's recommended to review custom CSS and limit who can edit posts\/pages. This plugin does not sanitize arbitrary CSS; it persists whatever CSS you enter. Restrict editor access as needed.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.2.0<\/h4>\n\n<ul>\n<li>Performance: Added a new Performance Optimization tab in the admin dashboard.<\/li>\n<li>Performance: Added support for preloading the LCP image and applying <code>fetchpriority=\"high\"<\/code> to improve Largest Contentful Paint (LCP) performance and page loading speed.<\/li>\n<\/ul>\n\n<h4>1.1.6<\/h4>\n\n<ul>\n<li>Update: Create new blockglowId when a block is duplicated or copied.<\/li>\n<li>Update: Added pagination and multiple select to delete CSS files in Block Glow page in backend.  <\/li>\n<\/ul>\n\n<h4>1.1.5<\/h4>\n\n<ul>\n<li>Admin: Fixed the nonce issue.<\/li>\n<\/ul>\n\n<h4>1.1.4<\/h4>\n\n<ul>\n<li>Admin: Removed the CSS filename when creating the delete nonce.<\/li>\n<\/ul>\n\n<h4>1.1.3<\/h4>\n\n<ul>\n<li>Fixed: Reordered logic in <code>BlockGlow_Admin::handle_delete_file()<\/code> so nonce validation runs before processing user input.<\/li>\n<li>Fixed: Addressed security scanner warning for missing nonce checks on <code>$_POST['file']<\/code> and <code>$_GET['file']<\/code>.<\/li>\n<li>Improved: Raw file input is now only read after successful nonce verification and capability checks.<\/li>\n<\/ul>\n\n<h4>1.1.2<\/h4>\n\n<ul>\n<li>Security: Added stricter nonce validation and capability checks for file deletion handlers; accept both generic and per-file nonces for compatibility.<\/li>\n<li>Security: Improved inline CSS handling for untrusted users \u2014 HTML tags are stripped before inlining to reduce the risk of injecting HTML into a style context.<\/li>\n<li>Admin: Removed PHPCS suppression and standardized sanitization of request inputs; cleaned up admin enqueue logic to prefer built assets when available.<\/li>\n<\/ul>\n\n<h4>1.1.1<\/h4>\n\n<ul>\n<li>Security: Tightened admin navigation and delete handlers \u2014 added nonce verification and input validation for admin page\/tab navigation and file deletion.<\/li>\n<li>Admin: Removed Import\/Export submenu and tab from the admin UI in this build to simplify the UI surface.<\/li>\n<li>Code Quality: Fixed PHPCS i18n warnings and added translator context where needed.<\/li>\n<\/ul>\n\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>Minor: Improved editor reliability and added an option to toggle in-editor rendering of custom CSS. This release is backwards-compatible; no data migration is required.<\/li>\n<\/ul>\n\n<h4>1.0.5<\/h4>\n\n<ul>\n<li>Editor: improved attribute attachment in the block editor so <code>data-blockglow-id<\/code> is applied to the actual editor block element when possible (closest-node, clientId selector and MutationObserver fallback).<\/li>\n<li>Editor: added a clientId-based selector fallback so editor-scoped CSS applies even when a DOM attribute cannot be attached.<\/li>\n<li>Editor: added a ToggleControl to optionally enable\/disable rendering custom CSS inside the editor preview (default: off).<\/li>\n<li>Editor: displays the \"Generated CSS file\" path under the CodeEditor\/textarea in the inspector so you can quickly open or verify the created CSS file.<\/li>\n<\/ul>\n\n<h4>1.0.4<\/h4>\n\n<ul>\n<li>Security: Sanitized input handling for $_POST['file'] and $_GET['file'] using sanitize_file_name() and wp_unslash().<\/li>\n<li>Security: Added nonce sanitization and validation for $_POST['_wpnonce'] and $_GET['_wpnonce'] using sanitize_text_field() and wp_verify_nonce().<\/li>\n<li>Code Quality: Resolved PHPCS warnings related to WordPress.Security.ValidatedSanitizedInput.InputNotSanitized.<\/li>\n<\/ul>\n\n<h4>1.0.3<\/h4>\n\n<ul>\n<li>Security: replace use of <code>$_REQUEST<\/code> with explicit <code>$_POST<\/code>\/<code>$_GET<\/code> handling and <code>wp_unslash()<\/code> for admin delete actions; improve input normalization and handling.<\/li>\n<\/ul>\n\n<h4>1.0.2<\/h4>\n\n<ul>\n<li>Security: perform nonce verification (<code>check_admin_referer()<\/code>) and capability checks early for admin delete actions; normalize and sanitize request inputs.<\/li>\n<li>Output safety: apply \"escape late\" handling for inline CSS \u2014 raw CSS is allowed only for users with <code>unfiltered_html<\/code>; other users will have CSS escaped at output time to avoid XSS.<\/li>\n<li>Editor: improved dark fallback textarea styling (border-radius:0; background:#000; color:#fff; font-size:13px; padding:10px) and token color rules for editor where available.<\/li>\n<li>Misc: several bugfixes and code hygiene improvements addressing WordPress.org review feedback.<\/li>\n<\/ul>\n\n<h4>1.0.1<\/h4>\n\n<ul>\n<li>Improved front-end output: removed automatic wrapper DIVs and now inject a <code>data-blockglow-id<\/code> attribute into the block's root element so global and theme styles are easier to author.<\/li>\n<li>Switched all inline stylesheet output to use <code>wp_register_style()<\/code> + <code>wp_add_inline_style()<\/code> and <code>wp_enqueue_style()<\/code> instead of echoing <code>&lt;style&gt;<\/code> tags directly.<\/li>\n<li>Added stronger admin-side security: nonce verification for delete actions via <code>check_admin_referer()<\/code> and capability checks for file management.<\/li>\n<li>Misc: improved input sanitization and removed unsafe direct superglobal usage in admin handlers.<\/li>\n<\/ul>","raw_excerpt":"Adds a &quot;Custom CSS&quot; inspector panel to every Gutenberg block and saves per-block CSS files to uploads for front-end enqueuing.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/249575","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=249575"}],"author":[{"embeddable":true,"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/eltresse93"}],"wp:attachment":[{"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=249575"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=249575"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=249575"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=249575"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=249575"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/br.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=249575"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}