La pantalla de login predeterminada de WordPress (wp-login.php) es funcional y reconocible. En un proyecto de cliente sigue leyéndose como «CMS de serie», no como su producto. Poner marca blanca en el login es un cambio pequeño con mucho acabado: logo, colores, errores más discretos y CSS que solo carga en esa URL.
Esta guía usa solo hooks del núcleo. Sin plugin de branding. Pon el código en un tema hijo o en un plugin pequeño del sitio (o must-use) para que una actualización del tema padre no lo borre. Si el sitio ya tiene historial de exposición, el endurecimiento que va más allá de lo cosmético encaja mejor tras revisar el entorno; puedes empezar por contacto cuando haga falta encajar marca y endurecimiento en el mismo trabajo.
Por qué personalizar el login
Editores y clientes llegan a wp-login.php más a menudo que a muchas páginas de marketing. Un logo de WordPress junto a los colores de su marca rompe la confianza antes de llegar al escritorio. Las agencias también usan un login con marca como señal suave de que la instalación se cuidó, no se dejó en valores por defecto.
Personalizar no es seguridad por sí sola. Cambiar el logo no detiene el credential stuffing. Combina la marca con texto de error genérico, límites de intentos (host o plugin) y 2FA en cuentas privilegiadas.
El briefing típico del cliente: «Que parezca nuestra app». Eso suele significar logo, fondo, color del botón principal y enlaces de pie que apuntan a su dominio. No significa reescribir la autenticación. Mantén el alcance honesto en el presupuesto para que nadie espere un SSO a partir de un ticket de CSS.
En redes multisite a menudo se quiere un login con marca para todos los sitios. Pon el CSS compartido en un must-use o en un plugin de red.
Reemplazar el logo
Engancha login_enqueue_scripts y sobrescribe la imagen de fondo en #login h1 a.
function wppoland_login_logo() {
?>
<style type="text/css">
#login h1 a,
.login h1 a {
background-image: url(<?php echo esc_url( get_stylesheet_directory_uri() . '/images/cliente-logo.svg' ); ?>);
height: 65px;
width: 320px;
background-size: contain;
background-repeat: no-repeat;
padding-bottom: 30px;
}
</style>
<?php
}
add_action( 'login_enqueue_scripts', 'wppoland_login_logo' );Usa esc_url en la ruta de la imagen. Prefiere SVG o un PNG listo para retina; un JPEG grande se ve blando en pantallas HiDPI. Guarda el archivo en el tema hijo para que los deploys sean predecibles.
Por defecto el logo enlaza a wordpress.org. Apúntalo al inicio del sitio:
function wppoland_login_logo_url() {
return home_url( '/' );
}
add_filter( 'login_headerurl', 'wppoland_login_logo_url' );Opcionalmente filtra login_headertext para que el título accesible coincida con el nombre del cliente en lugar de «Powered by WordPress».
Cargar CSS solo en la pantalla de login
No vuelques reglas de login en el style.css público. Encola un archivo dedicado en el mismo hook:
function wppoland_login_stylesheet() {
wp_enqueue_style(
'wppoland-custom-login',
get_stylesheet_directory_uri() . '/style-login.css',
array(),
wp_get_theme()->get( 'Version' )
);
}
add_action( 'login_enqueue_scripts', 'wppoland_login_stylesheet' );Ejemplo de style-login.css:
body.login {
background-color: #0d1117;
display: flex;
align-items: center;
justify-content: center;
}
.login form {
background: #161b22;
border: 1px solid #30363d;
box-shadow: none;
border-radius: 8px;
}
.login label {
color: #c9d1d9;
}
.wp-core-ui .button-primary {
background: #238636;
border-color: rgba(27, 31, 35, 0.15);
}
.login #backtoblog a,
.login #nav a {
color: #c9d1d9;
}Ajusta el contraste a WCAG cuando los editores lo necesiten: gris claro sobre gris oscuro falla para algunos usuarios. Prueba los outlines de foco en usuario, contraseña y envío; quitar outlines por «diseño limpio» es una regresión.
Los paquetes de idioma y las locales RTL siguen usando los mismos hooks. Evita cadenas en inglés fijas en propiedades CSS content.
Las imágenes de fondo en body.login deben estar comprimidas. Prefiere un color de marca sólido o un patrón sutil por debajo de 100 KB. Si el manual exige un formulario claro sobre fondo claro, sube el contraste del borde en .login form para que la tarjeta no se funda con la página.
Endurecer los mensajes de error
Un fallo de contraseña para un usuario existente históricamente producía un mensaje que confirmaba el nombre de usuario. Eso ayuda a enumerar cuentas antes de forzar contraseñas.
function wppoland_login_errors() {
return __( 'Credenciales no válidas.', 'your-textdomain' );
}
add_filter( 'login_errors', 'wppoland_login_errors' );Mantén el texto aburrido e idéntico para usuario desconocido y contraseña incorrecta. Esto es ofuscación frente a la enumeración, no un sustituto de:
- Prohibir contraseñas de administración débiles.
- Limitar intentos de login en la aplicación o en el edge.
- Activar 2FA para administradores.
- No usar
admincomo nombre de usuario en instalaciones nuevas.
Los flujos de contraseña perdida tienen sus propios mensajes. Revísalos si personalizas registro o plugins de membresía que comparten el CSS de login.
Algunos plugins de membresía sustituyen wp-login.php por un formulario en el front. En ese caso estos hooks no se disparan. Aplica las mismas reglas en los hooks del plugin, o estiliza sus plantillas parciales. Confirma qué URL usan realmente los editores antes de dar el trabajo por cerrado.
XML-RPC y el endpoint REST de usuarios son superficies de ataque aparte. Marcar wp-login.php no hace nada por ellas. Desactiva o restringe XML-RPC si no lo necesitas, y mantén las contraseñas de aplicación bajo política si el sitio las usa.
Quitar la animación shake
Los logins fallidos activan un temblor vía wp_shake_js. Algunas guías de marca lo tratan como ruido.
function wppoland_remove_login_shake() {
remove_action( 'login_head', 'wp_shake_js', 12 );
}
add_action( 'login_head', 'wppoland_remove_login_shake' );Si una versión futura del núcleo cambia la prioridad, revisa el hook en el código fuente y ajústalo. Documenta la intención en un comentario de una línea encima del remove_action.
2FA, passkeys y campos de plugins
Construir 2FA completo dentro de functions.php es el proyecto equivocado. Usa un plugin mantenido (por ejemplo el plugin oficial Two Factor o la oferta de tu hosting) y estiliza los campos extra para que encajen con el formulario de marca.
Selectores habituales tras activar 2FA:
.login .backup-methods- inputs añadidos para códigos TOTP
- botones de «usar una llave de seguridad»
Carga esas reglas en el mismo style-login.css. Tras cada actualización del plugin, vuelve a comprobar la URL de login en staging: los nombres de clase se mueven.
La UX de passkeys y WebAuthn varía según el plugin. En el lado de marca tu trabajo es contraste, espaciado y no recortar el prompt de la llave de seguridad con overflow: hidden en .login form.
Tema hijo frente a plugin del sitio
| Ubicación | Pros | Contras |
|---|---|---|
| Tema hijo | Viaja con assets del tema y la ruta del logo | Se pierde si alguien cambia de tema |
| Plugin específico del sitio | Sobrevive a cambios de tema | La URL del logo no debe hardcodear la ruta del tema antiguo |
| Must-use | Difícil de desactivar por accidente | Necesita acceso de deploy; no ideal para todos los clientes |
Las agencias que entregan el sitio suelen preferir un plugin pequeño con el nombre del cliente y el logo en assets/. Así la marca del login se mantiene cuando marketing instala después un tema de bloques nuevo.
Qué no hacer
- No edites
wp-login.phpen el núcleo. Las actualizaciones lo sobrescriben. - No encoles bundles frontend pesados en el login; mantén el CSS ligero.
- No ocultes la URL de login y llames a eso «seguridad» mientras dejas
admin/password123. - No apiles tres plugins de personalización de login encima de estos hooks.
- No pongas secretos ni claves API en el CSS de login.
Cambiar el slug de login (vía un plugin dedicado) es una decisión aparte. Puede recortar bots casuales; también rompe marcadores y algunos checklists de deploy. Marca y cambio de slug son independientes.
Si renombras la ruta de login, documenta la nueva URL en la entrega y en el gestor de contraseñas del cliente.
WooCommerce y otros formularios primos
Las páginas de cuenta de WooCommerce y los bloques de login en checkout usan otro markup. El CSS de login no restiliza my-account. O aceptas los formularios de Woo o encolas una hoja aparte. Mezclar ambos en style-login.css crea reglas muertas.
La misma separación aplica a LearnDash, MemberPress y similares: identifica la URL de entrada real. Un error habitual es pulir wp-login.php mientras los clientes solo ven un modal front con el logo de WordPress.
Mantenimiento tras actualizaciones del núcleo
Las versiones mayores de WordPress a veces retocan el markup o el CSS por defecto del login. Tras actualizar el núcleo en staging:
- Diff el HTML de login si algo se ve mal.
- Vuelve a probar el tamaño del logo; nuevas alturas por defecto pueden recortar SVG.
- Confirma que las prioridades de
remove_actionpara el shake siguen coincidiendo. - Revisa los campos de 2FA si ese plugin se actualizó en la misma ventana.
Fija la versión de la hoja de estilos a la del tema o del plugin para que el navegador no conserve un style-login.css antiguo tras un arreglo de contraste.
Checklist rápida de verificación
- Abre
/wp-login.phpsin sesión; confirma logo, colores y enlace al inicio. - Envía una contraseña incorrecta; confirma el error genérico y la ausencia de shake si lo quitaste.
- Confirma que «¿Olvidaste la contraseña?» sigue funcionando y que llegan los correos.
- Con 2FA activo, completa un login de administrador en staging.
- Cambia a un segundo idioma si el sitio es multilingüe y revisa el layout.
- Entra desde un viewport móvil; el centrado con flex a veces colapsa el formulario en pantallas bajas.
Resumen
Marca el logo y la URL del encabezado, encola CSS solo para login, devuelve errores genéricos y, si quieres, quita el shake. Mantén el código fuera del tema padre. Trata el 2FA como un control real y estiliza su UI; trata el CSS del logo como acabado.
Entrega al cliente una nota de una página: dónde vive el código, cómo sustituir el archivo del logo y cuál es la URL canónica para el personal. Esa nota evita que el siguiente freelance instale un plugin de login redundante seis meses después.
Si la instalación ya muestra indicios de abuso, o necesitas revisar el endurecimiento del login junto con plugins y hosting, empieza por contacto en lugar de apilar otro plugin cosmético sobre un sitio comprometido.






