Crea un elegante formulario de contacto oscuro con HTML, CSS y JavaScript
Spanish (Español) translation by Adriana Obregón (you can also view the original English article)
En este tutorial, veremos el proceso de diseño de elementos básicos de un formulario de contacto. Examinaremos diferentes formas de hacer que un formulario sea hermoso y completamente funcional al mismo tiempo.
Este es el formulario que vamos a crear:
Nota: ¡Este formulario de contacto es perfecto para cualquier interfaz de usuario de modo oscuro! Obtén más información sobre cómo puedes cambiar entre el modo oscuro y claro usando nada más que CSS:
1. Comienza por el marcado de página
Comenzaremos desde cero con un elemento de formulario que contiene un encabezado y una lista desordenada. Utilizaremos un contenedor para establecer un ancho máximo para el formulario y centrar horizontalmente su contenido:
1 |
<form class="my-form"> |
2 |
<div class="container"> |
3 |
<h1>Get in touch!</h1> |
4 |
<ul>
|
5 |
<li>...</li> |
6 |
<li>...</li> |
7 |
<li>...</li> |
8 |
<li>...</li> |
9 |
<li>...</li> |
10 |
<li>...</li> |
11 |
</ul>
|
12 |
</div>
|
13 |
</form>
|
Dentro de la lista colocaremos los elementos del formulario.
El primer elemento de la lista, por ejemplo, contendrá un elemento de selección con cuatro opciones. Por defecto, la primera opción está seleccionada, pero deshabilitada:
1 |
<select>
|
2 |
<option selected disabled>-- Please choose an option --</option> |
3 |
<option>Request Quote</option> |
4 |
<option>Send Resume</option> |
5 |
<option>Other</option> |
6 |
</select>
|
En el segundo elemento de la lista, colocaremos dos campos de entrada obligatorios:
1 |
<div class="grid grid-2"> |
2 |
<input type="text" placeholder="Name" required> |
3 |
<input type="text" placeholder="Surname" required> |
4 |
</div>
|
El tercer elemento de la lista incluye un campo de entrada obligatorio y uno opcional:
1 |
<div class="grid grid-2"> |
2 |
<input type="email" placeholder="Email" required> |
3 |
<input type="tel" placeholder="Phone"> |
4 |
</div>
|
El cuarto elemento en la lista contiene un área de texto:
1 |
<textarea placeholder="Message"></textarea> |
El quinto elemento de la lista contiene una casilla de verificación junto con su etiqueta:
1 |
<input type="checkbox" id="terms"> |
2 |
<label for="terms">...</label> |
Finalmente, el sexto elemento de la lista contiene un elemento div y dos botones (Escrito enviar y restablecer):
1 |
<div class="grid grid-3"> |
2 |
<div class="required-msg">REQUIRED FIELDS</div> |
3 |
<button class="btn-grid" type="submit" disabled> |
4 |
<span class="back"> |
5 |
<img src="IMG_SRC" alt=""> |
6 |
</span>
|
7 |
<span class="front">SUBMIT</span> |
8 |
</button>
|
9 |
<button class="btn-grid" type="reset" disabled> |
10 |
<span class="back"> |
11 |
<img src="IMG_SRC" alt=""> |
12 |
</span>
|
13 |
<span class="front">RESET</span> |
14 |
</button>
|
15 |
</div>
|
2. Definir algunos estilos básicos
Antes de echar un vistazo más de cerca a los elementos de formulario individuales, definamos primero algunos estilos CSS. Estos incluyen algunas variables personalizadas para darnos nuestro esquema de color y algunas reglas de reinicio:
1 |
:root { |
2 |
--white: #afafaf; |
3 |
--red: #e31b23; |
4 |
--bodyColor: #292a2b; |
5 |
--borderFormEls: hsl(0, 0%, 10%); |
6 |
--bgFormEls: hsl(0, 0%, 14%); |
7 |
--bgFormElsFocus: hsl(0, 7%, 20%); |
8 |
}
|
9 |
|
10 |
* { |
11 |
padding: 0; |
12 |
margin: 0; |
13 |
box-sizing: border-box; |
14 |
outline: none; |
15 |
}
|
16 |
|
17 |
a { |
18 |
color: inherit; |
19 |
}
|
20 |
|
21 |
input, |
22 |
select, |
23 |
textarea, |
24 |
button { |
25 |
font-family: inherit; |
26 |
font-size: 100%; |
27 |
}
|
28 |
|
29 |
button, |
30 |
label { |
31 |
cursor: pointer; |
32 |
}
|
33 |
|
34 |
select { |
35 |
appearance: none; |
36 |
}
|
37 |
|
38 |
select::-ms-expand { |
39 |
display: none; |
40 |
}
|
41 |
|
42 |
select:-moz-focusring { |
43 |
color: transparent !important; |
44 |
text-shadow: 0 0 0 var(--white); |
45 |
}
|
46 |
|
47 |
textarea { |
48 |
resize: none; |
49 |
}
|
50 |
|
51 |
ul { |
52 |
list-style: none; |
53 |
}
|
Nota: Por simplicidad no voy a mencionar todas las reglas CSS en el tutorial. Puedes verificar el resto haciendo clic en la pestaña CSS del proyecto de demostración.
3. Crea el diseño del formulario
En pantallas pequeñas, todos nuestros elementos de formulario se apilarán:



Sin embargo, en ventanas de 600 píxeles de ancho y más, el diseño del formulario cambiará. Más específicamente:
- Organizaremos los elementos de la segunda y tercera lista en dos columnas del mismo ancho.
- Los elementos de la sexta lista de elementos se organizarán en tres columnas.



Gracias a CSS Grid, podemos construir fácilmente el diseño deseado de varias columnas. Comenzamos declarando nuestro contenedor .grid .grid como una cuadrícula, luego definimos las columnas en los elementos de la cuadrícula que necesitamos cambiar:
1 |
@media screen and (min-width: 600px) { |
2 |
.my-form .grid { |
3 |
display: grid; |
4 |
grid-gap: 1.5rem; |
5 |
}
|
6 |
|
7 |
.my-form .grid-2 { |
8 |
grid-template-columns: 1fr 1fr; |
9 |
}
|
10 |
|
11 |
.my-form .grid-3 { |
12 |
grid-template-columns: auto auto auto; |
13 |
align-items: center; |
14 |
}
|
15 |
}
|
Todas estas reglas se colocan dentro de una consulta de medios, por lo que solo surten efecto en ventanas de 600px de ancho y superiores.
4. Dale estilo a los elementos del formulario
Con nuestra estructura ordenada, a continuación agregamos algunos estilos estéticos iniciales a todos los elementos de la forma:
1 |
/*CUSTOM VARIABLES HERE*/
|
2 |
|
3 |
.my-form select, |
4 |
.my-form input, |
5 |
.my-form textarea, |
6 |
.my-form button { |
7 |
width: 100%; |
8 |
line-height: 1.5; |
9 |
padding: 15px 10px; |
10 |
border: 1px solid var(--borderFormEls); |
11 |
color: var(--white); |
12 |
background: var(--bgFormEls); |
13 |
transition: background-color 0.3s cubic-bezier(0.57, 0.21, 0.69, 1.25), |
14 |
transform 0.3s cubic-bezier(0.57, 0.21, 0.69, 1.25); |
15 |
}
|
16 |
|
17 |
.my-form textarea { |
18 |
height: 170px; |
19 |
}
|
20 |
|
21 |
.my-form ::placeholder { |
22 |
color: inherit; |
23 |
opacity: 1; |
24 |
}
|
Nota: alternativamente, para configurar el ancho y la altura del área de texto, podríamos haber usado sus atributos cols y row respectivamente.
Agrega estilos enfocados
Cada vez que un elemento de formulario está enfocado, me gustaría que cambie su color de fondo. Además, algunos elementos se amplían un poco, solo por énfasis:



Así es como se hace:
1 |
/*CUSTOM VARIABLES HERE*/
|
2 |
|
3 |
.my-form select:focus, |
4 |
.my-form input:focus, |
5 |
.my-form textarea:focus, |
6 |
.my-form button:focus { |
7 |
background: var(--bgFormElsFocus); |
8 |
}
|
9 |
|
10 |
.my-form select:focus, |
11 |
.my-form input:focus, |
12 |
.my-form textarea:focus { |
13 |
transform: scale(1.02); |
14 |
}
|
Agregar iconos personalizados
Todos los elementos requeridos contienen un icono (asterisco) ubicado en la esquina central derecha:



Del mismo modo, la selección también contiene un icono personalizado (flecha) ubicado en la esquina central derecha:



Esto lo logramos aplicando un icono SVG como imagen de fondo:
1 |
.my-form *:required, |
2 |
.my-form select { |
3 |
background-repeat: no-repeat; |
4 |
background-position: center right 12px; |
5 |
background-size: 15px 15px; |
6 |
}
|
7 |
|
8 |
.my-form *:required { |
9 |
background-image: url(asterisk.svg); |
10 |
}
|
11 |
|
12 |
.my-form select { |
13 |
background-image: url(down.svg); |
14 |
}
|
Dar estilo a los botones
Como ya se ha mencionado antes, en nuestro formulario tenemos dos tipos de botones: un botón de envío y un botón de reinicio. Si vuelves a visitar el marcado del formulario, notarás que cada uno de esos botones contiene dos elementos: el elemento .back y el elemento .front.
Por defecto solo aparece .front:



Cuando pasamos el cursor sobre un botón, o cuando está enfocado, suceden cosas mágicas. Específicamente, su color de fondo cambia, el elemento secundario .front desaparece y, al mismo tiempo, el elemento secundario .back aparece con una animación deslizante:
Estos son los estilos responsables de ese comportamiento:
1 |
/*CUSTOM VARIABLES HERE*/
|
2 |
|
3 |
.my-form .btn-grid { |
4 |
position: relative; |
5 |
overflow: hidden; |
6 |
transition: filter 0.2s; |
7 |
}
|
8 |
|
9 |
.my-form button:enabled:hover, |
10 |
.my-form button:focus { |
11 |
background: var(--bgFormElsFocus); |
12 |
}
|
13 |
|
14 |
.my-form button > * { |
15 |
display: inline-block; |
16 |
width: 100%; |
17 |
transition: transform 0.4s ease-in-out; |
18 |
}
|
19 |
|
20 |
.my-form button .back { |
21 |
position: absolute; |
22 |
left: 50%; |
23 |
top: 50%; |
24 |
transform: translate(-110%, -50%); |
25 |
}
|
26 |
|
27 |
.my-form button:enabled:hover .back, |
28 |
.my-form button:focus .back { |
29 |
transform: translate(-50%, -50%); |
30 |
}
|
31 |
|
32 |
.my-form button:enabled:hover .front, |
33 |
.my-form button:focus .front { |
34 |
transform: translateX(110%); |
35 |
}
|
5. Crear una casilla de verificación personalizada
Si vuelves a mirar el marcado dentro del quinto elemento de la lista, verás que el valor de id de la casilla de verificación coincide con el valor for de la etiqueta. Eso crea una asociación entre los dos elementos que nos da la capacidad de construir una casilla de verificación personalizada.
Como primer paso, ocultamos visualmente la casilla de verificación predeterminada:
1 |
.my-form input[type="checkbox"] { |
2 |
position: absolute; |
3 |
left: -9999px; |
4 |
}
|
Luego, aprovechamos las etiquetas de los pseudo-elementos :: before y :: after para generar nuestra propia casilla de verificación.
Entonces, primero usamos el pseudo-elemento :: before para configurar su estado no verificado:



Y luego el pseudo-elemento :: after junto con la pseudo-clase: check para implementar su estado verificado:



Como hicimos con los otros elementos de formulario, agregamos un estilo adicional cuando la casilla de verificación está enfocada. Por último, es aconsejable asegurarse de que los usuarios puedan acceder a nuestro formulario a través de la navegación por teclado.
Echa un vistazo a los estilos asociados a continuación:
1 |
/*CUSTOM VARIABLES HERE*/
|
2 |
|
3 |
.my-form input[type="checkbox"] + label { |
4 |
position: relative; |
5 |
display: inline-block; |
6 |
padding-left: 2rem; |
7 |
transition: background 0.3s cubic-bezier(0.57, 0.21, 0.69, 1.25); |
8 |
}
|
9 |
|
10 |
.my-form input[type="checkbox"]:focus + label { |
11 |
background: var(--bgFormElsFocus); |
12 |
}
|
13 |
|
14 |
.my-form input[type="checkbox"] + label::before, |
15 |
.my-form input[type="checkbox"] + label::after { |
16 |
content: ''; |
17 |
position: absolute; |
18 |
}
|
19 |
|
20 |
.my-form input[type="checkbox"] + label::before { |
21 |
left: 0; |
22 |
top: 6px; |
23 |
width: 18px; |
24 |
height: 18px; |
25 |
border: 2px solid var(--white); |
26 |
}
|
27 |
|
28 |
.my-form input[type="checkbox"]:checked + label::before { |
29 |
background: var(--red); |
30 |
}
|
31 |
|
32 |
.my-form input[type="checkbox"]:checked + label::after { |
33 |
left: 7px; |
34 |
top: 7px; |
35 |
width: 6px; |
36 |
height: 14px; |
37 |
border-bottom: 2px solid var(--white); |
38 |
border-right: 2px solid var(--white); |
39 |
transform: rotate(45deg); |
40 |
}
|
41 |
|
42 |
@media screen and (min-width: 541px) { |
43 |
.my-form input[type="checkbox"] + label::before { |
44 |
top: 50%; |
45 |
transform: translateY(-50%); |
46 |
}
|
47 |
|
48 |
.my-form input[type="checkbox"]:checked + label::after { |
49 |
top: 3px; |
50 |
}
|
51 |
}
|
Vale la pena mencionar que también podríamos haber usado algunos iconos personalizados para crear la casilla de verificación deseada.
6. Alternar el estado de los botones
Inicialmente, los botones del formulario están deshabilitados. Eso significa que no podemos hacer clic en ellos o seleccionarlos:



En nuestro CSS agregamos algunos estilos específicamente dirigidos a estos elementos deshabilitados, dejando en claro al usuario que no pueden interactuar con ellos:
1 |
.my-form *:disabled { |
2 |
cursor: default; |
3 |
filter: blur(2px); |
4 |
}
|
Los botones se activan tan pronto como se marca la casilla de verificación:



El código JavaScript que maneja esta funcionalidad se muestra a continuación:
1 |
const checkbox = document.querySelector('.my-form input[type="checkbox"]'); |
2 |
const btns = document.querySelectorAll(".my-form button"); |
3 |
|
4 |
checkbox.addEventListener("change", function() { |
5 |
const checked = this.checked; |
6 |
for (const btn of btns) { |
7 |
checked ? (btn.disabled = false) : (btn.disabled = true); |
8 |
}
|
9 |
});
|
Conclusión
¡Eso es todo amigos! ¡Esto es lo que hemos creado!
En este tutorial, cubrimos muchos consejos y trucos diferentes para diseñar elementos de formulario de contacto. Aunque nos concentramos en un diseño de modo oscuro, puedes aplicar cualquier tipo de diseño de interfaz de usuario utilizando estos mismos principios.
Esperamos que hayas disfrutado el formulario de contacto que hemos creado y lo uses como inspiración para desarrollar tus propios formularios. ¡Como siempre, gracias por leer!
Obtén más información sobre el diseño de formularios web


AccesibilidadCómo hacer casillas de verificación y botones de selección accesibles y personalizadosSami Keijonen

Diseño de formularioMejores prácticas para mostrar errores de formularioAdi Purdila

FlexboxCómo crear un formulario receptivo con FlexboxGeorge Martsoukos

BootstrapCrear un formulario de contacto Bootstrap usando PHP y AJAXAaron Vanston





