Formulario de Login moderno con HTML, CSS y Font Awesome — Tutorial paso a paso 2026

En este tutorial vamos a construir un formulario de inicio de sesión moderno con layout de dos columnas: un panel izquierdo decorativo con identidad de marca y un panel derecho con el formulario limpio y funcional. Usaremos Font Awesome para los íconos, CSS puro para el diseño y un poco de JavaScript para el botón de mostrar/ocultar contraseña. El resultado es un formulario de nivel profesional que puedes integrar en cualquier proyecto web.

¿Qué aprenderás en este tutorial?

  • Cómo crear un layout de dos columnas con Flexbox.
  • Cómo usar Font Awesome para íconos en inputs y botones.
  • Cómo crear el efecto de círculos decorativos solo con CSS.
  • Cómo implementar el botón mostrar/ocultar contraseña con JavaScript.
  • Buenas prácticas de diseño de formularios para una mejor experiencia de usuario.

Paso 1 — Importar Font Awesome

Antes de escribir una sola línea de HTML del formulario, debemos importar Font Awesome. Esta librería de íconos es gratuita, no requiere registro y se puede usar con una sola línea en el <head>:

<link
  rel="stylesheet"
  href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"
/>

Para usar un ícono de Font Awesome, simplemente agregas una etiqueta <i> con las clases correspondientes. Por ejemplo:

<i class="fa-regular fa-user"></i>      <!-- ícono de usuario -->
<i class="fa-solid fa-lock"></i>       <!-- ícono de candado -->
<i class="fa-brands fa-google"></i>    <!-- ícono de Google -->
<i class="fa-regular fa-eye"></i>       <!-- ícono de ojo -->

Paso 2 — La estructura HTML completa

La estructura principal son dos divs hermanos dentro de .login-card: .lc-left para el panel decorativo y .lc-right para el formulario. El overflow: hidden en la tarjeta es lo que hace que los círculos decorativos que salen del panel izquierdo no se derramen fuera de la tarjeta:

<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Login — SystemsBM</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"/>
  <link rel="stylesheet" href="style.css">
</head>
<body>

<div class="login-card">

  <!-- PANEL IZQUIERDO -->
  <div class="lc-left">
    <div class="lc-circle"></div>
    <div class="lc-brand">
      <div class="lc-brand-icon">
        <i class="fa-solid fa-code"></i>
      </div>
      <h2>SystemsBM</h2>
      <p>Recursos de programación y tecnología en español para todos.</p>
    </div>
  </div>

  <!-- PANEL DERECHO: FORMULARIO -->
  <div class="lc-right">
    <h1 class="lc-title">Iniciar sesión</h1>
    <p class="lc-sub">Bienvenido de nuevo, ingresa tus datos</p>

    <div class="lc-field">
      <label>Usuario o correo</label>
      <div class="lc-input-wrap">
        <i class="fa-regular fa-user pre"></i>
        <input type="email" placeholder="tu@correo.com" required>
      </div>
    </div>

    <div class="lc-field">
      <label>Contraseña</label>
      <div class="lc-input-wrap">
        <i class="fa-solid fa-lock pre"></i>
        <input type="password" id="pwd" placeholder="••••••••" required>
        <button class="lc-show" onclick="togglePwd()" type="button">
          <i class="fa-regular fa-eye" id="eye-icon"></i>
        </button>
      </div>
    </div>

    <div class="lc-row">
      <label><input type="checkbox"> Recordarme</label>
      <a href="#">¿Olvidaste tu contraseña?</a>
    </div>

    <button class="lc-btn" type="submit">
      <i class="fa-solid fa-arrow-right-to-bracket"></i> Ingresar
    </button>

    <div class="lc-divider"><span>o continúa con</span></div>

    <button class="lc-btn-alt" type="button">
      <i class="fa-brands fa-google"></i> Google
    </button>

    <p class="lc-footer">
      ¿No tienes cuenta? <a href="#">Regístrate gratis</a>
    </p>
  </div>

</div>

<script src="script.js"></script>
</body>
</html>

Paso 3 — El CSS completo

El truco de los círculos decorativos usa ::before y ::after — pseudoelementos CSS que crean formas sin necesidad de agregar HTML extra. El overflow: hidden en .login-card los recorta elegantemente:

* { margin:0; padding:0; box-sizing:border-box; }

body {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #0d0d1a;
  font-family: 'Segoe UI', sans-serif;
}

.login-card {
  display: flex;
  width: 100%;
  max-width: 720px;
  border-radius: 16px;
  overflow: hidden;
  min-height: 400px;
}

/* Panel izquierdo */
.lc-left {
  flex: 1;
  background: #1a1a2e;
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 40px 36px;
}

/* Círculo decorativo superior izquierdo */
.lc-left::before {
  content: '';
  position: absolute;
  width: 220px;
  height: 220px;
  border-radius: 50%;
  background: linear-gradient(135deg, #6c47ff, #a855f7);
  top: -60px;
  left: -60px;
  opacity: 0.5;
}

/* Círculo decorativo inferior derecho */
.lc-left::after {
  content: '';
  position: absolute;
  width: 160px;
  height: 160px;
  border-radius: 50%;
  background: linear-gradient(135deg, #6c47ff, #818cf8);
  bottom: -40px;
  right: -40px;
  opacity: 0.4;
}

/* Tercer círculo (div extra) */
.lc-circle {
  position: absolute;
  width: 110px;
  height: 110px;
  border-radius: 50%;
  background: linear-gradient(135deg, #7c3aed, #a78bfa);
  bottom: 60px;
  left: 50px;
  opacity: 0.6;
}

.lc-brand { position: relative; z-index: 2; }

.lc-brand-icon {
  width: 44px;
  height: 44px;
  background: rgba(255,255,255,0.12);
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 20px;
}

.lc-brand-icon i { color: #a78bfa; font-size: 20px; }
.lc-brand h2 { font-size: 22px; font-weight: 700; color: #fff; margin: 0 0 8px; }
.lc-brand p { font-size: 13px; color: #a5b4fc; line-height: 1.6; max-width: 180px; }

/* Panel derecho */
.lc-right {
  flex: 1.1;
  background: #fff;
  padding: 40px 36px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.lc-title { font-size: 22px; font-weight: 700; color: #0f0f1a; margin: 0 0 4px; }
.lc-sub { font-size: 13px; color: #94a3b8; margin: 0 0 28px; }
.lc-field { margin-bottom: 14px; }
.lc-field label { display: block; font-size: 12px; color: #64748b; margin-bottom: 5px; font-weight: 500; }

.lc-input-wrap { position: relative; }

.lc-input-wrap i.pre {
  position: absolute;
  left: 13px;
  top: 50%;
  transform: translateY(-50%);
  color: #94a3b8;
  font-size: 14px;
  pointer-events: none;
}

.lc-input-wrap input {
  width: 100%;
  padding: 10px 40px;
  border: 1.5px solid #e2e8f0;
  border-radius: 8px;
  font-size: 13px;
  color: #0f0f1a;
  background: #f8fafc;
  outline: none;
  transition: border .2s, background .2s;
  box-sizing: border-box;
}

.lc-input-wrap input:focus { border-color: #7c3aed; background: #fff; }
.lc-input-wrap input::placeholder { color: #cbd5e1; }

.lc-show {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  cursor: pointer;
  color: #94a3b8;
  font-size: 14px;
  padding: 0;
}

.lc-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 12px;
  margin-bottom: 18px;
}

.lc-row label { display: flex; align-items: center; gap: 6px; color: #64748b; cursor: pointer; }
.lc-row label input { accent-color: #7c3aed; }
.lc-row a { color: #7c3aed; text-decoration: none; font-weight: 500; }

.lc-btn {
  width: 100%;
  padding: 11px;
  background: #7c3aed;
  color: #fff;
  border: none;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background .2s;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-bottom: 10px;
}

.lc-btn:hover { background: #6d28d9; }

.lc-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 4px 0 10px;
}

.lc-divider span { font-size: 11px; color: #cbd5e1; }
.lc-divider::before,.lc-divider::after { content:''; flex:1; height:1px; background:#e2e8f0; }

.lc-btn-alt {
  width: 100%;
  padding: 10px;
  background: #fff;
  color: #0f0f1a;
  border: 1.5px solid #e2e8f0;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  transition: background .2s;
}

.lc-btn-alt:hover { background: #f8fafc; }
.lc-btn-alt i { color: #4285f4; font-size: 15px; }

.lc-footer { text-align: center; font-size: 12px; color: #94a3b8; margin-top: 16px; }
.lc-footer a { color: #7c3aed; text-decoration: none; font-weight: 500; }

Paso 4 — El JavaScript para mostrar contraseña

Solo necesitamos una función que alterne el tipo del input entre password y text, y que cambie el ícono del ojo según el estado:

function togglePwd() {
  const input = document.getElementById('pwd');
  const icon  = document.getElementById('eye-icon');

  if (input.type === 'password') {
    input.type = 'text';
    icon.className = 'fa-regular fa-eye-slash';
  } else {
    input.type = 'password';
    icon.className = 'fa-regular fa-eye';
  }
}

¿Por qué usar type="button" en el botón del ojo? Si el botón está dentro de un formulario y no tiene type="button", el navegador lo trata como type="submit" y enviará el formulario al hacer clic. Siempre especifica el tipo en los botones que no son de envío.

Cómo cambiar los colores al tuyo

El color principal del formulario es el morado (#7c3aed). Para cambiarlo a otro esquema solo necesitas reemplazar tres valores en el CSS:

  • Morado → Azul: cambia #7c3aed por #2563eb y #6d28d9 por #1d4ed8.
  • Morado → Verde: usa #059669 y #047857.
  • Morado → Rojo/coral: prueba con #e11d48 y #be123c.

El fondo del panel izquierdo (#1a1a2e) también puedes cambiarlo. Para un look más claro prueba #1e3a5f con azul, o #0f2d0f para un verde oscuro.

Conclusión

Con este tutorial construiste un formulario de login de nivel profesional usando solo HTML, CSS y JavaScript básico. Los conceptos que aplicaste — pseudoelementos CSS, posicionamiento absoluto, Font Awesome y manipulación del DOM — son exactamente los mismos que se usan en proyectos reales del día a día.

En próximas entregas de SystemsBM vamos a ver cómo conectar este formulario a un backend con Python y FastAPI para que el login sea completamente funcional. Si tienes dudas, déjalas en los comentarios.

Publicar un comentario

Post a Comment (0)

Artículo Anterior Artículo Anterior Artículo Siguiente Artículo Siguiente