{"id":271201,"date":"2026-01-06T05:19:27","date_gmt":"2026-01-06T05:19:27","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/custom-page-styles\/"},"modified":"2026-03-20T08:47:12","modified_gmt":"2026-03-20T08:47:12","slug":"studio-noir-page-styles","status":"publish","type":"plugin","link":"https:\/\/ku.wordpress.org\/plugins\/studio-noir-page-styles\/","author":13670348,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_crdt_document":"","version":"2.0.1","stable_tag":"2.0.1","tested":"6.9.4","requires":"5.0","requires_php":"7.4","requires_plugins":null,"header_name":"Studio Noir Custom Page Styles","header_author":"Masaki Kobayashi (studioNoiR)","header_description":"Manage custom CSS for each page\/post with reusability feature. Write CSS directly in the editor and reuse styles across multiple pages.","assets_banners_color":"","last_updated":"2026-03-20 08:47:12","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/github.com\/monsieurNoiR\/custom-page-styles-plugin","header_author_uri":"https:\/\/github.com\/monsieurNoiR","rating":0,"author_block_rating":0,"active_installs":0,"downloads":305,"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":"studioNoiR","date":"2026-01-06 05:20:28"},"1.1.1":{"tag":"1.1.1","author":"studioNoiR","date":"2026-02-10 00:08:29"},"2.0.0":{"tag":"2.0.0","author":"studioNoiR","date":"2026-03-14 13:58:44"},"2.0.1":{"tag":"2.0.1","author":"studioNoiR","date":"2026-03-20 08:47:12"}},"upgrade_notice":{"2.0.0":"<p>Major update! Introduces the Style Library \u2014 a dedicated Custom Post Type for managing reusable styles. Existing CSS is automatically migrated on first activation. Fully backward compatible with v1.x data.<\/p>","1.1.1":"<p>Important security update! Enhanced file upload validation with MIME type checking and improved path traversal protection. Recommended for all users.<\/p>","1.1.0":"<p>Major update! Unlimited style selection with drag &amp; drop, file upload support for CSS\/JS, and improved load order control. Fully backward compatible with v1.0.x.<\/p>","1.0.2":"<p>Improved style loading priority for better theme override capability.<\/p>","1.0.1":"<p>Important security update with enhanced CSS sanitization and file validation.<\/p>","1.0.0":"<p>Initial release of Studio Noir Custom Page Styles.<\/p>"},"ratings":[],"assets_icons":[],"assets_banners":[],"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.0","1.1.1","2.0.0","2.0.1"],"block_files":[],"assets_screenshots":{"screenshot-1.jpg":{"filename":"screenshot-1.jpg","revision":3482556,"resolution":"1","location":"assets","locale":""},"screenshot-2.jpg":{"filename":"screenshot-2.jpg","revision":3482556,"resolution":"2","location":"assets","locale":""},"screenshot-3.jpg":{"filename":"screenshot-3.jpg","revision":3482556,"resolution":"3","location":"assets","locale":""},"screenshot-4.jpg":{"filename":"screenshot-4.jpg","revision":3482556,"resolution":"4","location":"assets","locale":""}},"screenshots":{"1":"Custom Page Styles meta box \u2014 file upload, inline CSS editor, and Save\/Sync to Library buttons","2":"Sync to Library dialog \u2014 overwrite existing style or save as new style","3":"Settings page \u2014 choose which post types have the meta box enabled","4":"Style Library list \u2014 manage reusable styles as named entries"},"jetpack_post_was_ever_published":false},"plugin_section":[],"plugin_tags":[356,2001,5887,59283,253394],"plugin_category":[59],"plugin_contributors":[253395],"plugin_business_model":[],"class_list":["post-271201","plugin","type-plugin","status-publish","hentry","plugin_tags-css","plugin_tags-custom-css","plugin_tags-file-upload","plugin_tags-page-styles","plugin_tags-reusable-css","plugin_category-utilities-and-tools","plugin_contributors-studionoir","plugin_committers-studionoir"],"banners":[],"icons":{"svg":false,"icon":"https:\/\/s.w.org\/plugins\/geopattern-icon\/studio-noir-page-styles.svg","icon_2x":false,"generated":true},"screenshots":[{"src":"https:\/\/ps.w.org\/studio-noir-page-styles\/assets\/screenshot-1.jpg?rev=3482556","caption":"Custom Page Styles meta box \u2014 file upload, inline CSS editor, and Save\/Sync to Library buttons"},{"src":"https:\/\/ps.w.org\/studio-noir-page-styles\/assets\/screenshot-2.jpg?rev=3482556","caption":"Sync to Library dialog \u2014 overwrite existing style or save as new style"},{"src":"https:\/\/ps.w.org\/studio-noir-page-styles\/assets\/screenshot-3.jpg?rev=3482556","caption":"Settings page \u2014 choose which post types have the meta box enabled"},{"src":"https:\/\/ps.w.org\/studio-noir-page-styles\/assets\/screenshot-4.jpg?rev=3482556","caption":"Style Library list \u2014 manage reusable styles as named entries"}],"raw_content":"<!--section=description-->\n<p>Tired of copy-pasting the same CSS across multiple pages? Studio Noir Custom Page Styles lets you write a style once and reuse it on any page \u2014 no duplicates, no maintenance headaches.<\/p>\n\n<h4>Key Features<\/h4>\n\n<ul>\n<li>Write custom CSS directly in the page\/post editor<\/li>\n<li><strong>Upload CSS and JavaScript files<\/strong><\/li>\n<li><strong>Select unlimited existing styles with drag &amp; drop reordering<\/strong><\/li>\n<li>Choose header or footer loading for JavaScript files<\/li>\n<li>Automatically generates CSS files for better performance<\/li>\n<li>Choose which post types to enable<\/li>\n<li>Secure and WordPress coding standards compliant<\/li>\n<\/ul>\n\n<h4>Perfect For<\/h4>\n\n<ul>\n<li>Adding unique designs to landing pages<\/li>\n<li>Customizing individual blog posts with external libraries<\/li>\n<li>Managing page-specific styles without bloating your main stylesheet<\/li>\n<li>Reusing common style patterns across multiple pages<\/li>\n<li>Adding JavaScript effects and animations to specific pages<\/li>\n<\/ul>\n\n<h4>How It Works<\/h4>\n\n<ol>\n<li>Edit any page or post<\/li>\n<li>Find the \"Custom Page Styles\" meta box<\/li>\n<li>Upload CSS\/JS files, select existing styles, or write custom CSS<\/li>\n<li>Reorder styles by drag &amp; drop to control load order<\/li>\n<li>Publish and see your styles in action!<\/li>\n<\/ol>\n\n<h4>Load Order<\/h4>\n\n<p>Styles are loaded in the following order for maximum flexibility:<\/p>\n\n<ol>\n<li>Selected styles (base templates)<\/li>\n<li>Uploaded files (libraries and frameworks)<\/li>\n<li>Direct CSS (final adjustments and overrides)<\/li>\n<\/ol>\n\n<h3>Support Development<\/h3>\n\n<p>If you find this plugin helpful, consider supporting its development:<\/p>\n\n<p>\u2615 <a href=\"https:\/\/ko-fi.com\/studio_noir\">Buy me a coffee on Ko-fi<\/a><\/p>\n\n<p>Your support helps me continue creating free, open-source WordPress plugins!<\/p>\n\n<!--section=installation-->\n<h4>Automatic Installation<\/h4>\n\n<ol>\n<li>Go to Plugins &gt; Add New<\/li>\n<li>Search for \"Studio Noir Custom Page Styles\"<\/li>\n<li>Click \"Install Now\"<\/li>\n<li>Activate the plugin<\/li>\n<\/ol>\n\n<h4>Manual Installation<\/h4>\n\n<ol>\n<li>Download the plugin zip file<\/li>\n<li>Go to Plugins &gt; Add New &gt; Upload Plugin<\/li>\n<li>Choose the downloaded file and click \"Install Now\"<\/li>\n<li>Activate the plugin<\/li>\n<\/ol>\n\n<h4>After Activation<\/h4>\n\n<ol>\n<li>Go to Settings &gt; Custom Page Styles<\/li>\n<li>Select which post types you want to enable<\/li>\n<li>Edit any page\/post and find the \"Custom Page Styles\" meta box<\/li>\n<li>Start adding custom styles!<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"can%20i%20use%20this%20on%20custom%20post%20types%3F\"><h3>Can I use this on custom post types?<\/h3><\/dt>\n<dd><p>Yes! Go to Settings &gt; Custom Page Styles and select which post types you want to enable.<\/p><\/dd>\n<dt id=\"will%20this%20work%20with%20my%20theme%3F\"><h3>Will this work with my theme?<\/h3><\/dt>\n<dd><p>Yes, Studio Noir Custom Page Styles works with any WordPress theme.<\/p><\/dd>\n<dt id=\"how%20many%20styles%20can%20i%20apply%20to%20one%20page%3F\"><h3>How many styles can I apply to one page?<\/h3><\/dt>\n<dd><p>Unlimited! You can select as many existing styles as you need, upload multiple CSS\/JS files, and add custom CSS - all on the same page.<\/p><\/dd>\n<dt id=\"can%20i%20control%20the%20order%20styles%20are%20loaded%3F\"><h3>Can I control the order styles are loaded?<\/h3><\/dt>\n<dd><p>Yes! Use drag &amp; drop to reorder selected styles. The order you set determines the load order.<\/p><\/dd>\n<dt id=\"what%20file%20types%20can%20i%20upload%3F\"><h3>What file types can I upload?<\/h3><\/dt>\n<dd><p>CSS (.css) and JavaScript (.js) files only. Maximum file size is 5MB per file.<\/p><\/dd>\n<dt id=\"where%20should%20javascript%20files%20be%20loaded%3F\"><h3>Where should JavaScript files be loaded?<\/h3><\/dt>\n<dd><p>You can choose header or footer for each JS file. Footer is recommended for most cases (default).<\/p><\/dd>\n<dt id=\"where%20are%20the%20uploaded%20files%20stored%3F\"><h3>Where are the uploaded files stored?<\/h3><\/dt>\n<dd><p>Uploaded files are stored in <code>\/wp-content\/uploads\/sn-cps-styles\/{post_id}\/<\/code> to keep files organized by post.<\/p><\/dd>\n<dt id=\"does%20this%20affect%20site%20performance%3F\"><h3>Does this affect site performance?<\/h3><\/dt>\n<dd><p>No, CSS is generated as separate files and only loaded on the relevant pages, which is better for performance than inline styles.<\/p><\/dd>\n<dt id=\"can%20i%20use%20this%20with%20page%20builders%3F\"><h3>Can I use this with page builders?<\/h3><\/dt>\n<dd><p>Yes, Studio Noir Custom Page Styles works alongside page builders like Elementor, Gutenberg, and the Classic Editor.<\/p><\/dd>\n<dt id=\"what%20if%20the%20meta%20box%20doesn%27t%20appear%3F\"><h3>What if the meta box doesn't appear?<\/h3><\/dt>\n<dd><ol>\n<li>Make sure the plugin is activated<\/li>\n<li>Check that the post type is enabled in Settings &gt; Custom Page Styles<\/li>\n<li>Click \"Screen Options\" at the top of the editor and make sure \"Custom Page Styles\" is checked<\/li>\n<\/ol><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>2.0.1<\/h4>\n\n<ul>\n<li>FIX: Save to Library and Sync to Library now correctly use the current textarea CSS instead of the stale database value<\/li>\n<li>FIX: Syncing to Library no longer clears the Library entry's CSS when the post had not been saved first<\/li>\n<\/ul>\n\n<h4>2.0.0<\/h4>\n\n<ul>\n<li>NEW: Style Library \u2014 manage reusable CSS as independent entries (Custom Post Type)<\/li>\n<li>NEW: \"Save to Library\" button \u2014 register a page's CSS as a named reusable style<\/li>\n<li>NEW: \"Sync to Library\" button \u2014 overwrite or fork an existing Library entry<\/li>\n<li>NEW: Automatic migration from v1.x data to Style Library entries<\/li>\n<li>NEW: Migration error notice with Retry \/ Dismiss actions<\/li>\n<li>NEW: Trash warning when a page with unregistered CSS is moved to trash<\/li>\n<li>IMPROVED: Style selector now uses Library entry names instead of page titles<\/li>\n<li>IMPROVED: Library entry deletion cleans up CSS files, uploaded files, and page references<\/li>\n<li>IMPROVED: Uninstall routine now removes all v2.0 data (CPT, meta keys, options)<\/li>\n<\/ul>\n\n<h4>1.1.1<\/h4>\n\n<ul>\n<li>SECURITY: Enhanced path traversal protection in ajax_remove_file()<\/li>\n<li>SECURITY: Added MIME type validation using finfo_file() in ajax_upload_file()<\/li>\n<li>FEATURE: Automatic filename conflict resolution (adds -1, -2, etc.)<\/li>\n<li>IMPROVED: File upload security with comprehensive validation<\/li>\n<\/ul>\n\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>NEW: Unlimited style selection (previously limited to 2)<\/li>\n<li>NEW: Drag &amp; drop reordering for selected styles (ACF-style sortable UI)<\/li>\n<li>NEW: File upload feature for CSS and JavaScript files<\/li>\n<li>NEW: Choose header or footer loading for JavaScript files<\/li>\n<li>NEW: Files organized in post-specific directories<\/li>\n<li>IMPROVED: CSS load order optimization (selected \u2192 uploaded \u2192 direct CSS)<\/li>\n<li>IMPROVED: Security enhancements for file uploads (type validation, size limit)<\/li>\n<li>IMPROVED: Better UI with visual feedback and file management<\/li>\n<\/ul>\n\n<h4>1.0.2<\/h4>\n\n<ul>\n<li>IMPROVED: Style loading priority optimization<\/li>\n<li>Set <code>wp_enqueue_scripts<\/code> hook priority to 20<\/li>\n<li>Custom CSS now reliably overrides theme styles<\/li>\n<\/ul>\n\n<h4>1.0.1<\/h4>\n\n<ul>\n<li>SECURITY: Enhanced CSS sanitization (WP_Error support)<\/li>\n<li>SECURITY: Additional dangerous pattern detection<\/li>\n<li>SECURITY: File size limit added (1MB for CSS)<\/li>\n<li>IMPROVED: Better error handling with Transient API<\/li>\n<li>IMPROVED: Path traversal attack prevention<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release<\/li>\n<li>Custom CSS per page\/post<\/li>\n<li>Reuse existing styles feature<\/li>\n<li>Post type selection<\/li>\n<li>Automatic CSS file generation<\/li>\n<li>Security: SQL injection prevention<\/li>\n<li>Security: CSS sanitization<\/li>\n<li>Security: File path validation<\/li>\n<\/ul>","raw_excerpt":"Manage custom CSS for each page\/post with unlimited style selection, file uploads, and reusability features.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/ku.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/271201","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ku.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/ku.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/ku.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=271201"}],"author":[{"embeddable":true,"href":"https:\/\/ku.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/studionoir"}],"wp:attachment":[{"href":"https:\/\/ku.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=271201"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/ku.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=271201"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/ku.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=271201"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/ku.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=271201"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/ku.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=271201"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/ku.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=271201"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}