Formularios HTML
Introducción

¿Qué Es un Formulario en HTML?
Un formulario en HTML es una estructura definida con la etiqueta <form>
que permite a los usuarios ingresar y enviar datos a un servidor para su procesamiento. Incluye elementos interactivos como campos de texto, menús desplegables, casillas de verificación y botones. Los formularios son esenciales para la interacción entre usuarios y páginas web, ya que facilitan la recolección de información y otras funciones interactivas.
¿Por Qué Son Importantes en Desarrollo Web?
Los formularios son esenciales en el desarrollo web porque permiten la interacción entre el usuario y el sitio web. Sin formularios, una página web sería simplemente informativa y estática. Son la base para:
- Recoger datos del usuario.
- Iniciar sesiones (login).
- Enviar mensajes o solicitudes.
- Procesar pagos en línea.
- Realizar búsquedas internas.
- Registrar usuarios.
Además, los formularios permiten aplicar validaciones, control de seguridad (como tokens CSRF), y mejoras de accesibilidad.
Estructura Básica de un Formulario
El Elemento <form>
El elemento principal de un formulario es la etiqueta <form>
. Todo lo que esté dentro de esta etiqueta se considera parte del formulario.
<form action="/procesar-formulario" method="POST">
<!-- Elementos del formulario -->
</form>
Anatomía Completa del Elemento <form>
<form
<!-- Atributos de la etiqueta <form> -->
action="/procesar-datos.php"
method="POST"
enctype="multipart/form-data"
name="formulario-contacto"
id="form-contacto"
target="_self"
autocomplete="on"
novalidate="false"
accept-charset="UTF-8">
<!-- Entradas del Formulario -->
<label for="nombre">Nombre:</label>
<input type="text" id="nombre" name="nombre">
<!-- Lista Desplegable -->
<label for="cars">Choose a car:</label>
<select id="cars" name="cars">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="fiat">Fiat</option>
<option value="audi">Audi</option>
</select>
<!-- Entrada Multilínea -->
<textarea name="message" rows="10" cols="30">
The cat was playing in the garden.
</textarea>
<!-- Botón de Envío -->
<button type="button" onclick="alert('Hello World!')">Click Me!</button>
</form>
Atributos del Formulario <form>
Qué Son los Atributos del Formulario <form>
Los atributos del elemento <form>
en HTML son características que se incluyen en esta etiqueta para especificar el comportamiento del formulario en una página web. Estos atributos guían al navegador sobre cómo manejar los datos ingresados por el usuario y cómo enviarlos al servidor o procesarlos.
A continuación, se presenta una explicación completa y clara de los principales atributos del elemento <form>
en HTML
action
El atributo action
en los formularios HTML especifica la URL o el destino al que se enviarán los datos del formulario al ser enviado por el usuario. Es uno de los atributos clave del elemento <form>
.
Sintaxis Básica de action
<form action="URL_destino" method="POST">
<!-- campos del formulario -->
</form>
Valores que Puede Tomar action
URL absoluta:
<form action="https://ejemplo.com/procesar.php">
<!-- campos del formulario -->
</form>
URL relativa:
<form action="/procesar-formulario">
<form action="procesar.php">
<form action="../handlers/contact.php">
- La
ruta /procesar-formulario
representa una dirección absoluta desde la raíz del dominio, asegurando que, independientemente de la ubicación del formulario dentro de las subcarpetas del sitio web, los datos siempre se envíen a la URLhttps://ejemplo.com/procesar-formulario
. -
procesar.php
es una ruta relativa que apunta a un archivo del mismo nombre ubicado en el mismo directorio que el archivo HTML del formulario, al cual se enviarán los datos para su procesamiento. - La ruta relativa
../handlers/contact.php
señala que, desde la ubicación del archivo HTML del formulario, se debe retroceder un nivel en la estructura de directorios, indicado por..
, a continuación, se ingresa a la carpetahandlers/
y se accede al archivocontact.php
ubicado dentro de ella.
Página actual:
<form action="">
<!-- Se envía a la misma página actual -->
</form>
Cuando un formulario con el atributo action=""
(o si el atributo action
simplemente se omite), significa que el formulario, al ser enviado, enviará sus datos a la misma URL de la página donde se encuentra el formulario.
method
La propiedad method
en los formularios HTML especifica cómo se enviarán los datos del formulario al servidor. Es uno de los atributos más importantes del elemento en conjunto con action
.
Valores principales de method
El atributo method en la etiqueta <form>
es crucial porque le dice al navegador cómo debe enviar los datos del formulario al servidor. Los dos valores principales y más usados son get
y post
.
get
Características:
- Los datos se envían como parámetros en la URL.
- Visible en la barra de direcciones del navegador.
- Limitado a aproximadamente 2048 caracteres.
- Los datos quedan en el historial del navegador.
- Puede ser marcado como favorito.
- Idempotente (no modifica datos en el servidor).
- Si no se especifica el atributo
method
, el formulario usaráget
por defecto.
Sintaxis básica de get
:
<form method="GET" action="procesar.php">
<input type="text" name="nombre">
<input type="submit" value="Enviar">
</form>
Ejemplo de una URL resultante:
https://ejemplo.com/procesar.php?nombre=Juan&apellido=Pérez
Usar get
cuando:
- Se solicita información del servidor.
- Los datos no son sensibles.
- Se quiere que la URL sea compartible.
- Se realiza búsquedas.
- Los datos son pequeños.
post
Características:
- Los datos se envían en el cuerpo de la petición HTTP.
- No son visibles en la URL.
- Sin límite práctico de tamaño.
- Más seguro para datos sensibles.
- No queda en el historial del navegador.
- No puede ser marcado como favorito.
- Puede modificar datos en el servidor.
Sintaxis básica de post
:
<form method="POST" action="procesar.php">
<input type="text" name="nombre">
<input type="password" name="contraseña">
<input type="submit" value="Enviar">
</form>
Utilizar post
cuando:
- Envío de datos sensibles (contraseñas, información personal).
- Modificación datos en el servidor.
- Subir archivos.
- Los datos son extensos.
- Realización de transacciones.
Ejemplo con get
y post
Formulario con método GET
Formulario con método POST
<div class="form-method">
<div class="container-method">
<!-- Formulario GET -->
<div class="section-method get-method">
<span class="indicator-method get-indicator-method">GET</span>
<p class="h2-method">Formulario con método GET</p>
<form method="GET" action="#" onsubmit="return handleGetSubmit(event)">
<div class="group-method">
<label for="search">Término de búsqueda:</label>
<input type="text" id="search" name="search" placeholder="Buscar productos...">
</div>
<div class="group-method">
<label for="category">Categoría:</label>
<select id="category" name="category">
<option value="">Todas</option>
<option value="electronics">Electrónicos</option>
<option value="clothing">Ropa</option>
<option value="books">Libros</option>
</select>
</div>
<div class="group-method">
<label for="price_min">Precio mínimo:</label>
<input type="text" id="price_min" name="price_min" placeholder="0">
</div>
<input type="submit" value="Buscar">
</form>
</div>
<!-- Formulario POST -->
<div class="section-method post-method">
<span class="indicator-method post-indicator-method">POST</span>
<p class="h2-method">Formulario con método POST</p>
<form method="POST" action="#" onsubmit="return handlePostSubmit(event)">
<div class="group-method">
<label for="username">Nombre de usuario:</label>
<input type="text" id="username" name="username" required>
</div>
<div class="group-method">
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
</div>
<div class="group-method">
<label for="password">Contraseña:</label>
<input type="password" id="password" name="password" required>
</div>
<div class="group-method">
<label for="bio">Biografía:</label>
<textarea id="bio" name="bio" rows="4" placeholder="Cuéntanos sobre ti..."></textarea>
</div>
<input type="submit" value="Registrarse">
</form>
</div>
</div>
</div>
.form-method {
font-family: Arial, sans-serif;
padding: 20px;
background-color: #f5f5f5;
min-height: 100vh;
}
.form-method .container-method {
max-width: 1200px;
margin: 0 auto;
display: grid;
grid-template-columns: 1fr;
gap: 30px;
}
.form-method .section-method {
background: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
border: 2px solid #e0e0e0;
}
.form-method .h1-method {
font-size: 2em;
font-weight: bold;
color: #333;
margin: 0.67em 0;
text-align: center;
}
.form-method .h2-method {
font-size: 1.5em;
font-weight: bold;
color: #333;
margin-top: 0;
padding-bottom: 10px;
border-bottom: 2px solid #4CAF50;
}
.form-method .h4-method {
font-size: 1.17em;
font-weight: bold;
color: #333;
margin: 1.33em 0;
}
.form-method .section-method h2 {
color: #333;
margin-top: 0;
padding-bottom: 10px;
border-bottom: 2px solid #4CAF50;
}
.form-method .get-method {
border-left: 4px solid #2196F3;
background-color: #f3f9ff;
}
.form-method .post-method {
border-left: 4px solid #FF9800;
background-color: #fff8f0;
}
.form-method .group-method {
margin-bottom: 15px;
}
.form-method label {
display: block;
margin-bottom: 5px;
font-weight: bold;
color: #555;
}
.form-method input[type="text"],
.form-method input[type="email"],
.form-method input[type="password"],
.form-method textarea,
.form-method select {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 14px;
box-sizing: border-box;
}
.form-method input[type="submit"] {
background-color: #4CAF50;
color: white;
padding: 12px 30px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s;
}
.form-method input[type="submit"]:hover {
background-color: #45a049;
}
.form-method .indicator-method {
display: inline-block;
padding: 5px 10px;
border-radius: 20px;
font-size: 12px;
font-weight: bold;
color: white;
margin-bottom: 15px;
}
.form-method .get-indicator-method {
background-color: #2196F3;
}
.form-method .post-indicator-method {
background-color: #FF9800;
}
.form-method .result-method {
background-color: #f0f8ff;
border: 1px solid #b0d4f1;
border-radius: 5px;
padding: 15px;
margin-top: 15px;
min-height: 50px;
}
.form-method .table-method {
width: 100%;
border-collapse: collapse;
margin-top: 15px;
}
.form-method .table-method th,
.form-method .table-method td {
border: 1px solid #ddd;
padding: 12px;
text-align: left;
}
.form-method .table-method th {
background-color: #f2f2f2;
font-weight: bold;
}
.form-method .table-method tr:nth-child(even) {
background-color: #f9f9f9;
}
.form-method .info-method {
background-color: #e8f5e8;
padding: 15px;
border-radius: 5px;
margin-top: 15px;
border-left: 4px solid #4CAF50;
}
.form-method .warning-method {
background-color: #fff3cd;
padding: 15px;
border-radius: 5px;
margin-top: 15px;
border-left: 4px solid #ffc107;
}
.form-method .code-method {
background-color: #f4f4f4;
padding: 15px;
border-radius: 5px;
margin-top: 15px;
font-family: monospace;
white-space: pre-wrap;
overflow-x: auto;
border: 1px solid #ddd;
}
/* Responsive - Bootstrap lg breakpoint: 992px */
@media (min-width: 992px) {
.form-method .container-method {
grid-template-columns: 1fr 1fr;
gap: 40px;
}
.form-method .section-method {
padding: 40px;
}
}
/* Responsive para tablets */
@media (max-width: 768px) {
.form-method {
padding: 10px;
}
.form-method .section-method {
padding: 20px;
}
}
/* Responsive para móviles */
@media (max-width: 576px) {
.form-method .section-method {
padding: 15px;
}
.form-method input[type="submit"] {
width: 100%;
}
}
Consejos Adicionales de Buenas Prácticas
- No depende
get
nicamente del método para garantizar la seguridad: Aunque el método
oculta los datos en la URL, no los cifra por sí mismo. Para proteger datos sensibles de manera efectiva, es fundamental implementar HTTPS en todo el sitio web, identificable por el ícono de candado en la barra de direcciones. HTTPS asegura la encriptación de toda la comunicación entre el navegador y el servidor.post
- Validación en el cliente y en el servidor: Es recomendable emplear la validación HTML5 (atributos como
required
,type="email"
,pattern
, entre otros) para mejorar la experiencia del usuario. Sin embargo, siempre debe complementarse con una validación en el servidor, ya que usuarios malintencionados pueden omitir las restricciones del navegador. - Evitar la confusión de conceptos: No se debe utilizar el método
get
para enviar datos sensibles bajo la suposición de que un formulario es suficiente. Asimismo, no es apropiado usarpost
para búsquedas simples que podrían ser compartibles. La selección del método debe reflejar claramente la intención del formulario.
enctype
Introducción a enctype
enctype
es uno de los atributos más relevantes, aunque a menudo poco comprendido, de los formularios HTML, significa encoding type o tipo de codificación. Este atributo especifica cómo se codifican los datos del formulario antes de enviarlos al servidor. Su comprensión es esencial, especialmente para gestionar archivos, datos binarios o formularios complejos.
Tipos de Codificación Soportados
Existen tres valores principales para el atributo enctype
: application/x-www-form-urlencoded
, multipart/form-data
y text/plain
:
application/x-www-form-urlencoded
Este es el tipo de codificación predeterminado que se aplica automáticamente si no se especifica un enctype
explícito.
Características:
- Codifica los datos del formulario como pares clave-valor unidos por
&
. - Los espacios se convierten en signos
+
. - Los caracteres especiales se codifican usando el formato de porcentaje (URL encoding), es decir, secuencias escapadas (
%20
para espacios, etc). - Los datos se envían en una sola línea .
Ejemplo de uso:
<form action="/procesar" method="POST" enctype="application/x-www-form-urlencoded">
<input type="text" name="nombre" value="Juan Pérez">
<input type="email" name="email" value="juan@ejemplo.com">
<button type="submit">Enviar</button>
</form>
Datos enviados:
nombre=Juan+P%C3%A9rez&email=juan%40ejemplo.com
Este formato es el más eficiente para datos puramente de texto.
multipart/form-data
Este tipo de codificación es esencial cuando el formulario incluye archivos o grandes cantidades de datos binarios.
Características:
- Divide los datos en múltiples partes separadas por delimitadores únicos.
- Cada campo del formulario se envía como una parte separada.
- Conserva el formato original de los archivos y previene su codificación, garantizando que se transmitan al servidor sin alteraciones.
- Es la única opción viable para subir archivos (
<input type="file" />
). - Cada parte puede contener texto o datos binarios (como imágenes, PDF, etc).
text/plain
Esta codificación envía los datos como texto plano sin codificación especial.
Características:
- No codifica caracteres especiales.
- Cada par clave-valor aparece en una línea separada.
- Principalmente usado para depuración o casos muy específicos.
- No es adecuado para datos que contienen caracteres especiales.
Ejemplo de uso:
<form action="/debug" method="POST" enctype="text/plain">
<input type="text" name="mensaje" value="Hola mundo">
<input type="text" name="autor" value="Desarrollador">
<button type="submit">Enviar</button>
</form>
Datos enviados:
mensaje=Hola mundo
autor=Desarrollador
Consideraciones Técnicas para enctype
Rendimiento:
-
application/x-www-form-urlencoded
es más eficiente para datos pequeños. -
multipart/form-data
tiene overhead adicional, es necesario para archivos. -
text/plain
es el más simple pero menos flexible.
Seguridad:
- Todos los tipos de
enctype
deben validarse en el servidor. -
multipart/form-data
requiere validación especial de tipos de archivo. - La codificación no proporciona seguridad por sí misma.
Compatibilidad:
-
application/x-www-form-urlencoded
tiene soporte universal. -
multipart/form-data
está ampliamente soportado en navegadores modernos. -
text/plain
es menos común en aplicaciones de producción.
Mejores Prácticas enctype
- Especificar siempre el
enctype
explícitamente cuando usesmultipart/form-data
. - Validar el tipo de contenido en el servidor independientemente del
enctype
. - Usa
multipart/form-data
solo cuando sea necesario debido a su overhead. - Implementa validación tanto en cliente como en servidor.
- Considera el tamaño máximo de datos que tu servidor puede manejar.
- Documenta qué tipo de
enctype
espera cada endpoint.
name
Dentro de las diversas propiedades que definen el comportamiento de un formulario <form>
, el atributo name
emerge como un identificador crucial, aunque a menudo subestimado o malentendido por los desarrolladores menos experimentados.
Definición y Propósito name
El atributo name de la etiqueta <form>
establece un identificador único para el formulario dentro del documento HTML. Este identificador permite referenciar el formulario específico desde JavaScript, CSS (en casos limitados) y otras tecnologías del lado del cliente.
<form name="loginForm" method="post" action="/login">
<!-- contenido del formulario -->
</form>
Especificaciones y Estándares name
HTML 4.01 y Versiones Anteriores para name
En HTML 4.01, el atributo name
era ampliamente utilizado y formaba parte integral de la especificación. Los formularios se identificaban principalmente a través de este atributo, y era común encontrar código JavaScript que hacía referencia a formularios usando document.forms["nombreFormulario"]
o document.forms.nombreFormulario
.
HTML5 y Estándares Modernos para name
Con la introducción de HTML5, el atributo name
para formularios se considera obsoleto. La especificación HTML5 del W3C recomienda el uso del atributo id
en su lugar para identificar elementos únicos en el documento. Sin embargo, por razones de compatibilidad hacia atrás, la mayoría de los navegadores modernos aún soportan el atributo name
en formularios.
Diferencias entre name
e id
Propósito y Alcance de name e id
-
name
: Tradicionalmente usado para identificar formularios en el contexto del DOM y para el envío de datos. -
id
: Identificador único universal que puede ser usado por CSS, JavaScript y enlaces de anclaje.
Restricciones del Nombre
-
name
: Permite algunos caracteres especiales y puede no ser único en el documento. -
id
: Debe ser único en todo el documento y sigue reglas más estrictas de nomenclatura.
Ejemplo Comparativo
<!-- Enfoque tradicional (HTML 4.01) -->
<form name="loginForm" method="post" action="/register">
<input type="text" name="username" placeholder="Usuario">
<input type="email" name="email" placeholder="Email">
<input type="submit" value="Registrar">
</form>
<!-- Enfoque moderno (HTML5) -->
<form id="loginForm" method="post" action="/register">
<input type="text" name="username" placeholder="Usuario">
<input type="email" name="email" placeholder="Email">
<input type="submit" value="Registrar">
</form>
Acceso desde JavaScript
- Métodos de Acceso con
name
:// Acceso directo por nombre var formulario = document.forms['loginForm']; // Acceso a través de la propiedad forms var formulario = document.forms.loginForm; // Método más explícito var formulario = document.forms.namedItem('loginForm');
- Métodos de Acceso con
id
:// Usando id (método recomendado) var formulario = document.getElementById('loginForm'); var formulario = document.querySelector('#loginForm'); // Usando name (método legacy) var formulario = document.forms['loginForm'];
id
¿Qué Es el Atributo id
?
En HTML, el atributo id
es un identificador único que puede aplicarse a prácticamente cualquier elemento, incluido <form>
. Este identificador:
- Sirve para diferenciar de forma única a ese elemento respecto a los demás en la misma página.
- Permite referenciarlo fácilmente desde CSS, JavaScript o incluso otras etiquetas HTML que necesiten hacer referencia directa a ese formulario.
var formulario = document.getElementById('loginForm');
var formulario = document.querySelector('#loginForm');
En este caso, loginForm
es el valor del id
, y debe ser único dentro de todo el documento HTML.
¿Por Qué Es Importante el id en un <form>?
- Manipulación con JavaScript: Con un
id
, se puede acceder rápidamente al formulario desde JavaScript utilizando métodos como:const formulario = document.getElementById('registroUsuario');
- Validar campos antes de enviar.
- Modificar dinámicamente el contenido.
- Escuchar eventos como
submit
.
- Asociación con otras etiquetas: Algunas etiquetas de HTML pueden asociarse a un formulario aunque estén fuera de la estructura interna del
<form>
, usando el atributoid
del formulario:<form id="loginForm"> <!-- campos del formulario --> </form> <button type="submit" form="loginForm">Enviar</button>
<form>
, gracias al atributoform="loginForm"
, el botón funciona como si estuviera dentro. - Aplicación de estilos CSS: Al usar el
id
en CSS se pueden definir estilos específicos para un formulario:#registroUsuario { background-color: #f9f9f9; padding: 20px; }
id
es útil cuando se quiere afectar solo a un formulario concreto.
Buenas Prácticas de Uso del Atributo id
- Unicidad: cada
id
debe ser único en todo el documento. - Nombres descriptivos: usar nombres que describan la función del formulario, como registroUsuario, contactoForm, etc.
- Evitar caracteres especiales y espacios: deben usarse letras, números, guiones o guiones bajos, y empezar por una letra.
target
Qué Es el Atributo target
El atributo target
es un atributo global que se puede usar en formularios HTML. Su función principal es indicar el destino donde se debe mostrar la respuesta después de que el formulario es enviado.
En términos más técnicos: Cuando se envía un formulario HTML, el navegador realiza una solicitud HTTP (usualmente get
o post
) al recurso especificado en el atributo action
del formulario. El atributo target
le dice al navegador en qué ventana o marco (frame
) debe cargar la respuesta del servidor.
Valores Posibles del Atributo target
-
_blank
: Abre en nueva ventana o pestaña. -
_self
: Abre en el mismo frame (valor por defecto). -
_parent
: Abre en el frame padre. -
_top
: Abre en la ventana completa, cancelando todos los frames. -
nombre_de_frame
: Si existe unframe
oiframe
con el atributoname="nombre_de_frame"
, la respuesta se mostrará en ese frame específico.
Nota: si se especifica un nombre de frame que no existe, el navegador puede abrir una nueva ventana con ese nombre y mostrar allí la respuesta.
Ejemplo Práctico target
Se tiene un formulario para buscar productos:
<form action="/buscar" method="get" target="_blank">
<input type="text" name="q" placeholder="Buscar producto">
<button type="submit">Buscar</button>
</form>
En este ejemplo, cuando el usuario hace clic en Buscar, la solicitud se enviará al servidor y el resultado se abrirá en una nueva pestaña (_blank
).
Integración con iframe
<iframe name="resultado" width="600" height="300"></iframe>
<form action="/procesar" method="post" target="resultado">
<input type="text" name="dato">
<button type="submit">Enviar</button>
</form>
Aquí, el formulario tiene target="resultado"
, por lo que la respuesta del servidor se mostrará dentro del iframe que tiene name="resultado"
.
Consideraciones y Buenas Prácticas target
- Si no se indica el atributo
target
, se asume por defecto_self
. - Usar
_blank
puede mejorar la experiencia del usuario al mantener la página original abierta, pero se debe hacer con cuidado para evitar problemas de usabilidad. - El uso de nombres de frames depende de que estos frames o iframes existan en la estructura HTML y tengan correctamente configurado el atributo
name
. - Actualmente, en sitios modernos se tiende a controlar esto con JavaScript y AJAX para una mejor experiencia sin recargar la página, aunque
target
sigue siendo útil en algunos escenarios.
Consideraciones de Seguridad target
Riesgo de Ataques de Tabnabbing
Cuando se usa target="_blank"
para abrir la respuesta de un formulario en una nueva pestaña, el navegador por defecto mantiene una referencia desde la nueva página a la página original (a través de window.opener
en JavaScript).
Un sitio malicioso cargado en esa nueva pestaña podría aprovechar esa referencia para cambiar la ubicación de la página original y redirigirla a otro sitio falso, intentando engañar al usuario.
Cómo Mitigar el Tabnabbing
<!-- Problemático -->
<form action="external-site.com" target="_blank">
<!-- contenido -->
</form>
<!-- Seguro -->
<form action="external-site.com" target="_blank" rel="noopener noreferrer">
<!-- contenido -->
</form>
Nota: En un <form>
, el atributo rel
no es formal. Así que, cuando se necesita seguridad total, se recomienda:
- Preferir abrir la respuesta en la misma ventana
(target="_self")
. - Si se necesita abrir en una nueva ventana, evaluar si es posible hacerlo con JavaScript controlado, evitando referencias a
window.opener
.
Dependencia de Nombres de frames
Cuando se usa un nombre de frame como valor de target (por ejemplo target="resultado"), se debe asegurar que:
- El
<iframe>
o<frame>
tiene definido correctamentename="resultado"
. - El frame "resultado" exista.
- El contenido cargado en ese frame sea confiable.
Integridad del Contenido Cargado
Al cargar respuestas de formularios en frames o ventanas nuevas:
- Verificar siempre que el servidor responda contenido seguro (por ejemplo, usando HTTPS).
- Asegurarse de que las páginas no permitan ser cargadas en frames externos si no es necesario, para evitar ataques como clickjacking.
Esto puede configurarse en el servidor usando cabeceras HTTP como:X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'self';
Control del Flujo y la Lógica del Formulario
Aunque target
solo define dónde mostrar la respuesta, se debe evitar confiar únicamente en el cliente para validar datos. Toda validación crítica (autenticación, autorización, reglas de negocio) debe hacerse siempre en el servidor, porque el cliente puede modificar el HTML o los valores enviados.
Inyección de Contexto y el Atributo target
en <form>
La inyección de contexto ocurre cuando un atacante logra incluir contenido malicioso en una parte de la página web o en la respuesta del servidor, aprovechando que el navegador interpreta ese contenido en un contexto distinto al esperado.
En el caso de formularios HTML, aunque el atributo target
por sí mismo no es directamente vulnerable a inyección de contexto, puede facilitar ataques cuando:
- Se usa
target
para cargar la respuesta del formulario dentro de un<iframe>
o<frame>
cuyo contenido proviene de datos no validados. - El servidor devuelve HTML o scripts que incluyen valores enviados por el usuario sin escaparlos correctamente.
Así, un atacante podría inyectar código que se ejecuta en el navegador del usuario (como JavaScript malicioso), alterando la funcionalidad de la página o robando datos
Cómo Prevenir la Inyección de Contexto
- Sanitizar entradas de usuario: Escapar y validar todos los datos de entrada en el servidor antes de devolverlos al cliente.
// Vulnerable const targetName = userInput; // Sin validación form.target = targetName; // Seguro const targetName = userInput.replace(/[^a-zA-Z0-9_]/g, ''); form.target = targetName;
- Evitar construir respuestas HTML dinámicamente con datos de usuarios sin filtrado.
- Usar cabeceras de seguridad como:
Content-Security-Policy X-Content-Type-Options
- Controlar en qué
target
se carga la respuesta para no exponer el sitio a marcos externos.
autocomplete
El atributo autocomplete
es una característica fundamental de HTML que permite a los desarrolladores controlar cómo los navegadores web manejan el autocompletado de campos en formularios. Esta funcionalidad mejora significativamente la experiencia del usuario al reducir la cantidad de texto que debe escribir manualmente, especialmente en formularios recurrentes como registros, inicios de sesión y procesos de compra.
¿Qué es el Autocompletado?
El atributo autocomplete
es una característica de los formularios HTML que permite a los navegadores guardar y rellenar automáticamente los valores de los campos de entrada que un usuario ya ha utilizado antes.
Esto significa que si un usuario ya llenó su nombre, correo electrónico o dirección en un formulario anterior, el navegador puede sugerir y completar esos mismos datos en formularios futuros, mejorando la experiencia de usuario y reduciendo el tiempo de escritura.
Sintaxis Básica de autocomplete
- Se puede usar en la etiqueta
<form>
: Esto define si todos los campos del formulario permitirán autocompletado o no. - Se puede usar en campos individuales
<input>
,<textarea>
o<select>
: En este caso, se controla de forma más específica.
Ejemplo:
<!-- En el formulario completo -->
<form autocomplete="on">
<!-- contenido del formulario -->
</form>
<!-- En campos específicos -->
<input type="text" name="username" autocomplete="username">
<input type="email" name="email" autocomplete="email">
Valores Principales de autocomplete
Valores Básicos
-
on
: Habilita el autocompletado para el formulario o campo específico. Es el valor por defecto en la mayoría de los navegadores. -
off
: Desactiva completamente el autocompletado. Útil para campos sensibles como códigos de seguridad o información confidencial.
Se usa, por ejemplo, en formularios sensibles:- Formularios de inicio de sesión.
- Formularios de pago.
- Formularios de datos personales delicados.
<form autocomplete="off"> <input type="text" name="usuario"> <input type="password" name="contrasena"> </form>
Ejemplo Combinado:
<form autocomplete="on">
<input type="text" name="nombre">
<input type="email" name="correo" autocomplete="off">
</form>
En este ejemplo:
- El formulario permite autocompletado en general.
- El campo de correo lo desactiva específicamente.
Valores Específicos (Tokens)
HTML5 introduce tokens específicos que indican exactamente qué tipo de información espera cada campo. Estos tokens ayudan a los navegadores a hacer sugerencias más precisas.
Además de on
y off
, en campos individuales se pueden usar valores específicos para indicar el tipo de dato:
-
autocomplete="name"
-
autocomplete="email"
-
autocomplete="username"
-
autocomplete="new-password"
-
autocomplete="current-password"
-
autocomplete="street-address"
-
autocomplete="postal-code"
-
autocomplete="tel"
-
autocomplete="cc-number"
(tarjeta de crédito) - Entre otros.
Esto ayuda al navegador a entender qué datos ofrecer en sus sugerencias.
Ejemplo:
<form autocomplete="on">
<input type="text" name="nombre" autocomplete="name">
<input type="email" name="correo" autocomplete="email">
<input type="password" name="contrasena" autocomplete="new-password">
</form>
Otros valores:
- Información Personal
<input type="text" name="nombre" autocomplete="given-name"> <input type="text" name="apellido" autocomplete="family-name"> <input type="text" name="nombre-completo" autocomplete="name"> <input type="email" name="email" autocomplete="email"> <input type="tel" name="telefono" autocomplete="tel">
- Información de Dirección
<input type="text" name="calle" autocomplete="street-address"> <input type="text" name="ciudad" autocomplete="address-level2"> <input type="text" name="estado" autocomplete="address-level1"> <input type="text" name="codigo-postal" autocomplete="postal-code"> <input type="text" name="pais" autocomplete="country">
- Información de Pago
<input type="text" name="numero-tarjeta" autocomplete="cc-number"> <input type="text" name="nombre-tarjeta" autocomplete="cc-name"> <input type="text" name="expiracion" autocomplete="cc-exp"> <input type="text" name="cvv" autocomplete="cc-csc">
- Credenciales de Acceso
<input type="text" name="usuario" autocomplete="username"> <input type="password" name="clave" autocomplete="current-password"> <input type="password" name="nueva-clave" autocomplete="new-password">
Modificadores Avanzados
- Secciones: El modificador section- permite agrupar campos relacionados, especialmente útil cuando un formulario maneja múltiples conjuntos de la misma información.
<!-- Dirección de envío --> <input type="text" name="envio-calle" autocomplete="section-shipping street-address"> <input type="text" name="envio-ciudad" autocomplete="section-shipping address-level2"> <!-- Dirección de facturación --> <input type="text" name="factura-calle" autocomplete="section-billing street-address"> <input type="text" name="factura-ciudad" autocomplete="section-billing address-level2">
- Contactos Específicos: Los modificadores
home
,work
,mobile
yfax
especifican el contexto de la información de contacto.<input type="tel" name="tel-casa" autocomplete="home tel"> <input type="tel" name="tel-trabajo" autocomplete="work tel"> <input type="tel" name="tel-movil" autocomplete="mobile tel"> <input type="email" name="email-trabajo" autocomplete="work email">
Casos de Uso Prácticos autocomplete
Formulario de Registro Completo autocomplete
<form autocomplete="on">
<h2>Información Personal</h2>
<input type="text" name="nombre" autocomplete="given-name" placeholder="Nombre">
<input type="text" name="apellido" autocomplete="family-name" placeholder="Apellido">
<input type="email" name="email" autocomplete="email" placeholder="Email">
<input type="tel" name="telefono" autocomplete="tel" placeholder="Teléfono">
<h2>Dirección</h2>
<input type="text" name="direccion" autocomplete="street-address" placeholder="Dirección">
<input type="text" name="ciudad" autocomplete="address-level2" placeholder="Ciudad">
<input type="text" name="codigo-postal" autocomplete="postal-code" placeholder="Código Postal">
<h2>Credenciales</h2>
<input type="text" name="usuario" autocomplete="username" placeholder="Usuario">
<input type="password" name="clave" autocomplete="new-password" placeholder="Contraseña">
</form>
Formulario de Pago autocomplete
<form autocomplete="on">
<h2>Información de Pago</h2>
<input type="text" name="numero-tarjeta" autocomplete="cc-number" placeholder="Número de Tarjeta">
<input type="text" name="nombre-tarjeta" autocomplete="cc-name" placeholder="Nombre en la Tarjeta">
<input type="text" name="expiracion" autocomplete="cc-exp" placeholder="MM/AA">
<input type="text" name="cvv" autocomplete="cc-csc" placeholder="CVV">
<h2>Dirección de Facturación</h2>
<input type="text" name="direccion-factura" autocomplete="billing street-address" placeholder="Dirección">
<input type="text" name="ciudad-factura" autocomplete="billing address-level2" placeholder="Ciudad">
</form>
Este formulario es una muestra y debe considerarse que ciertos datos no deben tener habilitada la función de autocompletado.
Mejores Prácticas autocomplete
- Utilizar siempre los tokens estándar para garantizar la mejor experiencia de usuario:
<!-- Correcto --> <input type="email" name="email" autocomplete="email"> <!-- Incorrecto --> <input type="email" name="email" autocomplete="email-address">
- El autocompletado funciona bien junto con la validación HTML5:
<input type="email" name="email" autocomplete="email" required> <input type="tel" name="telefono" autocomplete="tel" pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}">
- Asegurarse de que los campos tengan etiquetas apropiadas:
<label for="email">Correo Electrónico:</label> <input type="email" id="email" name="email" autocomplete="email">
- Desactivar (off) solo cuando realmente se requiere por seguridad o privacidad.
- No confiar en que siempre funcionará igual en todos los navegadores: algunos pueden ignorar
autocomplete="off"
por decisión del usuario o del navegador.
novalidate
El navegador, de forma predeterminada, intenta ser útil y verifica que los campos obligatorios se llenen o que los formatos (como los de correo electrónico o URL) sean correctos antes de enviar la información a un servidor. Esta validación automática es muy útil, ¡pero no siempre es lo que se necesita!
Aquí es donde entra en juego la etiqueta (o más precisamente, el atributo) novalidate
en la etiqueta <form>
.
¿Qué es la Validación en Formularios Web?
Cuando se llena un formulario en una página web y se presiona el botón de "Enviar", el navegador web realiza una serie de verificaciones para asegurarse de que los datos ingresados sean válidos. Por ejemplo:
- Campos Obligatorios: Si un campo está marcado con el atributo
required
, el navegador se asegura de que no esté vacío. - Formatos Específicos: Si un campo es de tipo
email
,url
,number
, etc., el navegador verifica que el texto ingresado cumpla con el formato esperado. - Longitud Mínima/Máxima: Se puede validar que el texto tenga una longitud mínima (
minlength
) o máxima (maxlength
). - Rangos Numéricos: Para campos numéricos, se pueden establecer rangos (
min
,max
).
Si alguna de estas validaciones falla, el navegador impide que el formulario se envíe y muestra un mensaje de error al usuario, indicando qué necesita corregir. Esto se conoce como validación del lado del cliente (o "client-side validation"), ya que ocurre directamente en el navegador del usuario.
Qué Es novalidate
El atributo novalidate
, aplicable a la etiqueta <form>
en HTML,, es un atributo booleano que no requiere un valor. Su función es deshabilitar la validación automática del navegador para los campos de un formulario al momento de enviarlo, permitiendo que el formulario se envíe sin verificar restricciones como required
, pattern
o type="email"
, entre otras, antes del envío.
Cómo se Usa novalidate
El uso es muy simple: se coloca el atributo novalidate dentro de la etiqueta <form>
.
Ejemplo Básico:
<form action="/procesar-datos" method="post" novalidate>
<label for="correo">Correo electrónico:</label>
<input type="email" id="correo" name="correo" required>
<button type="submit">Enviar</button>
</form>
En este caso, aunque el campo correo es de tipo email
y es required
, el navegador no realizará ninguna comprobación automática al presionar el botón de enviar. El formulario se enviará tal cual esté.
Características importantes novalidate
- Es un atributo booleano, es decir, no necesita valor:
<form novalidate>...</form> <!-- Otra forma de configuración --> <form novalidate="novalidate">...</form>
- Solo afecta a la validación en el lado del cliente (navegador). No sustituye ni elimina la necesidad de validar los datos en el servidor.
- Es especialmente útil si se desea crear una experiencia de usuario personalizada, mostrando mensajes de error hechos a medida en lugar de los mensajes por defecto del navegador.
Comparación Práctica novalidate
<!-- SIN novalidate - El navegador valida automáticamente -->
<form>
<input type="email" required placeholder="Tu email">
<input type="number" min="18" max="100" required placeholder="Tu edad">
<button type="submit">Enviar</button>
</form>
En este ejemplo, si se intenta enviar el formulario:
- El navegador verificará que el email tenga formato válido.
- Verificará que la edad esté entre 18 y 100.
- Mostrará mensajes de error si algo está mal.
Al agregar novalidate
al formulario, se le indica al navegador: "No valide este formulario automáticamente".
<!-- CON novalidate - El navegador NO valida -->
<form novalidate>
<input type="email" required placeholder="Tu email">
<input type="number" min="18" max="100" required placeholder="Tu edad">
<button type="submit">Enviar</button>
</form>
accept-charset
Qué es accept-charset
accept-charset es un atributo opcional que puede incluirse dentro de la etiqueta <form>
para indicar al navegador qué conjuntos de caracteres (charsets) se deben utilizar al enviar los datos del formulario al servidor.
Un conjunto de caracteres define cómo los caracteres (letras, números, símbolos, etc.) se representan como bytes.
Los más comunes son:
- UTF-8: El estándar moderno que puede representar cualquier carácter Unicode.
- ISO-8859-1: Un conjunto más limitado que cubre caracteres latinos básicos.
- Windows-1252: Una extensión de ISO-8859-1 usado en Windows.
Por Qué Es Importante accept-charset
Cuando un usuario escribe caracteres especiales como acentos (á, é, í), eñes (ñ), o símbolos de otras lenguas (ç, ü, ø), el navegador necesita saber cómo codificar estos caracteres antes de enviarlos al servidor. Una codificación incorrecta puede resultar en caracteres distorsionados o "cuadraditos" en lugar del texto original, o también llamados mojibake.
Sintaxis accept-charset
<form accept-charset="utf-8">
...
</form>
Ejemplo con varios charsets:
<form accept-charset="UTF-8 ISO-8859-1">
...
</form>
Donde:
- Se puede especificar uno o varios conjuntos de caracteres, separados por espacios.
- El navegador usará el primer conjunto que sea compatible.
Valor por defecto accept-charset
Si no se especifica accept-charset
, el navegador usará:
- El conjunto de caracteres del documento HTML actual (por ejemplo, el que está definido en
<meta charset="utf-8">
), o - El valor por defecto del servidor, si el documento no define uno.
Por eso es muy común que en la práctica se vea poco el uso explícito de accept-charset
, porque muchos sitios ya definen <meta charset="utf-8">
en la cabecera del HTML.
Cuando Usar accept-charset
Aunque no siempre es obligatorio, es muy recomendable usarlo:
- Si el servidor requiere una codificación específica.
- Cuando se envían datos en varios idiomas.
- Para asegurar la correcta transmisión de caracteres especiales.
Ejemplo recomendado:
<form action="/procesar.php" method="post" accept-charset="UTF-8">
<label for="nombre">Nombre:</label>
<input type="text" id="nombre" name="nombre">
<input type="submit" value="Enviar">
</form>
Mejores Prácticas accept-charset
Siempre Usar UTF-8
<form accept-charset="UTF-8">
...
</form>
Esta es la práctica más segura y compatible con el desarrollo web moderno.
Mantener la Consistencia
Asegurarse que toda la aplicación use la misma codificación:
- Meta charset del HTML
- accept-charset del formulario
- Configuración del servidor
- Base de datos
Probar con Caracteres Especiales
Siempre probar los formularios con:
- Acentos: á, é, í, ó, ú
- Caracteres especiales: ñ, ç, ü
- Símbolos: €, £, ¥
- Emojis: 😀, 🎉, ❤️
Los Elementos del formulario
El Elemento <input />
El elemento <input>
es un componente fundamental en los documentos HTML5, siendo el más importante en la creación de formularios web. Se utiliza para declarar controles de entrada que permiten a los usuarios introducir datos, tomar decisiones, comunicar información y cambiar el comportamiento de una aplicación.
Sintaxis Básica: El elemento <input>
es una etiqueta vacía (void element), lo que significa que no requiere una etiqueta de cierre ni contiene contenido directo entre etiquetas. Por defecto, si no se especifica un tipo, se comporta como un campo de texto de una sola línea.
<input type="text" name="username" id="username">
Tipos de Entrada <input />
HTML5 ha expandido significativamente los tipos de entrada disponibles, lo que permite a los navegadores validar la entrada y ofrecer interfaces de usuario más intuitivas.
Tipos de Entrada de Texto
-
type="text"
: Entrada de texto de una sola línea. Nombres, direcciones, comentarios cortos.
<input type="text" name="nombre">
-
type="password"
: Campo de texto que oculta lo que se escribe (caracteres enmascarados). PINs y contraseñas.
<input type="password" name="clave">
-
type="email"
: Entrada de dirección de correo electrónico con validación. Emails, validación automática de formato.
<input type="email" name="correo">
-
type="url"
: Entrada de URL con validación. Sitios web, enlaces.
<input type="url" name="sitio">
-
type="tel"
: Entrada de número telefónico.
<input type="tel" name="telefono">
-
type="search"
: Campo de búsqueda con comportamiento específico. Cajas de búsqueda, filtros.
<input type="search" name="buscar">
Ejemplo:
<div class="ej-formulario-general">
<form class="ej-formulario-contenedor" action="#" method="POST">
<p class="ej-titulo-principal">Registro de Usuario</h1>
<div class="ej-grupo-campo">
<label for="nombre" class="ej-etiqueta-texto">Nombre completo</label>
<input type="text" name="nombre" id="nombre" class="ej-entrada-texto" placeholder="Ingresa tu nombre completo" required>
</div>
<div class="ej-grupo-campo">
<label for="clave" class="ej-etiqueta-texto">Contraseña</label>
<input type="password" name="clave" id="clave" class="ej-entrada-clave" placeholder="Crea una contraseña segura" required>
</div>
<div class="ej-grupo-campo">
<label for="correo" class="ej-etiqueta-texto">Correo electrónico</label>
<input type="email" name="correo" id="correo" class="ej-entrada-correo" placeholder="ejemplo@correo.com" required>
</div>
<div class="ej-grupo-campo">
<label for="sitio" class="ej-etiqueta-texto">Sitio web</label>
<input type="url" name="sitio" id="sitio" class="ej-entrada-sitio" placeholder="https://www.tusitio.com">
</div>
<div class="ej-grupo-campo">
<label for="telefono" class="ej-etiqueta-texto">Número de teléfono</label>
<input type="tel" name="telefono" id="telefono" class="ej-entrada-telefono" placeholder="+57 300 123 4567">
</div>
<div class="ej-grupo-campo">
<label for="buscar" class="ej-etiqueta-texto">Búsqueda</label>
<input type="search" name="buscar" id="buscar" class="ej-entrada-buscar" placeholder="¿Qué estás buscando?">
</div>
<button type="submit" class="ej-boton-enviar">Registrarse</button>
</form>
</div>
.ej-formulario-general {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Arial', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.ej-formulario-general * {
box-sizing: border-box;
}
.ej-formulario-general .ej-formulario-contenedor {
background: white;
padding: 40px;
border-radius: 20px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
width: 100%;
max-width: 500px;
backdrop-filter: blur(10px);
}
.ej-formulario-general .ej-titulo-principal {
text-align: center;
color: #333;
margin-bottom: 30px;
font-size: 2.2em;
font-weight: 300;
letter-spacing: 1px;
}
.ej-formulario-general .ej-grupo-campo {
margin-bottom: 25px;
position: relative;
}
.ej-formulario-general .ej-etiqueta-texto {
display: block;
margin-bottom: 8px;
color: #555;
font-weight: 500;
font-size: 0.95em;
letter-spacing: 0.5px;
}
.ej-formulario-general .ej-entrada-texto,
.ej-formulario-general .ej-entrada-clave,
.ej-formulario-general .ej-entrada-correo,
.ej-formulario-general .ej-entrada-sitio,
.ej-formulario-general .ej-entrada-telefono,
.ej-formulario-general .ej-entrada-buscar {
width: 100%;
padding: 15px 20px;
border: 2px solid #e1e5e9;
border-radius: 12px;
font-size: 1em;
transition: all 0.3s ease;
background: #f8f9fa;
}
.ej-formulario-general .ej-entrada-texto:focus,
.ej-formulario-general .ej-entrada-clave:focus,
.ej-formulario-general .ej-entrada-correo:focus,
.ej-formulario-general .ej-entrada-sitio:focus,
.ej-formulario-general .ej-entrada-telefono:focus,
.ej-formulario-general .ej-entrada-buscar:focus {
outline: none;
border-color: #667eea;
background: white;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
transform: translateY(-2px);
}
.ej-formulario-general .ej-entrada-texto::placeholder,
.ej-formulario-general .ej-entrada-clave::placeholder,
.ej-formulario-general .ej-entrada-correo::placeholder,
.ej-formulario-general .ej-entrada-sitio::placeholder,
.ej-formulario-general .ej-entrada-telefono::placeholder,
.ej-formulario-general .ej-entrada-buscar::placeholder {
color: #aaa;
font-style: italic;
}
.ej-formulario-general .ej-boton-enviar {
width: 100%;
padding: 15px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 12px;
font-size: 1.1em;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
letter-spacing: 1px;
margin-top: 20px;
}
.ej-formulario-general .ej-boton-enviar:hover {
transform: translateY(-3px);
box-shadow: 0 10px 25px rgba(102, 126, 234, 0.3);
}
.ej-formulario-general .ej-boton-enviar:active {
transform: translateY(-1px);
}
.ej-formulario-general .ej-icono-campo {
position: absolute;
right: 15px;
top: 50%;
transform: translateY(-50%);
color: #aaa;
font-size: 1.2em;
}
Tipos de Entrada Numérica y Rango
-
type="number"
: Descripción: Entrada numérica con controles de incremento/decremento. Cantidades, edades, precios.
<input type="number" name="edad" min="0" max="120">
-
type="range"
:Descripción: Control deslizante para seleccionar un valor en un rango. Volumen, brillo, escalas de valoración.<input type="range" name="volumen" min="0" max="100">
Tipos de Fecha y Hora
-
type="date"
: Descripción: Selector de fecha (año, mes, día). Fechas de nacimiento, citas, eventos.
<input type="date" name="fecha">
-
type="time"
: Descripción: Selector de hora (horas, minutos, segundos). Horarios, citas.<input type="time" name="hora">
-
type="datetime-local"
: Descripción: Selector de fecha y hora local. Citas con fecha y hora específica.
<input type="datetime-local" name="local">
-
type="month"
: Descripción: Selector de mes y año. Fechas de vencimiento, periodos mensuales.
<input type="month" name="mes">
-
type="week"
: Descripción: Selector de semana del año. Planificación semanal.
<input type="week" name="semana">
Tipos de Selección
-
type="checkbox"
: Descripción: Casilla de verificación para valores booleanos. Opciones múltiples, términos y condiciones.
<input type="checkbox" name="acepto" value="si">
Ejemplo:¿Qué vehículos tienes?
<div class="ej-container-checkbox"> <p class="ej-h1-checkbox"> ¿Qué vehículos tienes? </p> <form class="ej-form-checkbox"> <div class="ej-item-checkbox"> <input type="checkbox" id="vehicle1" name="vehicle1" value="Bike" class="ej-input-checkbox" /> <label for="vehicle1" class="ej-label-checkbox" > <span class="ej-icon-checkbox">🚲</span> <span class="ej-text-checkbox" >Tengo una bicicleta</span > </label> </div> <div class="ej-item-checkbox"> <input type="checkbox" id="vehicle2" name="vehicle2" value="Car" class="ej-input-checkbox" /> <label for="vehicle2" class="ej-label-checkbox" > <span class="ej-icon-checkbox">🚗</span> <span class="ej-text-checkbox" >Tengo un carro</span > </label> </div> <div class="ej-item-checkbox"> <input type="checkbox" id="vehicle3" name="vehicle3" value="Boat" class="ej-input-checkbox" /> <label for="vehicle3" class="ej-label-checkbox" > <span class="ej-icon-checkbox">🛥️</span> <span class="ej-text-checkbox" >Tengo un barco</span > </label> </div> <button type="submit" class="ej-button-checkbox" > Enviar </button> </form> </div>.ej-container-checkbox { font-family: Arial, sans-serif; max-width: 300px; margin: 20px auto; padding: 20px; background: #f5f5f5; border-radius: 10px; } .ej-h1-checkbox { color: #333; font-size: 18px; text-align: center; margin-bottom: 20px; } .ej-form-checkbox { display: flex; flex-direction: column; gap: 10px; } .ej-item-checkbox { display: flex; align-items: center; } .ej-input-checkbox { margin-right: 10px; width: 18px; height: 18px; } .ej-label-checkbox { display: flex; align-items: center; cursor: pointer; color: #555; font-size: 14px; } .ej-label-checkbox:hover { color: #007bff; } .ej-icon-checkbox { margin-right: 8px; font-size: 16px; } .ej-text-checkbox { color: inherit; } .ej-button-checkbox { background: #007bff; color: white; border: none; padding: 10px 20px; border-radius: 5px; font-size: 14px; cursor: pointer; margin-top: 15px; } .ej-button-checkbox:hover { background: #0056b3; }Explicación del Código:
- Formulario:
<form class="ej-form-checkbox">...</form>
. - Cada Opción de Checkbox:
-
ej-item-checkbox
: Contenedor de cada opción. -
<input type="checkbox" id="vehicle1" name="vehicle1" value="Bike" class="ej-input-checkbox">
:-
type="checkbox"
: Define que es una casilla de verificación. -
id="vehicle1"
: Identificador único para vincular con el<label>
. -
name="vehicle1"
: Nombre del campo para enviar datos al servidor. -
value="Bike"
: Valor que se envía si está marcado. - Cuando el usuario marca la casilla, el formulario enviará
vehicle1=Bike
. Si no está marcada, no se envía nada para ese campo.
-
-
<label for="vehicle1" class="ej-label-checkbox">
:-
for="vehicle1"
: Crea una etiqueta clickeable que está conectada al checkbox conid="vehicle1"
.
-
- Botón
<button>
, enviar:-
type="submit"
: Define que este botón envía el formulario. - Datos enviados por el formulario: si están seleccionadas las opciones de bicicleta y carro el formulario enviara:
vehicle1=Bike&vehicle2=Car
-
Sintaxis básica:
<div class="ej-item-checkbox"> <input type="checkbox" id="vehicle1" name="vehicle1" value="Bike" class="ej-input-checkbox"> <label for="vehicle1" class="ej-label-checkbox"> <span class="ej-icon-checkbox">🚲</span> <span class="ej-text-checkbox">Tengo una bicicleta</span> </label> </div>
-
- Formulario:
-
type="radio"
: Descripción: Botón de radio para selección única en un grupo. Selección excluyente, género, opciones únicas.
<input type="radio" name="genero" value="masculino">
Ejemplo:Ejemplo de Input Type Radio
Tu selección:
<div class="ej-container-radio"> <p class="ej-h1-radio">Ejemplo de Input Type Radio</p> <form class="ej-form-radio" id="radioForm"> <fieldset class="ej-fieldset-radio"> <legend class="ej-legend-radio">Selecciona tu color favorito</legend> <div class="ej-radio-group"> <div class="ej-radio-item"> <input type="radio" id="rojo" name="color" value="rojo" class="ej-radio-input"> <label for="rojo" class="ej-radio-label">Rojo</label> </div> <div class="ej-radio-item"> <input type="radio" id="azul" name="color" value="azul" class="ej-radio-input"> <label for="azul" class="ej-radio-label">Azul</label> </div> <div class="ej-radio-item"> <input type="radio" id="verde" name="color" value="verde" class="ej-radio-input"> <label for="verde" class="ej-radio-label">Verde</label> </div> <div class="ej-radio-item"> <input type="radio" id="amarillo" name="color" value="amarillo" class="ej-radio-input"> <label for="amarillo" class="ej-radio-label">Amarillo</label> </div> </div> </fieldset> <fieldset class="ej-fieldset-radio"> <legend class="ej-legend-radio">Selecciona tu tamaño preferido</legend> <div class="ej-radio-group"> <div class="ej-radio-item"> <input type="radio" id="pequeno" name="tamaño" value="pequeño" class="ej-radio-input"> <label for="pequeno" class="ej-radio-label">Pequeño</label> </div> <div class="ej-radio-item"> <input type="radio" id="mediano" name="tamaño" value="mediano" class="ej-radio-input"> <label for="mediano" class="ej-radio-label">Mediano</label> </div> <div class="ej-radio-item"> <input type="radio" id="grande" name="tamaño" value="grande" class="ej-radio-input"> <label for="grande" class="ej-radio-label">Grande</label> </div> </div> </fieldset> <button type="submit" class="ej-submit-radio">Enviar Selección</button> </form> <div id="resultado" class="ej-result-radio"> <p><strong>Tu selección:</strong></p> <p id="seleccion"></p> </div> </div>.ej-container-radio { font-family: Arial, sans-serif; max-width: 600px; margin: 40px auto; padding: 30px; background-color: #f9f9f9; border-radius: 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); } .ej-h1-radio { color: #333; text-align: center; margin-bottom: 30px; font-size: 24px; } .ej-form-radio { background: white; padding: 25px; border-radius: 6px; border: 1px solid #ddd; } .ej-fieldset-radio { border: 2px solid #e0e0e0; border-radius: 6px; padding: 20px; margin-bottom: 20px; } .ej-legend-radio { font-weight: bold; color: #555; padding: 0 10px; } .ej-radio-group { margin: 15px 0; } .ej-radio-item { display: flex; align-items: center; margin: 10px 0; padding: 8px; border-radius: 4px; transition: background-color 0.2s; } .ej-radio-item:hover { background-color: #f5f5f5; } .ej-radio-input { margin-right: 10px; width: 16px; height: 16px; cursor: pointer; } .ej-radio-label { cursor: pointer; color: #333; font-size: 14px; } .ej-submit-radio { background-color: #4CAF50; color: white; padding: 12px 24px; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; margin-top: 20px; transition: background-color 0.3s; } .ej-submit-radio:hover { background-color: #45a049; } .ej-result-radio { margin-top: 20px; padding: 15px; background-color: #e8f5e8; border-radius: 4px; border-left: 4px solid #4CAF50; display: none; }- Formulario: Contiene todos los elementos interactivos. El
id="radioForm"
permite que JavaScript lo identifique para manejar el evento de envío. - Primer Grupo: Colores:
-
<fieldset>
: Agrupa elementos relacionados del formulario -
<legend>
: Proporciona un título descriptivo para el grupo - Opciones: Rojo, Azul, Verde, Amarillo
Sintaxis básica:
<fieldset class="ej-fieldset-radio"> <legend class="ej-legend-radio">Selecciona tu color favorito</legend> <div class="ej-radio-group"> <!-- Radio buttons para colores --> </div> </fieldset>
-
- Cada opción de color tiene:
-
type="radio"
: Define que es un botón de opción. -
name="color"
: Agrupa los radio buttons, todos los radio buttons de este grupo (colores) comparten este nombre. -
value="rojo"
: Valor que se enviará al servidor. -
id="rojo"
: Identificador único. -
<label for="rojo">
: Etiqueta asociada que permite hacer clic en el texto para seleccionar.
Sintaxis básica:
<div class="ej-radio-item"> <input type="radio" id="rojo" name="color" value="rojo" class="ej-radio-input"> <label for="rojo" class="ej-radio-label">Rojo</label> </div>
-
- Botón
<button>
, enviar:-
type="submit"
: Define que este botón envía el formulario. - Datos enviados por el formulario: si están seleccionadas las opciones de color rojo y tamaño mediano el formulario enviara:
color=rojo&tamaño=mediano
-
- Formulario: Contiene todos los elementos interactivos. El
Tipos de Archivo y Multimedia
-
type="file"
: Descripción: Control para seleccionar archivos del sistema. Subida de documentos, imágenes, videos.
<input type="file" name="archivo" accept=".jpg,.png">
-
type="image"
: Descripción: Botón de envío gráfico (imagen clickeable). Botones de envío personalizados con imagen.
<input type="image" src="enviar.png" alt="Enviar">
Tipos de Color
-
type="color"
: Selector de color. Selección de colores, temas, personalización.
<input type="color" name="color" value="#ff0000">
Tipos de Botón
-
type="submit"
: Botón para enviar el formulario. Envío de datos del formularioEnvío de datos del formulario.
<input type="submit" value="Enviar">
-
type="reset"
: Botón para restablecer el formulario. Limpiar todos los campos del formulario.
<input type="reset" value="Limpiar">
-
type="button"
: Botón genérico sin comportamiento predeterminado. Botones personalizados con JavaScript.
<input type="button" value="Hacer algo" onclick="miFuncion()">
Ejemplo:
<div class="ej-contenedor-submit">
<form
action="https://formspree.io/f/mdkdawkg"
method="POST"
class="ej-formulario-submit"
>
<p class="ej-h1-submit">
Formulario de Contacto
</p>
<div class="ej-grupo-submit">
<label class="ej-label-submit" for="nombre"
>Nombre:</label
>
<input
class="ej-input-submit"
type="text"
id="nombre"
name="nombre"
required
/>
</div>
<div class="ej-grupo-submit">
<label class="ej-label-submit" for="email"
>Email:</label
>
<input
class="ej-input-submit"
type="email"
id="email"
name="email"
required
/>
</div>
<div class="ej-grupo-submit">
<label class="ej-label-submit" for="mensaje"
>Mensaje:</label
>
<textarea
class="ej-textarea-submit"
id="mensaje"
name="mensaje"
rows="4"
required
></textarea>
</div>
<div class="ej-botones-submit">
<input
class="ej-btn-enviar-submit"
type="submit"
value="Enviar"
/>
<input
class="ej-btn-limpiar-submit"
type="reset"
value="Limpiar"
/>
<input
class="ej-btn-personalizado-submit"
type="button"
value="Hacer algo"
onclick="miFuncion()"
/>
</div>
</form>
</div>
<script>
function miFuncion() {
alert(
"¡Botón personalizado activado! 🎉\n\nEste botón puede ejecutar cualquier función JavaScript que necesites."
);
// Ejemplo de funcionalidad adicional
const nombre =
document.getElementById("nombre").value;
if (nombre) {
console.log("Usuario:", nombre);
}
}
// Añadir funcionalidad extra al formulario
document
.querySelector(".ej-formulario-submit")
.addEventListener("submit", function (e) {
e.preventDefault();
alert(
"Formulario enviado exitosamente! ✅"
);
// RESETEAR el formulario después del envío
this.reset();
});
</script>
.ej-contenedor-submit {
font-family: 'Arial', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
margin: 0;
padding: 20px;
box-sizing: border-box;
}
.ej-formulario-submit {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border-radius: 20px;
padding: 40px;
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1);
width: 100%;
max-width: 450px;
border: 1px solid rgba(255, 255, 255, 0.2);
}
.ej-h1-submit {
color: #4a5568;
font-size: 28px;
font-weight: bold;
text-align: center;
margin: 0 0 30px 0;
background: linear-gradient(45deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.ej-grupo-submit {
margin-bottom: 20px;
}
.ej-label-submit {
display: block;
margin-bottom: 8px;
color: #4a5568;
font-weight: 600;
font-size: 14px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.ej-input-submit,
.ej-textarea-submit {
width: 100%;
padding: 12px 16px;
border: 2px solid #e2e8f0;
border-radius: 12px;
font-size: 16px;
transition: all 0.3s ease;
background: rgba(255, 255, 255, 0.8);
box-sizing: border-box;
}
.ej-input-submit:focus,
.ej-textarea-submit:focus {
outline: none;
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
transform: translateY(-2px);
}
.ej-textarea-submit {
resize: vertical;
min-height: 100px;
}
.ej-botones-submit {
display: flex;
gap: 12px;
flex-wrap: wrap;
margin-top: 30px;
}
.ej-btn-enviar-submit,
.ej-btn-limpiar-submit,
.ej-btn-personalizado-submit {
flex: 1;
min-width: 120px;
padding: 12px 20px;
border: none;
border-radius: 25px;
font-size: 14px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.ej-btn-enviar-submit {
background: linear-gradient(45deg, #667eea, #764ba2);
color: white;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
}
.ej-btn-enviar-submit:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.6);
}
.ej-btn-limpiar-submit {
background: linear-gradient(45deg, #ff6b6b, #ee5a52);
color: white;
box-shadow: 0 4px 15px rgba(255, 107, 107, 0.4);
}
.ej-btn-limpiar-submit:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(255, 107, 107, 0.6);
}
.ej-btn-personalizado-submit {
background: linear-gradient(45deg, #4ecdc4, #44a08d);
color: white;
box-shadow: 0 4px 15px rgba(78, 205, 196, 0.4);
}
.ej-btn-personalizado-submit:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(78, 205, 196, 0.6);
}
.ej-btn-enviar-submit:active,
.ej-btn-limpiar-submit:active,
.ej-btn-personalizado-submit:active {
transform: translateY(0);
}
/* Efecto de onda al hacer clic */
.ej-btn-enviar-submit::before,
.ej-btn-limpiar-submit::before,
.ej-btn-personalizado-submit::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
border-radius: 50%;
background: rgba(255, 255, 255, 0.3);
transform: translate(-50%, -50%);
transition: width 0.3s, height 0.3s;
}
.ej-btn-enviar-submit:active::before,
.ej-btn-limpiar-submit:active::before,
.ej-btn-personalizado-submit:active::before {
width: 300px;
height: 300px;
}
/* Responsive */
@media (max-width: 600px) {
.ej-formulario-submit {
padding: 30px 20px;
}
.ej-botones-submit {
flex-direction: column;
}
.ej-btn-enviar-submit,
.ej-btn-limpiar-submit,
.ej-btn-personalizado-submit {
width: 100%;
margin-bottom: 10px;
}
}
Explicación:
- Botón Submit (Enviar):
Sintaxis básica:
<input class="ej-btn-enviar-submit" type="submit" value="Enviar">
- Este botón envía automáticamente toda la información del formulario.
-
type="submit"
: Le dice al navegador "cuando alguien haga clic aquí, envía el formulario". - No es necesario usar JavaScript: Funciona solo, es comportamiento nativo del navegador.
- Los formularios son enviados al servicio en linea de administración de correos:
formspree.io
, definido en la etiqueta<form>
.
- Botón Reset (Limpiar):
Sintaxis básica:
<input class="ej-btn-limpiar-submit" type="reset" value="Limpiar">
- Borra todo lo que el usuario escribió en el formulario.
-
type="reset"
: Le dice al navegador "limpia todos los campos y déjalos como estaban al principio". - No es necesario usar JavaScript: Funciona solo, es comportamiento nativo del navegador.
- Botón Button (Personalizado):
<nput class="ej-btn-personalizado-submit" type="button" value="Hacer algo" onclick="miFuncion()">
- Este botón NO hace nada por sí solo, es como un botón "en blanco".
-
type="button"
: Le dice al navegador "soy solo un botón, no hagas nada especial". -
onclick="miFuncion()"
: Aquí se le dice qué hacer cuando alguien haga clic. - Se necesita JavaScript: Se tiene que programar la función
miFuncion()
para que haga algo. - Muestra una alerta que ya se envío el formulario.
Tipo Especial
-
type="hidden"
: Campo oculto no visible para el usuario. Datos que se envían pero no se muestran.
<input type="hidden" name="token" value="abc123">
Atributos de Entrada <input />
Globales
Estos atributos funcionan en casi todas lass entradas.
-
name
: Nombre del campo para el servidor. -
id
: Identificador único en la página. -
value
: Valor inicial (depende del tipo). -
disabled
: Desactiva el campo. -
readonly
: Solo lectura (no se puede editar, pero se envía). -
required
: Campo obligatorio. -
tabindex
: Orden en la navegación con TAB. -
title
: Mensaje de ayuda (tooltip). -
autofocus
: Foco automático al cargar la página. -
form
: ID del formulario al que pertenece (si está fuera). -
list
: ID de un<datalist>
para sugerencias.
Para Entradas de Texto
-
maxlength
: Limita la cantidad máxima de caracteres. -
minlength
: Establece un mínimo de caracteres. -
placeholder
: Muestra texto guía cuando el campo está vacío. -
pattern
: Valida el texto usando una expresión regular. -
size
: Define el ancho visual en caracteres. -
spellcheck
: Activa/desactiva el corrector ortográfico (en "text" y "search"). -
multiple
: Solo aplica a email y file para permitir varios valores. -
dirname
: Envía la dirección del texto (ltr o rtl). -
autocomplete
: Activa/desactiva el autocompletado.
Para Numérica y Rango
-
min
: Valor mínimo permitido. -
max
: Valor máximo permitido. -
step
: Incremento o decremento permitido. -
value
: Valor inicial.
Nota: pattern
, maxlength
y minlength
no funcionan aquí, porque el valor se valida como número, no como texto.
Para Fecha y Hora
-
min
: Fecha/hora mínima permitida. -
max
: Fecha/hora máxima permitida. -
step
: Saltos de valores; ej: cada 5 minutos. -
value
: Valor inicial.
Para Selección
-
checked
: Define si aparece marcado por defecto. -
value
: Valor que se envía si está seleccionado.
Para Archivo y Multimedia
-
multiple
: Permite seleccionar varios archivos. -
accept
: Limita los tipos de archivos que se pueden subir (ej: .jpg,.png). -
src
: Ruta de la imagen a mostrar. -
alt
: Texto alternativo. -
height
: Altura de la imagen. -
width
: Ancho de la imagen.
Para Color
-
value
: Color inicial (ej: #ff0000).
El Elemento <label>
El elemento <label>
en HTML se utiliza para referenciar un elemento de acción de un formulario. Su propósito principal en la interfaz de usuario es facilitar la selección o el destino de elementos como los botones de radio o las casillas de verificación. Al usarlo, se proporciona contexto a los botones y se indica a los usuarios para qué sirve cada uno.
Al asociar un <label>
con un control de formulario, el texto del <label>
se vuelve interactivo: al hacer clic en el texto de la etiqueta, se activará el control de formulario asociado (por ejemplo, se marcará una casilla de verificación o se seleccionará un botón de radio).
La etiqueta <label>
mejora la accesibilidad para usuarios de lectores de pantalla, ya que estos dispositivos leen en voz alta el texto de la etiqueta cuando el usuario selecciona un elemento de entrada (input). Además, facilita la interacción a usuarios con dificultades para hacer clic en áreas pequeñas, como botones de opción o casillas de verificación, permitiendo activar o desactivar estos elementos al hacer clic en el texto asociado dentro de la etiqueta <label>
.
Existen dos formas principales de utilizar el elemento <label>
:
Envolviendo el Elemento de Control
El elemento <label>
puede contener directamente el elemento de entrada del formulario que desea etiquetar, por ejemplo:
<label>
Nombre:
<input type="text" name="nombre">
</label>
Cuando se coloca el <input>
dentro del <label>
, el navegador asocia automáticamente ese texto ("Nombre:") con el campo de entrada.
Esto significa que si el usuario hace clic en el texto “Nombre:”, el cursor se colocará directamente en la caja de texto, facilitando la interacción.
Ventajas:
- Más compacta y simple.
- Asociación automática sin necesidad de IDs.
- Ideal para casos simples.
Usando el Atributo for
Para asociar un <label>
con un elemento de formulario sin necesidad de envolverlo, se puede utilizar el atributo for
en la etiqueta <label>
. El valor de este atributo debe coincidir con el valor del atributo id
del elemento de formulario al que se desea vincular. Esto permite ubicar la etiqueta en cualquier parte del documento, por ejemplo:
<label for="nombre">Nombre:</label>
<input type="text" id="nombre" name="nombre">
Al hacer clic en el texto “Nombre:” de la etiqueta <label>
, el navegador coloca el cursor en el campo <input>
porque el atributo for="nombre"
coincide exactamente con el id="nombre"
.
Ventajas:
- Mayor flexibilidad en el diseño y ubicación.
- Permite separar la etiqueta del campo.
- Mejor para layouts complejos.
- Más explícita en la asociación.
Consideraciones y Buenas Prácticas
No debe contener más de un elemento de control dentro de una misma etiqueta <label>
.
Para agrupar colecciones de botones de radio o casillas de verificación, se recomienda incluirlos dentro de un elemento <fieldset>
con un elemento <legend>
que proporcione un título para el grupo.
Aunque las casillas de verificación pueden agruparse de manera similar, no deben compartir el mismo atributo name
, ya que no son mutuamente excluyentes como los botones de radio.
El Elemento <select>
El elemento <select>
en HTML se utiliza para generar un menú desplegable (drop-down menu) desde el cual el usuario puede elegir una o más opciones.
Sintaxis básica:
<select name="idiomas">
<option value="es">Español</option>
<option value="en">Inglés</option>
<option value="fr">Francés</option>
<option value="de">Alemán</option>
</select>
Explicación de Ejemplo:
<select>
-
<select name="idiomas">
: Este es el elemento principal que crea el menú desplegable. -
name="idiomas"
: Le asigna un nombre al campo, que será útil cuando el formulario se envíe al servidor.
<option>
-
<option value="es">Español</option>
: Cada elemento<option>
representa una opción disponible en el menú. -
value="es"
: Este atributo es el valor que se enviará al servidor cuando se seleccione esta opción. - Mientras que "Español" es el texto que ve el usuario.
- Por defecto, la primera opción (Español) aparecerá preseleccionada.
- Cuando el usuario envía el formulario, se envía algo como
idiomas=es
si tiene la opciónEspañol
seleccionada.
Atributos Principales de <select>
-
name
: Nombre del campo para el formulario. -
id
: Identificador único del elemento. -
class
: Clases CSS para estilizar. -
style
: Estilos CSS inline.
Atributos de Comportamiento de <select>
-
multiple
: Permite seleccionar múltiples opciones. -
size
: Número de opciones visibles (por defecto es 1.) -
disabled
: Desactiva el select. -
readonly
: Solo lectura (no estándar para select.) -
required
: Campo obligatorio para validación HTML5. -
autofocus
: Enfoca automáticamente al cargar la página. -
selected
: Es un atributo booleano que, al incluirse, selecciona la opción por defecto al cargar la página. Si no se especifica, se selecciona automáticamente la primera opción del menú.
Ejemplo <select>
Selecciona tus Colores
<div class="wrapper-select">
<div class="container-select">
<p class="h1-select">Selecciona tus Colores</p>
<form id="colorForm">
<div class="form-group-select">
<label for="colores" class="label-select">
Elige tus colores favoritos <span class="required-indicator-select">*</span>
</label>
<select
id="colores"
name="colores"
class="select-select"
multiple
size="3"
required
autofocus>
<option value="rojo" class="option-select">Rojo</option>
<option value="azul" class="option-select">Azul</option>
<option value="verde" class="option-select">Verde</option>
<option value="amarillo" class="option-select">Amarillo</option>
<option value="morado" class="option-select">Morado</option>
<option value="naranja" class="option-select">Naranja</option>
<option value="rosa" class="option-select">Rosa</option>
<option value="negro" class="option-select">Negro</option>
<option value="blanco" class="option-select">Blanco</option>
<option value="gris" class="option-select">Gris</option>
</select>
<p class="hint-select">
Mantén presionado Ctrl para seleccionar múltiples opciones
</p>
</div>
<button type="submit" class="submit-btn-select">
Confirmar Selección
</button>
</form>
</div>
</div>
.wrapper-select {
font-family: Arial, sans-serif;
background: #f5f5f5;
margin: 0;
padding: 20px;
}
.container-select {
background: white;
border-radius: 8px;
padding: 30px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
max-width: 400px;
margin: 0 auto;
}
.h1-select {
color: #333;
text-align: center;
margin-bottom: 25px;
font-size: 1.8em;
font-weight: normal;
}
.form-group-select {
margin-bottom: 25px;
}
.label-select {
display: block;
margin-bottom: 8px;
font-weight: bold;
color: #555;
}
.select-select {
width: 100%;
padding: 10px;
font-size: 16px;
border: 1px solid #ddd;
border-radius: 4px;
background: #fff;
color: #333;
font-family: inherit;
}
.select-select:focus {
outline: none;
border-color: #4CAF50;
box-shadow: 0 0 5px rgba(76, 175, 80, 0.3);
}
.option-select {
padding: 8px;
}
.hint-select {
margin-top: 8px;
font-size: 14px;
color: #666;
}
.submit-btn-select {
width: 100%;
padding: 12px;
background: #4CAF50;
color: white;
border: none;
border-radius: 4px;
font-size: 16px;
cursor: pointer;
margin-top: 20px;
}
.submit-btn-select:hover {
background: #45a049;
}
.required-indicator-select {
color: #e74c3c;
}
Atributos del <select>
utilizados en el ejemplo:
-
multiple
: Permite seleccionar múltiples opciones. -
size="3"
: Muestra 3 opciones visibles. -
required
: Campo obligatorio. -
autofocus
: Foco automático al cargar.
Uso de <label>
con <select>
Sintaxis básica:
<label for="colores" class="label-select">
Elige tus colores favoritos</span>
</label>
<select id="colores" name="colores">
<option value="rojo" class="option-select">Rojo</option>
<option value="azul" class="option-select">Azul</option>
<option value="verde" class="option-select">Verde</option>
<option value="amarillo" class="option-select">Amarillo</option>
</select>
- El
for="colores"
del<label
se vincula con elid="colores"
del<select>
. - Al hacer clic en el texto del
<label>
, automáticamente se enfoca el<select>
Beneficios de usar <label>
con <select>
:
- Hacer clic en "Elige tus colores favoritos" activa el
<select>
. - Área de clic más grande y cómoda para el usuario.
- Lectores de pantalla anuncian el
<label>
cuando el select recibe foco. - Cumple con estándares WCAG de accesibilidad web.
- Usuarios con discapacidades pueden navegar más fácilmente.
- HTML semánticamente correcto.
- Estructura clara de formulario.
- Mejor para SEO y procesamiento automático.
Alternativas de Uso de <label>
con <select>
También se puede anidar el <select>
dentro del <label>
:
Sintaxis básica:
<label class="label-select">
Elige tus colores favoritos
<select name="colores" class="select-select" multiple>
<!-- opciones -->
</select>
</label>
Ambas formas son válidas, pero la primera (usando for
e id
) es más común y flexible para estilos CSS.
El Elemento <optgroup>
El elemento <optgroup>
es una etiqueta contenedora que se usa dentro de un elemento <select>
para agrupar opciones relacionadas (<option>).
Su propósito principal es organizar y mejorar la usabilidad de los menús desplegables cuando hay muchas opciones, mostrando títulos o categorías que ayuden al usuario a entender mejor las distintas opciones disponibles.
Sintaxis básica:
<select>
<optgroup label="Frutas">
<option value="manzana">Manzana</option>
<option value="pera">Pera</option>
</optgroup>
<optgroup label="Verduras" disabled>
<option value="zanahoria">Zanahoria</option>
<option value="lechuga">Lechuga</option>
</optgroup>
</select>
Explicación del Código:
-
<select>
: crea la lista desplegable. -
<optgroup>
: define un grupo dentro de esa lista. - El atributo
label
del<optgroup>
indica el nombre de ese grupo que se mostrará como encabezado. - El atributo
disabled
del<optgroup>
deshabilita todo el grupo de opciones. - El nombre de cada grupo se muestra con un estilo diferente (generalmente en negrita).
- El nombre de cada grupo no es seleccionable, solo sirve como separadores visuales.
- Dentro del
<optgroup>
van las distintas<option>
que pertenecen a ese grupo. - Las opciones de cada
<option>
que están dentro del grupo aparecen indentadas (desplazadas hacia la derecha) para que el usuario vea que pertenecen a ese grupo. - Ayuda a organizar listas largas de opciones de forma más intuitiva
- Mejora la accesibilidad y experiencia del usuario
Ejemplo:
OPTGROUP
<div class="ej-wrapper-optgroup">
<div class="ej-container-optgroup">
<p class="ej-h1-optgroup">OPTGROUP</p>
<div class="ej-form-group-optgroup">
<label for="paises" class="ej-label-optgroup">Selecciona un país:</label>
<select id="paises" class="ej-select-optgroup" onchange="mostrarSeleccion()">
<option value="">-- Selecciona un país --</option>
<optgroup label="América del Norte" class="ej-optgroup-optgroup">
<option value="usa" class="ej-option-optgroup">Estados Unidos</option>
<option value="canada" class="ej-option-optgroup">Canadá</option>
<option value="mexico" class="ej-option-optgroup">México</option>
</optgroup>
<optgroup label="América del Sur" class="ej-optgroup-optgroup">
<option value="colombia" class="ej-option-optgroup">Colombia</option>
<option value="brasil" class="ej-option-optgroup">Brasil</option>
<option value="argentina" class="ej-option-optgroup">Argentina</option>
<option value="chile" class="ej-option-optgroup">Chile</option>
<option value="peru" class="ej-option-optgroup">Perú</option>
</optgroup>
<optgroup label="Europa" class="ej-optgroup-optgroup">
<option value="espana" class="ej-option-optgroup">España</option>
<option value="francia" class="ej-option-optgroup">Francia</option>
<option value="alemania" class="ej-option-optgroup">Alemania</option>
<option value="italia" class="ej-option-optgroup">Italia</option>
<option value="reino_unido" class="ej-option-optgroup">Reino Unido</option>
</optgroup>
<optgroup label="Asia" class="ej-optgroup-optgroup">
<option value="china" class="ej-option-optgroup">China</option>
<option value="japon" class="ej-option-optgroup">Japón</option>
<option value="india" class="ej-option-optgroup">India</option>
<option value="corea_sur" class="ej-option-optgroup">Corea del Sur</option>
</optgroup>
</select>
</div>
<div class="ej-form-group-optgroup">
<label for="comida" class="ej-label-optgroup">Tipo de comida favorita:</label>
<select id="comida" class="ej-select-optgroup" onchange="mostrarSeleccion()">
<option value="">-- Selecciona --</option>
<optgroup label="Comida Asiática" class="ej-optgroup-optgroup">
<option value="sushi" class="ej-option-optgroup">Sushi</option>
<option value="ramen" class="ej-option-optgroup">Ramen</option>
<option value="pad_thai" class="ej-option-optgroup">Pad Thai</option>
<option value="curry" class="ej-option-optgroup">Curry</option>
</optgroup>
<optgroup label="Comida Europea" class="ej-optgroup-optgroup">
<option value="pizza" class="ej-option-optgroup">Pizza</option>
<option value="pasta" class="ej-option-optgroup">Pasta</option>
<option value="paella" class="ej-option-optgroup">Paella</option>
<option value="croissant" class="ej-option-optgroup">Croissant</option>
</optgroup>
<optgroup label="Comida Latinoamericana" class="ej-optgroup-optgroup">
<option value="tacos" class="ej-option-optgroup">Tacos</option>
<option value="arepa" class="ej-option-optgroup">Arepa</option>
<option value="empanada" class="ej-option-optgroup">Empanada</option>
<option value="ceviche" class="ej-option-optgroup">Ceviche</option>
</optgroup>
</select>
</div>
<div class="ej-buttons-container-optgroup">
<button onclick="enviarFormulario()" class="ej-button-enviar-optgroup">Enviar</button>
<button onclick="limpiarSelecciones()" class="ej-button-limpiar-optgroup">Limpiar</button>
</div>
<div class="ej-result-optgroup" id="resultado" style="display: none;">
<p class="ej-h3-optgroup">Tu selección:</p>
<p id="texto-resultado" class="ej-texto-resultado-optgroup"></p>
</div>
</div>
</div>
<script>
function enviarFormulario() {
const pais = document.getElementById('paises');
const comida = document.getElementById('comida');
const resultado = document.getElementById('resultado');
const textoResultado = document.getElementById('texto-resultado');
if (!pais.value && !comida.value) {
alert('Por favor, selecciona al menos una opción antes de enviar.');
return;
}
let mensaje = '<strong>Formulario enviado exitosamente!</strong><br><br>';
if (pais.value) {
const paisTexto = pais.options[pais.selectedIndex].text;
const grupoTexto = pais.options[pais.selectedIndex].parentNode.label || 'Sin grupo';
mensaje += `🌍 País: ${paisTexto} (${grupoTexto})<br>`;
}
if (comida.value) {
const comidaTexto = comida.options[comida.selectedIndex].text;
const grupoComida = comida.options[comida.selectedIndex].parentNode.label || 'Sin grupo';
mensaje += `🍽️ Comida: ${comidaTexto} (${grupoComida})`;
}
textoResultado.innerHTML = mensaje;
resultado.style.display = 'block';
}
function mostrarSeleccion() {
const pais = document.getElementById('paises');
const comida = document.getElementById('comida');
const resultado = document.getElementById('resultado');
const textoResultado = document.getElementById('texto-resultado');
let mensaje = '';
if (pais.value) {
const paisTexto = pais.options[pais.selectedIndex].text;
const grupoTexto = pais.options[pais.selectedIndex].parentNode.label || 'Sin grupo';
mensaje += `País: ${paisTexto} (${grupoTexto})`;
}
if (comida.value) {
const comidaTexto = comida.options[comida.selectedIndex].text;
const grupoComida = comida.options[comida.selectedIndex].parentNode.label || 'Sin grupo';
if (mensaje) mensaje += '<br>';
mensaje += `Comida: ${comidaTexto} (${grupoComida})`;
}
if (mensaje) {
textoResultado.innerHTML = mensaje;
resultado.style.display = 'block';
} else {
resultado.style.display = 'none';
}
}
function limpiarSelecciones() {
document.getElementById('paises').value = '';
document.getElementById('comida').value = '';
document.getElementById('resultado').style.display = 'none';
}
</script>
.ej-wrapper-optgroup {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
min-height: 100vh;
background: linear-gradient(45deg, #ff9a9e 0%, #fecfef 50%, #fecfef 100%);
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.ej-container-optgroup {
background: white;
padding: 40px;
border-radius: 20px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
max-width: 500px;
width: 100%;
position: relative;
overflow: hidden;
}
.ej-container-optgroup::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 5px;
background: linear-gradient(90deg, #ff6b6b, #4ecdc4, #45b7d1);
}
.ej-h1-optgroup {
text-align: center;
margin-bottom: 30px;
color: #333;
font-size: 2rem;
font-weight: 300;
letter-spacing: 2px;
}
.ej-form-group-optgroup {
margin-bottom: 25px;
}
.ej-label-optgroup {
display: block;
margin-bottom: 8px;
color: #555;
font-weight: 500;
font-size: 1rem;
}
.ej-select-optgroup {
width: 100%;
padding: 15px;
font-size: 16px;
border: 2px solid #f0f0f0;
border-radius: 12px;
background: #fafafa;
color: #333;
cursor: pointer;
transition: all 0.3s ease;
appearance: none;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
background-position: right 12px center;
background-repeat: no-repeat;
background-size: 16px;
padding-right: 40px;
}
.ej-select-optgroup:focus {
outline: none;
border-color: #ff6b6b;
background: white;
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(255, 107, 107, 0.15);
}
.ej-optgroup-optgroup {
font-weight: 600;
font-style: normal;
color: #ff6b6b;
background: #fff0f0;
font-size: 14px;
text-transform: uppercase;
letter-spacing: 1px;
}
.ej-option-optgroup {
font-weight: 400;
font-style: normal;
padding: 8px;
color: #333;
background: white;
}
.ej-buttons-container-optgroup {
display: flex;
gap: 15px;
margin-top: 20px;
}
.ej-button-enviar-optgroup,
.ej-button-limpiar-optgroup {
flex: 1;
border: none;
padding: 15px 30px;
border-radius: 25px;
font-size: 16px;
cursor: pointer;
transition: all 0.3s ease;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 1px;
}
.ej-button-enviar-optgroup {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.ej-button-enviar-optgroup:hover {
transform: translateY(-3px);
box-shadow: 0 10px 30px rgba(118, 75, 162, 0.3);
}
.ej-button-limpiar-optgroup {
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%);
color: white;
}
.ej-button-limpiar-optgroup:hover {
transform: translateY(-3px);
box-shadow: 0 10px 30px rgba(255, 107, 107, 0.3);
}
.ej-result-optgroup {
margin-top: 25px;
padding: 20px;
background: linear-gradient(135deg, #667eea20, #764ba220);
border-radius: 15px;
border-left: 4px solid #667eea;
animation: fadeIn 0.5s ease-in-out;
}
.ej-h3-optgroup {
color: #333;
margin-bottom: 10px;
font-size: 1.2rem;
font-weight: 500;
}
.ej-texto-resultado-optgroup {
color: #555;
line-height: 1.6;
font-size: 1rem;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@media (max-width: 600px) {
.ej-wrapper-optgroup {
padding: 10px;
}
.ej-container-optgroup {
padding: 25px;
}
.ej-h1-optgroup {
font-size: 1.5rem;
}
.ej-buttons-container-optgroup {
flex-direction: column;
gap: 10px;
}
}
El elemento <textarea>
El elemento <textarea>
se utiliza en HTML para permitir a los usuarios introducir texto de varias líneas. A diferencia del elemento <input>
de tipo text
, que es para una sola línea de texto, <textarea>
está diseñado para cantidades sustanciales de texto.
Detalles clave sobre el elemento <textarea>
:
- Propósito: Se utiliza para campos de texto que pueden alcanzar una gran longitud, como comentarios o descripciones, etc.
- Estructura: Requiere una etiqueta de apertura y una etiqueta de cierre, por ejemplo,
<textarea>
...</textarea>
. Lo que se encuentre entre las etiquetas será el contenido predeterminado, si lo hay.
Sintaxis básica:
<label for="mensaje">Comentario:</label>
<textarea name="mensaje" id="mensaje" rows="4" cols="50">
Texto predeterminado opcional
</textarea>
Atributos principales de <textarea>
-
name
: Permite asignar un nombre a la variable de introducción de datos. Este nombre será enviado al servidor junto con el contenido. -
rows
: Representa el número de filas visibles para el área de texto. -
cols
: Representa el número de columnas visibles para el área de texto. -
id
: Identificador único para poder enlazarlo con el atributofor
de la etiqueta<label>
.
Otros atributos útiles:
-
placeholder
: texto que aparece como sugerencia dentro del campo. -
maxlength
: número máximo de caracteres permitidos. -
readonly
: hace que el texto solo se pueda leer, no editar. -
disabled
: desactiva el campo, evitando que el usuario pueda interactuar con él. -
required
: indica que es obligatorio rellenar el campo antes de enviar el formulario.
Los Elementos <fieldset>
y <legend>
Los elementos <fieldset>
y <legend>
se utilizan en HTML para organizar y agrupar elementos relacionados dentro de un formulario, mejorando la estructura y la accesibilidad.
- Elemento
<fieldset>
:- Actúa como un contenedor para agrupar varios controles de formulario, como campos de entrada (
<input>
), checkboxes o botones de radio, que tienen una relación lógica entre sí. - Su propósito principal es agrupar visualmente estos elementos relacionados.
- Actúa como un contenedor para agrupar varios controles de formulario, como campos de entrada (
- Elemento
<legend>
:- Se utiliza para definir un título o una leyenda para el grupo de elementos de formulario contenido dentro de un
<fieldset>
. - ◦ Debe ser el primer elemento hijo de
<fieldset>
.
- Se utiliza para definir un título o una leyenda para el grupo de elementos de formulario contenido dentro de un
Ejemplo:
<div class="ej-container-fieldset">
<form class="ej-form-fieldset">
<fieldset class="ej-fieldset-fieldset">
<legend class="ej-legend-fieldset">Información personal</legend>
<label for="nombre" class="ej-label-fieldset">Nombre:</label>
<input type="text" id="nombre" name="nombre" class="ej-input-fieldset" placeholder="Ingresa tu nombre completo">
<label for="correo" class="ej-label-fieldset">Correo electrónico:</label>
<input type="email" id="correo" name="correo" class="ej-input-fieldset" placeholder="ejemplo@correo.com">
</fieldset>
</form>
</div>
.ej-container-fieldset {
font-family: Arial, sans-serif;
padding: 20px;
margin: 0;
}
.ej-form-fieldset {
max-width: 500px;
margin: 0 auto;
background-color: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.ej-fieldset-fieldset {
border: 2px solid #e0e0e0;
border-radius: 6px;
padding: 20px;
margin: 0;
background-color: #fafafa;
}
.ej-legend-fieldset {
font-size: 18px;
font-weight: bold;
color: #333;
padding: 0 10px;
background-color: white;
border-radius: 4px;
border: 1px solid #e0e0e0;
}
.ej-label-fieldset {
display: block;
margin-bottom: 5px;
font-weight: 500;
color: #555;
}
.ej-input-fieldset {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
margin-bottom: 15px;
box-sizing: border-box;
transition: border-color 0.3s ease;
}
.ej-input-fieldset:focus {
outline: none;
border-color: #4caf50;
box-shadow: 0 0 5px rgba(76, 175, 80, 0.3);
}
.ej-input-fieldset:hover {
border-color: #bbb;
}
Consideraciones importantes <fieldset>
y <legend>
Las casillas de verificación (checkboxes
) también pueden agruparse de manera similar utilizando un <fieldset>
y un <legend>
.
Es fundamental que las casillas de verificación no compartan el mismo atributo name
, ya que no son mutuamente excluyentes y esto podría llevar a un comportamiento indefinido al enviar el formulario. Cada checkbox
debería tener un name
único o usar un conjunto de corchetes ([]
) para indicar que se debe enviar una matriz de valores para esa clave.
Se recomienda mantener el texto del <legend>
corto, ya que algunas combinaciones de navegadores y lectores de pantalla pueden leer la leyenda antes de cada campo de entrada dentro del <fieldset>
lo que podría resultar redundante o molesto para el usuario.
El Elemento <datalist>
El elemento <datalist>
es una característica de HTML5 diseñada para especificar una lista de opciones predefinidas para un campo de entrada (<input>
). Proporciona una función de "autocompletar" o "sugerencia" en los elementos <input />
, permitiendo a los usuarios ver una lista desplegable de opciones a medida que escriben.
No es un menú desplegable fijo (como <select>
), sino una lista de sugerencias: el usuario puede escribir cualquier valor, no está obligado a elegir solo de la lista.
Este elemento es específico de formularios.
Uso y Estructura de <datalist>
Sintaxis básica:
<label for="color">Elige un color:</label>
<input list="colores" id="color" name="color">
<datalist id="colores">
<option value="Rojo">
<option value="Verde">
<option value="Azul">
<option value="Amarillo">
</datalist>
Análisis de cada elemento:
- Etiqueta
<label>
:-
for="color"
: Conecta con el<input>
que tieneid="color"
. - Proporciona accesibilidad y descripción del campo.
- Al hacer clic en la etiqueta, se enfoca el input.
-
- Campo
<input>
:-
list="colores"
: Se conecta con el<datalist id="colores">
. -
id="color"
: Identificador único para el label. -
name="color"
: Nombre para el envío del formulario. - Este campo puede aceptar datos que no estén en la lista.
-
- Lista
<datalist>
:-
id="colores"
: Debe coincidir con el atributo list en<input list="colores">
. - Contiene opciones
<option>
con valores predefinidos. - No es visible por sí mismo, solo aparece como sugerencias.
-
<datalist>
solo contiene elementos<option>
-
- Campo
<option>
- Cada
<option>
debe tener un atributo value (que es el texto que se sugerirá).
- Cada
Ejemplo completo:
Ejemplos de <datalist>
<div class="ej-wrapper-datalist">
<div class="ej-container-datalist">
<p class="ej-h1-datalist">Ejemplos de <datalist></p>
<form id="formulario">
<div class="ej-form-group-datalist">
<label for="navegador" class="ej-label-datalist">Navegador favorito:</label>
<input type="text" id="navegador" name="navegador" list="navegadores" placeholder="Escribe o selecciona un navegador" class="ej-input-datalist">
<datalist id="navegadores">
<option value="Chrome">
<option value="Firefox">
<option value="Safari">
<option value="Edge">
<option value="Opera">
<option value="Internet Explorer">
</datalist>
<div class="ej-description-datalist">Comienza a escribir para ver las sugerencias</div>
</div>
<div class="ej-form-group-datalist">
<label for="pais" class="ej-label-datalist">País:</label>
<input type="text" id="pais" name="pais" list="paises" placeholder="Escribe o selecciona un país" class="ej-input-datalist">
<datalist id="paises">
<option value="España">
<option value="México">
<option value="Argentina">
<option value="Colombia">
<option value="Chile">
<option value="Perú">
<option value="Venezuela">
<option value="Ecuador">
<option value="Uruguay">
<option value="Bolivia">
</datalist>
<div class="ej-description-datalist">Países de habla hispana</div>
</div>
<div class="ej-form-group-datalist">
<label for="color" class="ej-label-datalist">Color favorito:</label>
<input type="text" id="color" name="color" list="colores" placeholder="Escribe o selecciona un color" class="ej-input-datalist">
<datalist id="colores">
<option value="Rojo">
<option value="Azul">
<option value="Verde">
<option value="Amarillo">
<option value="Naranja">
<option value="Violeta">
<option value="Rosa">
<option value="Negro">
<option value="Blanco">
<option value="Gris">
</datalist>
<div class="ej-description-datalist">También puedes escribir cualquier otro color</div>
</div>
<div class="ej-form-group-datalist">
<label for="lenguaje" class="ej-label-datalist">Lenguaje de programación:</label>
<input type="text" id="lenguaje" name="lenguaje" list="lenguajes" placeholder="Escribe o selecciona un lenguaje" class="ej-input-datalist">
<datalist id="lenguajes">
<option value="JavaScript">
<option value="Python">
<option value="Java">
<option value="C++">
<option value="C#">
<option value="PHP">
<option value="Ruby">
<option value="Go">
<option value="Rust">
<option value="Swift">
</datalist>
<div class="ej-description-datalist">Lenguajes de programación populares</div>
</div>
<button type="button" onclick="mostrarResultados()" class="ej-button-datalist">Mostrar selecciones</button>
</form>
<div id="resultado" class="ej-result-datalist" style="display: none;">
<p class="ej-h3-datalist">Tus selecciones:</p>
<div id="contenido-resultado"></div>
</div>
</div>
</div>
.ej-wrapper-datalist {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 50px auto;
padding: 20px;
background-color: #f5f5f5;
}
.ej-container-datalist {
background: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.ej-h1-datalist {
color: #333;
text-align: center;
margin-bottom: 30px;
font-size: 2em;
font-weight: bold;
margin-top: 0;
}
.ej-form-group-datalist {
margin-bottom: 25px;
}
.ej-label-datalist {
display: block;
margin-bottom: 8px;
font-weight: bold;
color: #555;
}
.ej-input-datalist {
width: 100%;
padding: 12px;
border: 2px solid #ddd;
border-radius: 5px;
font-size: 16px;
transition: border-color 0.3s;
}
.ej-input-datalist:focus {
outline: none;
border-color: #4CAF50;
}
.ej-description-datalist {
margin-top: 5px;
font-size: 14px;
color: #666;
}
.ej-result-datalist {
margin-top: 20px;
padding: 15px;
background-color: #e8f5e8;
border-radius: 5px;
border-left: 4px solid #4CAF50;
}
.ej-button-datalist {
background-color: #4CAF50;
color: white;
padding: 12px 25px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
margin-top: 10px;
}
.ej-button-datalist:hover {
background-color: #45a049;
}
.ej-h3-datalist {
font-size: 1.2em;
font-weight: bold;
margin-top: 0;
margin-bottom: 10px;
color: #333;
}
.ej-p-datalist {
margin: 5px 0;
color: #333;
}
Ejemplo Práctico de Formulario HTML
Formulario Completo
Ejemplo con todos los tipos de entrada HTML
<div class="ej-body-ej-form">
<div class="ej-container-ej-form">
<p class="ej-h1-ej-form">Formulario Completo</p>
<p class="ej-subtitle-ej-form">
Ejemplo con todos los tipos de entrada HTML
</p>
<form
class="ej-form-ej-form"
action="#"
method="POST"
>
<!-- Información Personal -->
<div class="ej-section-ej-form">
<p class="ej-section-title-ej-form">
📋 Información Personal
</p>
<div class="ej-field-group-ej-form">
<div class="ej-field-row-ej-form">
<div>
<label
class="ej-label-ej-form"
for="nombre"
>Nombre completo</label
>
<input
class="ej-input-ej-form"
type="text"
id="nombre"
name="nombre"
placeholder="Tu nombre completo"
required
/>
</div>
<div>
<label
class="ej-label-ej-form"
for="email"
>Correo electrónico</label
>
<input
class="ej-input-ej-form"
type="email"
id="email"
name="email"
placeholder="tu@email.com"
required
/>
</div>
</div>
<div class="ej-field-row-ej-form">
<div>
<label
class="ej-label-ej-form"
for="telefono"
>Teléfono</label
>
<input
class="ej-input-ej-form"
type="tel"
id="telefono"
name="telefono"
placeholder="+1 234 567 8900"
/>
</div>
<div>
<label
class="ej-label-ej-form"
for="fecha-nacimiento"
>Fecha de nacimiento</label
>
<input
class="ej-input-ej-form"
type="date"
id="fecha-nacimiento"
name="fecha_nacimiento"
/>
</div>
</div>
<div>
<label
class="ej-label-ej-form"
for="url-personal"
>Sitio web personal</label
>
<input
class="ej-input-ej-form"
type="url"
id="url-personal"
name="url_personal"
placeholder="https://tusitio.com"
/>
</div>
</div>
</div>
<!-- Información de Contacto -->
<div class="ej-section-ej-form">
<p class="ej-section-title-ej-form">
🏠 Información de Contacto
</p>
<div class="ej-field-group-ej-form">
<div>
<label
class="ej-label-ej-form"
for="direccion"
>Dirección</label
>
<textarea
class="ej-input-ej-form ej-textarea-ej-form"
id="direccion"
name="direccion"
placeholder="Tu dirección completa"
></textarea>
</div>
<div class="ej-field-row-ej-form">
<div>
<label class="ej-label-ej-form" for="pais"
>País</label
>
<select
class="ej-input-ej-form ej-select-ej-form"
id="pais"
name="pais"
>
<option value="">
Selecciona un país
</option>
<option value="es">España</option>
<option value="mx">México</option>
<option value="ar">Argentina</option>
<option value="co">Colombia</option>
<option value="pe">Perú</option>
</select>
</div>
<div>
<label
class="ej-label-ej-form"
for="codigo-postal"
>Código postal</label
>
<input
class="ej-input-ej-form"
type="text"
id="codigo-postal"
name="codigo_postal"
pattern="[0-9]{5}"
placeholder="12345"
/>
</div>
</div>
</div>
</div>
<!-- Configuración de Cuenta -->
<div class="ej-section-ej-form">
<p class="ej-section-title-ej-form">
🔐 Configuración de Cuenta
</p>
<div class="ej-field-group-ej-form">
<div class="ej-field-row-ej-form">
<div>
<label
class="ej-label-ej-form"
for="password"
>Contraseña</label
>
<input
class="ej-input-ej-form"
type="password"
id="password"
name="password"
placeholder="Mínimo 8 caracteres"
minlength="8"
required
/>
</div>
<div>
<label
class="ej-label-ej-form"
for="confirm-password"
>Confirmar contraseña</label
>
<input
class="ej-input-ej-form"
type="password"
id="confirm-password"
name="confirm_password"
placeholder="Repite tu contraseña"
minlength="8"
required
/>
</div>
</div>
<div>
<label class="ej-label-ej-form" for="edad"
>Edad</label
>
<input
class="ej-input-ej-form"
type="number"
id="edad"
name="edad"
min="18"
max="100"
placeholder="25"
/>
</div>
</div>
</div>
<!-- Preferencias -->
<div class="ej-section-ej-form">
<p class="ej-section-title-ej-form">
⚙️ Preferencias
</p>
<div class="ej-field-group-ej-form">
<div>
<label class="ej-label-ej-form"
>Género</label
>
<div class="ej-radio-group-ej-form">
<label class="ej-radio-item-ej-form">
<input
class="ej-radio-ej-form"
type="radio"
name="genero"
value="masculino"
/>
Masculino
</label>
<label class="ej-radio-item-ej-form">
<input
class="ej-radio-ej-form"
type="radio"
name="genero"
value="femenino"
/>
Femenino
</label>
<label class="ej-radio-item-ej-form">
<input
class="ej-radio-ej-form"
type="radio"
name="genero"
value="otro"
/>
Otro
</label>
</div>
</div>
<div>
<label class="ej-label-ej-form"
>Intereses</label
>
<div class="ej-checkbox-group-ej-form">
<label class="ej-checkbox-item-ej-form">
<input
class="ej-checkbox-ej-form"
type="checkbox"
name="intereses[]"
value="tecnologia"
/>
Tecnología
</label>
<label class="ej-checkbox-item-ej-form">
<input
class="ej-checkbox-ej-form"
type="checkbox"
name="intereses[]"
value="deportes"
/>
Deportes
</label>
<label class="ej-checkbox-item-ej-form">
<input
class="ej-checkbox-ej-form"
type="checkbox"
name="intereses[]"
value="musica"
/>
Música
</label>
<label class="ej-checkbox-item-ej-form">
<input
class="ej-checkbox-ej-form"
type="checkbox"
name="intereses[]"
value="arte"
/>
Arte
</label>
<label class="ej-checkbox-item-ej-form">
<input
class="ej-checkbox-ej-form"
type="checkbox"
name="intereses[]"
value="viajes"
/>
Viajes
</label>
</div>
</div>
<div>
<label
class="ej-label-ej-form"
for="nivel-experiencia"
>Nivel de experiencia (1-10)</label
>
<div class="ej-range-container-ej-form">
<input
class="ej-range-ej-form"
type="range"
id="nivel-experiencia"
name="nivel_experiencia"
min="1"
max="10"
value="5"
oninput="document.getElementById('range-value').textContent = this.value"
/>
<span
class="ej-range-value-ej-form"
id="range-value"
>5</span
>
</div>
</div>
<div class="ej-field-row-ej-form">
<div>
<label
class="ej-label-ej-form"
for="color-favorito"
>Color favorito</label
>
<input
class="ej-input-ej-form ej-color-ej-form"
type="color"
id="color-favorito"
name="color_favorito"
value="#667eea"
/>
</div>
<div>
<label
class="ej-label-ej-form"
for="hora-preferida"
>Hora preferida para contacto</label
>
<input
class="ej-input-ej-form"
type="time"
id="hora-preferida"
name="hora_preferida"
/>
</div>
</div>
<div class="ej-field-row-ej-form">
<div>
<label
class="ej-label-ej-form"
for="fecha-evento"
>Fecha para evento</label
>
<input
class="ej-input-ej-form"
type="datetime-local"
id="fecha-evento"
name="fecha_evento"
/>
</div>
<div>
<label
class="ej-label-ej-form"
for="semana"
>Semana del año</label
>
<input
class="ej-input-ej-form"
type="week"
id="semana"
name="semana"
/>
</div>
</div>
<div>
<label class="ej-label-ej-form" for="mes"
>Mes preferido</label
>
<input
class="ej-input-ej-form"
type="month"
id="mes"
name="mes"
/>
</div>
</div>
</div>
<!-- Archivos y Datos Adicionales -->
<div class="ej-section-ej-form">
<p class="ej-section-title-ej-form">
📁 Archivos y Información Adicional
</p>
<div class="ej-field-group-ej-form">
<div>
<label
class="ej-label-ej-form"
for="archivo"
>Subir archivo (CV, portafolio,
etc.)</label
>
<input
class="ej-input-ej-form ej-file-ej-form"
type="file"
id="archivo"
name="archivo"
multiple
accept=".pdf,.doc,.docx,.jpg,.png"
/>
</div>
<div>
<label
class="ej-label-ej-form"
for="busqueda"
>Término de búsqueda</label
>
<input
class="ej-input-ej-form"
type="search"
id="busqueda"
name="busqueda"
placeholder="Buscar..."
/>
</div>
<div>
<label
class="ej-label-ej-form"
for="comentarios"
>Comentarios adicionales</label
>
<textarea
class="ej-input-ej-form ej-textarea-ej-form"
id="comentarios"
name="comentarios"
placeholder="Cuéntanos más sobre ti..."
rows="4"
></textarea>
</div>
<!-- Campo oculto -->
<input
type="hidden"
name="formulario_id"
value="form_001"
/>
<div>
<label class="ej-checkbox-item-ej-form">
<input
class="ej-checkbox-ej-form"
type="checkbox"
name="terminos"
value="1"
required
/>
Acepto los términos y condiciones
</label>
</div>
<div>
<label class="ej-checkbox-item-ej-form">
<input
class="ej-checkbox-ej-form"
type="checkbox"
name="newsletter"
value="1"
/>
Suscribirme al boletín de noticias
</label>
</div>
</div>
</div>
<!-- Botón de envío -->
<button class="ej-submit-ej-form" type="submit">
🚀 Enviar Formulario
</button>
</form>
</div>
</div>
.ej-body-ej-form {
margin: 0;
padding: 0;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.ej-container-ej-form {
background: rgba(255, 255, 255, 0.95);
border-radius: 20px;
padding: 40px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(10px);
max-width: 600px;
width: 90%;
margin: 20px;
}
.ej-h1-ej-form {
text-align: center;
color: #4a5568;
font-size: 2.5rem;
margin-bottom: 10px;
font-weight: 700;
}
.ej-subtitle-ej-form {
text-align: center;
color: #718096;
margin-bottom: 30px;
font-style: italic;
}
.ej-form-ej-form {
display: grid;
gap: 20px;
}
.ej-section-ej-form {
background: rgba(247, 250, 252, 0.8);
padding: 25px;
border-radius: 15px;
border-left: 4px solid #667eea;
}
.ej-section-title-ej-form {
color: #2d3748;
font-size: 1.3rem;
margin-bottom: 15px;
font-weight: 600;
}
.ej-field-group-ej-form {
display: grid;
gap: 15px;
}
.ej-field-row-ej-form {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 15px;
}
.ej-label-ej-form {
display: block;
color: #4a5568;
font-weight: 500;
margin-bottom: 5px;
font-size: 0.9rem;
}
.ej-input-ej-form {
width: 100%;
padding: 12px 15px;
border: 2px solid #e2e8f0;
border-radius: 10px;
font-size: 1rem;
transition: all 0.3s ease;
background: white;
box-sizing: border-box;
}
.ej-input-ej-form:focus {
outline: none;
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
transform: translateY(-2px);
}
.ej-textarea-ej-form {
resize: vertical;
min-height: 100px;
}
.ej-select-ej-form {
cursor: pointer;
}
.ej-checkbox-group-ej-form {
display: flex;
flex-wrap: wrap;
gap: 15px;
margin-top: 10px;
}
.ej-checkbox-item-ej-form {
display: flex;
align-items: center;
cursor: pointer;
color: var(--color-fondo); /* Color de texto oscuro para visibilidad */
font-weight: 500;
}
.ej-checkbox-ej-form {
margin-right: 8px;
transform: scale(1.2);
accent-color: #667eea;
}
.ej-radio-group-ej-form {
display: flex;
gap: 20px;
margin-top: 10px;
}
.ej-radio-item-ej-form {
display: flex;
align-items: center;
cursor: pointer;
color: var(--color-fondo); /* Color de texto oscuro para visibilidad */
font-weight: 500;
}
.ej-radio-ej-form {
margin-right: 8px;
transform: scale(1.2);
accent-color: #667eea;
}
.ej-file-ej-form {
border: 2px dashed #cbd5e0;
background: rgba(247, 250, 252, 0.5);
cursor: pointer;
}
.ej-file-ej-form:hover {
border-color: #667eea;
background: rgba(102, 126, 234, 0.05);
}
.ej-range-container-ej-form {
display: flex;
align-items: center;
gap: 15px;
}
.ej-range-ej-form {
flex: 1;
height: 6px;
border-radius: 3px;
background: #e2e8f0;
outline: none;
accent-color: #667eea;
}
.ej-range-value-ej-form {
background: #667eea;
color: white;
padding: 5px 10px;
border-radius: 5px;
font-weight: 600;
min-width: 40px;
text-align: center;
}
.ej-color-ej-form {
height: 50px;
border-radius: 10px;
cursor: pointer;
}
.ej-submit-ej-form {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 15px 40px;
border: none;
border-radius: 50px;
font-size: 1.1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
margin-top: 20px;
width: 200px;
justify-self: center;
}
.ej-submit-ej-form:hover {
transform: translateY(-3px);
box-shadow: 0 10px 25px rgba(102, 126, 234, 0.3);
}
.ej-submit-ej-form:active {
transform: translateY(-1px);
}
@media (max-width: 768px) {
.ej-field-row-ej-form {
grid-template-columns: 1fr;
}
.ej-radio-group-ej-form,
.ej-checkbox-group-ej-form {
flex-direction: column;
}
}