Direct answer
To change the logo on WordPress's core login screen safely, select one local Media Library image, resolve it through WordPress's attachment API, and print bounded CSS through login_enqueue_scripts that changes only the native logo anchor's background image and contained size.
Use login_headerurl for the logo destination and login_headertext for its accessible title. If the image is missing or invalid, print nothing and let WordPress's native logo, link, and title remain authoritative.
StoreFixKit's Change Login Logo follows that boundary. Free supplies one local image, the site homepage, and site-name title. Pro adds a bounded HTTP/HTTPS destination, plain-text accessible title, and maximum width. Neither version touches authentication.
The logo is not the login system
WordPress's core login page owns many separate responsibilities:
- username and password fields;
- authentication and cookies;
- errors and notices;
- registration and password reset;
- sessions and redirects;
- the logo anchor and its accessible text;
- the form and surrounding markup.
A logo plugin should own only the final visual anchor properties.
WordPress's current login_header() implementation exposes login_enqueue_scripts, login_headerurl, and login_headertext around the native logo markup. The documented login_enqueue_scripts hook is limited to the login page, and login_headerurl changes the native logo link without replacing the form.
Those hooks provide a much smaller surface than copying wp-login.php, injecting sitewide CSS, or installing a complete login-page builder.
Public complaints reveal image and CSS boundaries
Support threads report custom logos cropped to a fixed width, logos changing after a WordPress update, and requests to adjust logo size on the login page.
These reports do not prove one core defect. They show three common ownership conflicts:
- the source image contains transparent padding or an unsuitable aspect ratio;
- another plugin or theme prints a later or more specific CSS rule;
- a core update changes the native selector or declaration order.
WordPress 7.0 exposed the third case during StoreFixKit testing: an earlier custom rule with the same specificity could be overridden by core login CSS. Version 0.1.3 uses a page-scoped selector specific enough to keep the selected image visible while leaving the form untouched. That regression is now part of the automated compatibility contract.
Use a local Media Library attachment
Storing a remote image URL looks flexible but adds availability, privacy, mixed-content, tracking, and domain-control risks to the login page. A local WordPress attachment gives the plugin a stable numeric ID and lets core decide whether it is a supported image.
The safe process is:
- open the standard WordPress media picker only on the plugin settings page;
- store one positive attachment ID after an authorized request;
- verify the attachment is an image with
wp_attachment_is_image(); - resolve its full local URL and dimensions through WordPress;
- escape the URL into page-scoped login CSS;
- otherwise print no custom CSS.
The plugin should not enable SVG uploads, regenerate thumbnails, optimize files, copy media, or recreate a deleted attachment.
Contain the complete image
A logo can be wide, square, tall, or padded. background-size: contain preserves the complete image's aspect ratio within a bounded area. It avoids stretching and deliberate cropping, but it cannot remove transparent padding baked into the source file.
Test a real logo at desktop and narrow mobile widths. A maximum width should be bounded; StoreFixKit Pro accepts 40 to 500 pixels. A larger number is not automatically better because the native login form still needs a clear, stable layout.
Do not scale font size or form width to match the logo. That would turn an image helper into a login-page design system.
Accessibility needs a real text alternative
The logo is inside a link. Its accessible name should describe the destination rather than the image file. Free uses the site name and homepage. Pro can supply one plain-text title up to 120 characters and one valid HTTP or HTTPS destination.
An empty Pro value should fall back to Free. Invalid schemes such as javascript: must be rejected. The visible image never replaces the need for keyboard focus, readable form labels, and WordPress's own login messages.
Custom login routes may be different products
A security plugin, membership suite, LMS, ecommerce portal, page builder, or identity provider may route users to a custom page. That page may not call WordPress's core login hooks.
A safe core-login plugin should remain silent there. It should not:
- replace templates;
- search the DOM for logo-like selectors;
- inject CSS on every frontend page;
- intercept authentication routes;
- disable security plugins;
- rewrite redirects;
- copy credentials or login errors.
Supporting a custom provider requires a named adapter, its own tests, and an explicit compatibility claim.
Test security by proving non-interference
The visual result is only half the test. Use this matrix:
| Case | Expected result |
|---|---|
Valid local image on core /wp-login.php |
Complete image is contained in native logo area |
| Feature disabled | Native WordPress logo, link, and title return |
| Attachment deleted or no longer an image | No custom CSS or fallback write occurs |
| Narrow mobile viewport | Logo and form do not overlap or change form width |
| Wrong password | WordPress's native error and authentication behavior remain |
| Password reset and registration | Native routes, fields, messages, and actions remain |
| Custom login page bypassing core hooks | StoreFixKit remains silent |
Also test the selected link with keyboard navigation and inspect the accessible name. Never use production credentials for visual testing.
Resource and failure boundary
Free reads one owned option and resolves one local attachment only on core login rendering. Its media-picker JavaScript loads only on the plugin settings page. Pro overlays three bounded display values from one owned option.
It needs no:
- sitewide frontend asset;
- remote image or public API call;
- user, password, session, or cookie query;
- authentication or redirect hook;
- custom database table;
- cron or background job;
- telemetry or analytics event.
A missing image, malformed setting, custom login route, inactive Pro plugin, expired license, or unavailable license API leaves WordPress login behavior intact. Free remains local.
The Change Login Logo documentation includes real screenshots, exact setup, compatibility limits, troubleshooting, rollback, uninstall ownership, and support evidence.
Beginner launch checklist
Prepare the image
Use a PNG, JPEG, WebP, or another format WordPress already supports. Remove unintended transparent padding and note the original pixel dimensions.
Record the native baseline
Open core /wp-login.php at desktop and mobile widths. Record the logo, link, accessible title, form dimensions, error display, password-reset link, and any security plugin output.
Choose the image through WordPress
Use Settings > Login Logo > Choose logo. Do not paste a remote URL or edit theme files.
Test the off path
Disable the setting, remove the selection, and delete a disposable selected attachment. WordPress's native result should return each time.
Test rollback
Move from 0.1.3 to 0.1.2 and back. On WordPress 7.0, 0.1.2 may show the core image because of equal-specificity CSS order; 0.1.3 is the compatibility fix. Authentication must remain unchanged in both states.
Security, privacy, and support evidence
Only an administrator with manage_options should save settings. Every write needs a nonce and capability check. Attachment IDs must be positive integers and verified as images. URLs must use HTTP or HTTPS, text must be bounded plain text, and every output must be escaped for its context.
Useful support evidence includes the core login URL with sensitive query values removed, attachment ID and file type, source dimensions, expected and actual image, Free and Pro versions, WordPress version, custom-login and security plugins, cache/CDN state, computed logo CSS, and desktop/mobile screenshots. Never send credentials, cookies, user records, payment details, or full license keys.
FAQ
Does changing the logo change login security?
No. The plugin does not connect to credentials, authentication, sessions, cookies, routes, redirects, CAPTCHA, two-factor authentication, registration, or password reset.
Can it change the background and form design?
No. It intentionally changes only the native logo image, link, title, and optional contained width.
Why does my custom login page still show another logo?
That page may bypass WordPress's core login hooks and is outside this plugin's contract.
What happens when Pro expires?
The Free local image, homepage link, and site-name title continue. The Pro destination, title, and width require an active product-bound license.
Focused plugin
Use the one-job implementation.
Show one local Media Library image in WordPress's native login-logo position without changing the form, users, passwords, sessions, routes, redirects, messages, registration, password reset, or security.