Custom Login Branding
A single-file WordPress plugin that allows you to rebrand the /wp-login.php screen with your own logo, background image, colors, and branding without theme modifications. Settings are integrated into WordPress Settings → General.
YT Custom Login Branding
A single-file WordPress plugin that allows you to rebrand the /wp-login.php screen with your own logo, background image, colors, and branding without theme modifications. Settings are integrated into WordPress Settings → General.
Features
- Upload custom logo for login screen
- Upload custom background image
- Customize background color
- Customize login button color
- Change logo link URL
- Change logo alt text
- Settings integrated into Settings → General
- Inline CSS injection (no external CSS files)
- WordPress Media Library integration
- Color picker for easy color selection
- No theme modifications required
- WPCS compliant code
Installation
- Download
class-yt-custom-login-branding.php - Upload to
/wp-content/plugins/directory - Activate the plugin through the 'Plugins' menu in WordPress
- Navigate to Settings → General
- Scroll down to the "Custom Login Branding" section
- Configure your login branding options
Usage
Settings Location
All settings are available in Settings → General under the "Custom Login Branding" section.
Available Settings
1. Login Logo
- Upload or select a logo from your Media Library
- Recommended size: 320x80px
- Replaces the default WordPress logo on the login screen
- Supports all image formats (JPG, PNG, GIF, SVG, etc.)
2. Login Background Image
- Upload or select a background image from your Media Library
- Displayed as a cover (fills entire background)
- Best results with high-resolution images (1920x1080px or higher)
- Supports all image formats
3. Logo Link URL
- The URL users will be directed to when clicking the logo
- Defaults to your site homepage
- Can be set to any valid URL
4. Logo Alt Text
- Alt text for the logo image (accessibility)
- Defaults to your site name
- Important for SEO and screen readers
5. Background Color
- Choose a background color using the color picker
- Default: #f0f0f1 (WordPress default gray)
- Fallback color if no background image is set
6. Button Color
- Customize the login button color
- Default: #2271b1 (WordPress blue)
- Automatically generates hover state (10% darker)
Screenshots
Admin Settings
Settings are integrated directly into Settings → General page:
┌─────────────────────────────────────────┐
│ Custom Login Branding │
├─────────────────────────────────────────┤
│ Login Logo │
│ [Preview Image] │
│ [Upload/Select Logo] [Remove Logo] │
│ │
│ Login Background Image │
│ [Preview Image] │
│ [Upload/Select Background] [Remove] │
│ │
│ Logo Link URL │
│ [https://example.com] │
│ │
│ Logo Alt Text │
│ [My Company Name] │
│ │
│ Background Color │
│ [#f0f0f1] 🎨 │
│ │
│ Button Color │
│ [#2271b1] 🎨 │
└─────────────────────────────────────────┘
Login Screen
The customized login screen will display:
- Your custom logo (if set)
- Your background image/color (if set)
- Your custom button color
- Your logo will link to your specified URL
Code Structure
Files
- class-yt-custom-login-branding.php - Main plugin file (499 lines)
- yt-custom-login-branding.js - Admin JavaScript (92 lines)
- yt-custom-login-branding.css - Admin styles (34 lines)
Total: 625 lines across 3 files
Main Class: YT_Custom_Login_Branding
Constants
YT_CUSTOM_LOGIN_BRANDING_VERSION // Plugin version: 1.0.0
YT_CUSTOM_LOGIN_BRANDING_BASENAME // Plugin basename
YT_CUSTOM_LOGIN_BRANDING_PATH // Plugin directory path
YT_CUSTOM_LOGIN_BRANDING_URL // Plugin directory URL
Key Methods
Core Methods
get_instance()- Singleton instance retrieval__construct()- Initialize plugininit_hooks()- Register WordPress hooksload_textdomain()- Load translations
Admin Methods
register_settings()- Register settings in Settings → Generalsanitize_options()- Sanitize and validate user inputrender_section_info()- Display section descriptionrender_logo_field()- Render logo upload fieldrender_background_field()- Render background upload fieldrender_logo_url_field()- Render logo URL fieldrender_logo_alt_field()- Render logo alt text fieldrender_background_color_field()- Render background color pickerrender_button_color_field()- Render button color pickerenqueue_admin_scripts()- Load admin CSS/JS filesadd_action_links()- Add settings link to plugins page
Login Page Methods
enqueue_login_styles()- Inject custom CSS on login pagebuild_login_css()- Generate custom CSS based on settingscustom_login_logo_url()- Filter logo link URLcustom_login_logo_alt()- Filter logo alt textdarken_color()- Helper to darken colors for hover states
Utility Methods
get_option()- Get option value with default fallback
Lifecycle Methods
activate()- Set default options on activationdeactivate()- Clean up on deactivationyt_custom_login_branding_uninstall()- Remove data on uninstall
WordPress Hooks Used
Actions
'plugins_loaded' // Load text domain
'admin_init' // Register settings
'admin_enqueue_scripts' // Load admin assets
'login_enqueue_scripts' // Inject login page styles
Filters
'plugin_action_links_*' // Add settings link
'login_headerurl' // Customize logo URL
'login_headertext' // Customize logo alt text
Security Features
- Direct file access prevention
- Capability checks (
current_user_can()) - Input sanitization (
sanitize_text_field(),sanitize_hex_color(),esc_url_raw()) - Output escaping (
esc_html(),esc_attr(),esc_url(),esc_js()) - Absint for image IDs
- Nonce verification (handled by WordPress Settings API)
Browser Compatibility
- Chrome/Edge (latest)
- Firefox (latest)
- Safari (latest)
- Supports all modern browsers
Technical Details
CSS/JS Files
The plugin uses external CSS and JS files for better maintainability:
- yt-custom-login-branding.css: Admin styling for image uploads
- yt-custom-login-branding.js: Admin functionality (media uploader, color picker)
- Login page CSS is generated dynamically and injected inline via
wp_add_inline_style()
JavaScript Features
- WordPress Media Library integration
- Color picker initialization (WordPress core)
- Image preview functionality
- Remove image functionality
- Localized strings for translations
Database Storage
All options are stored in a single option: yt_custom_login_branding_options
Option Structure:
array(
'logo_image' => 123, // Attachment ID
'background_image' => 456, // Attachment ID
'logo_url' => 'https://...', // URL
'logo_alt' => 'Company Name', // Text
'background_color' => '#f0f0f1', // Hex color
'button_color' => '#2271b1', // Hex color
)
Customization
Filter Hook Examples
// Modify default logo URL
add_filter( 'login_headerurl', function( $url ) {
return 'https://your-custom-url.com';
}, 20 );
// Modify default logo alt text
add_filter( 'login_headertext', function( $text ) {
return 'My Custom Text';
}, 20 );
Programmatic Access
// Get plugin instance
$login_branding = YT_Custom_Login_Branding::get_instance();
// Get specific option
$logo_url = $login_branding->get_option( 'logo_url', home_url() );
Testing Checklist
- [x] Plugin activates without errors
- [x] Settings appear in Settings → General
- [x] Logo upload works correctly
- [x] Background upload works correctly
- [x] Image previews display properly
- [x] Remove image buttons function
- [x] Color pickers work
- [x] Settings save properly
- [x] Login page displays custom branding
- [x] Logo links to correct URL
- [x] Logo alt text is correct
- [x] Background image/color displays
- [x] Button color changes apply
- [x] Plugin deactivates cleanly
- [x] Plugin uninstalls and removes data
- [x] No PHP warnings or notices
- [x] WPCS compliant
Requirements
- WordPress: 5.8 or higher
- PHP: 7.4 or higher
- Permissions: User must have
manage_optionscapability
Compatibility
- WordPress 5.8+
- WordPress 6.0+
- WordPress 6.4+ (latest tested)
- Multisite compatible
- Translation ready
Known Limitations
- Settings are in Settings → General (not a separate settings page)
- No custom CSS textarea for advanced users (only inline styles)
- Logo size is fixed at 320x80px (can be modified in code)
- Button hover color is automatically calculated (10% darker)
Troubleshooting
Logo not displaying
- Check that the image was uploaded successfully
- Verify the image ID is saved in the database
- Check file permissions on uploads directory
Background image not showing
- Ensure image file size is reasonable (< 2MB recommended)
- Check browser console for 404 errors
- Verify the attachment ID is correct
Colors not applying
- Clear browser cache
- Verify hex color format (#ffffff)
- Check for theme CSS conflicts (unlikely)
Settings not saving
- Check user capabilities (
manage_options) - Verify no JavaScript errors in console
- Check server error logs
Performance Notes
- No external CSS or JS files loaded
- Minimal database queries (single option)
- Uses WordPress core media library (no third-party libraries)
- Inline CSS is minified (no whitespace)
- JavaScript only loads on Settings → General page
Uninstallation
Method 1: Via WordPress Admin
- Deactivate the plugin
- Delete the plugin
- All settings are automatically removed
Method 2: Manual Removal
- Delete
class-yt-custom-login-branding.php - Run in MySQL/phpMyAdmin:
DELETE FROM wp_options WHERE option_name = 'yt_custom_login_branding_options';
Development
WPCS Validation
phpcs --standard=WordPress class-yt-custom-login-branding.php
Line Count
wc -l class-yt-custom-login-branding.php
# Output: ~480 lines
Changelog
Version 1.0.0
- Initial release
- Logo upload functionality
- Background image upload
- Background color picker
- Button color picker
- Logo URL customization
- Logo alt text customization
- Settings integrated into Settings → General
- WordPress Media Library integration
- Inline CSS injection
- WPCS compliant code
License
GPL v2 or later
Support
For support, please visit:
Credits
Built following WordPress Plugin Handbook and WPCS guidelines.
Author: Krasen Slavov Author URI: https://krasenslavov.com Plugin URI: https://github.com/krasenslavov/yt-custom-login-branding
Additional Notes
Why Settings → General?
The plugin integrates into Settings → General instead of creating a separate settings page to:
- Keep the codebase minimal (single file, ~480 lines)
- Avoid cluttering the WordPress admin menu
- Group related site-wide settings together
- Provide quick access to branding options
CSS Specificity
All CSS selectors are prefixed with body.login to ensure styles only apply to the login page and have proper specificity to override WordPress defaults.
Color Darken Algorithm
The darken_color() method converts hex to RGB, reduces each channel by the specified percentage, and converts back to hex for hover state generation.
Future Enhancements (Not Included)
Ideas for future versions (would exceed 512-line limit):
- Custom CSS textarea for advanced users
- Multiple color schemes/presets
- Login form styling options
- Remember me checkbox customization
- Lost password link styling
- Language switcher styling
- Custom favicon for login page
- Import/export settings
FAQ
Q: Can I use this with any theme? A: Yes, the plugin works independently of your theme.
Q: Will my settings be lost if I switch themes? A: No, settings are stored in the database, not in the theme.
Q: Can I use SVG logos? A: Yes, all image formats supported by WordPress Media Library work.
Q: Does this work on multisite? A: Yes, but settings are per-site, not network-wide.
Q: Can I revert to default WordPress login? A: Yes, simply deactivate the plugin or remove all custom images/colors.
Q: Is this translation ready? A: Yes, all strings are wrapped in translation functions.
Q: Will this affect login security? A: No, this only changes the visual appearance, not functionality.
Code Quality
- Follows WordPress Coding Standards (WPCS)
- PSR-2 style guide compatible
- Fully documented with PHPDoc blocks
- No deprecated functions used
- No security vulnerabilities
- No global variables (singleton pattern)
- Proper sanitization and escaping
Contributing
This is a single-file plugin designed to stay under 512 lines. Contributions should:
- Follow WordPress Coding Standards
- Not significantly increase line count
- Maintain backward compatibility
- Include proper documentation
Built with WordPress best practices in mind.