diff options
Diffstat (limited to 'files/es/learn/forms')
12 files changed, 5814 insertions, 0 deletions
diff --git a/files/es/learn/forms/basic_native_form_controls/index.html b/files/es/learn/forms/basic_native_form_controls/index.html new file mode 100644 index 0000000000..c8a2651837 --- /dev/null +++ b/files/es/learn/forms/basic_native_form_controls/index.html @@ -0,0 +1,326 @@ +--- +title: Controles de formulario originales +slug: Learn/HTML/Forms/The_native_form_widgets +translation_of: Learn/Forms/Basic_native_form_controls +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Forms/How_to_structure_an_HTML_form", "Learn/Forms/HTML5_input_types", "Learn/Forms")}}</div> + +<p class="summary">En el <a href="/es/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">artículo anterior</a>, marcamos un ejemplo de formulario web funcional, presentamos algunos controles de formulario y elementos estructurales comunes, y nos centramos en las mejores prácticas de accesibilidad. A continuación, veremos con detalle las funciones de los diferentes controles de formulario, o <em>widgets</em>, y estudiaremos todas las diferentes opciones de que se dispone para la recopilación de diferentes tipos de datos. En este artículo en particular, veremos el conjunto original de controles de formulario, disponible en todos los navegadores desde los primeros días de la web.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática y de <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">lenguaje HTML</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Comprender en detalle el conjunto original de controles de formulario originales disponibles en los navegadores para la recopilación de datos y su implementación con HTML.</td> + </tr> + </tbody> +</table> + +<p>Ya conoces algunos elementos de formulario, incluidos {{HTMLelement ('form')}}, {{HTMLelement ('fieldset')}}, {{HTMLelement ('legend')}}, {{HTMLelement ('textarea' )}}, {{HTMLelement ('label')}}, {{HTMLelement ('button')}} y {{HTMLelement ('input')}}. Este artículo expone:</p> + +<ul> + <li>Los tipos de entrada comunes {{HTMLelement('input/button', 'button')}}, {{HTMLelement('input/checkbox', 'checkbox')}}, {{HTMLelement('input/file', 'file')}}, {{HTMLelement('input/hidden', 'hidden')}}, {{HTMLelement('input/image', 'image')}}, {{HTMLelement('input/password', 'password')}}, {{HTMLelement('input/radio', 'radio')}}, {{HTMLelement('input/reset', 'reset')}}, {{HTMLelement('input/submit', 'submit')}} y {{HTMLelement('input/text', 'text')}}.</li> + <li>Algunos de los atributos que comunes para todos los controles de formulario.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Las características que se consideran en este artículo son compatibles con todos los navegadores, lo que no es el caso para todos los controles de formulario. En los próximos dos artículos vamos a exponer los controles de formulario que se han añadido a HTML5 más recientemente. Si quieres una referencia más avanzada, consulta nuestra <a href="/es/docs/Web/HTML/Elemento#Formularios">referencia a elementos de formulario HTML</a>, y en particular nuestra extensa referencia a <a href="/es/docs/Web/HTML/Elemento/input">tipos <input></a>.</p> +</div> + +<h2 id="Campos_de_entrada_de_texto">Campos de entrada de texto</h2> + +<p>Los campos de texto {{htmlelement ("input")}} son los controles de formulario más básicos. Son un modo muy cómodo de permitir al usuario introducir cualquier tipo de datos, y ya hemos visto algunos ejemplos sencillos.</p> + +<div class="note"> +<p><strong>Nota</strong>: Los campos de texto de los formularios HTML son controles de entrada de texto sencillos sin formato. Esto significa que no puedes usarlos para aplicar una <a href="/en-US/docs/Rich-Text_Editing_in_Mozilla" title="/en-US/docs/Rich-Text_Editing_in_Mozilla">edición enriquecida </a> (negrita, cursiva, etc.). Todos los controles de formulario que encuentres con texto enriquecido son controles de formulario personalizados creados con HTML, CSS y JavaScript.</p> +</div> + +<p>Todos los controles de texto básicos comparten algunos comportamientos comunes:</p> + +<ul> + <li>Se pueden marcar como {{htmlattrxref ("readonly","input")}} (el usuario no puede modificar el valor de entrada, pero este se envía con el resto de los datos del formulario) o {{htmlattrxref ("disabled","input")}} (el valor de entrada no se puede modificar y nunca se envía con el resto de los datos del formulario).</li> + <li>Pueden tener un {{htmlattrxref ("placeholder","input")}}; se trata de un texto que aparece dentro de la caja de entrada de texto y que se usa para describir brevemente el propósito de la caja de texto.</li> + <li>Pueden presentar una limitación de <a href="/en-US/docs/Web/HTML/Attributes/size">tamaño</a> (el tamaño físico de la caja de texto) y de la <a href="/en-US/docs/Web/HTML/Attributes/maxlength" title="/en-US/docs/HTML/Element/input#attr-maxlength">extensión máxima</a> (el número máximo de caracteres que se pueden poner en la caja de texto).</li> + <li>Admiten <a href="/en-US/docs/HTML/Element/input#attr-spellcheck" title="/en-US/docs/HTML/Element/input#attr-spellcheck"> corrección ortográfica</a> (utilizando el atributo <a href="/en-US/docs/Web/HTML/Attributes/spellcheck"><code>spellcheck</code></a>), si el navegador la admite.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: El elemento {{htmlelement ("input")}} es único entre los elementos HTML porque puede tomar muchas formas diferentes según el valor de su atributo. Se utiliza para crear la mayoría de los tipos de controles de formulario, que incluyen campos de texto de una sola línea, controles para la fecha y la hora, controles sin introducción de texto, como casillas de verificación, botones de opción y selectores de color, y botones.</p> +</div> + +<h3 id="Campos_de_texto_de_una_sola_línea">Campos de texto de una sola línea</h3> + +<p>Un campo de texto de una sola línea se crea utilizando un elemento {{HTMLElement ("input")}} cuyo valor de atributo {{htmlattrxref ("type","input")}} se establece en <code>text</code>, u omitiendo por completo el atributo {{htmlattrxref ( "type","input")}} (<code>text</code> es el valor predeterminado). El valor <code>text</code> de este atributo también es el valor alternativo si el navegador no reconoce el valor que has especificado para el atributo {{htmlattrxref ("type","input")}} (por ejemplo, si especificas <code>type="color"</code> y el navegador no está dotado en origen de un control de selección de colores).</p> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar ejemplos de todos los tipos de campo de texto de una sola línea en GitHub en <a href="https://github.com/mdn/learning-area/blob/master/html/forms/native-form-widgets/single-line-text-fields.html">single-line-text-fields.html</a> (<a href="https://mdn.github.io/learning-area/html/forms/native-form-widgets/single-line-text-fields.html">o consultarlo en vivo</a>).</p> +</div> + +<p>Aquí hay un ejemplo básico de campo de texto de una sola línea:</p> + +<pre class="brush: html notranslate"><input type="text" id="comment" name="comment" value="I'm a text field"></pre> + +<p>Los campos de texto de una sola línea solo tienen una restricción verdadera: si escribes el texto con saltos de línea, el navegador elimina esos saltos de línea antes de enviar los datos al servidor.</p> + +<p><em>La captura de pantalla siguiente muestra los tipos de entrada de texto predeterminado, activo (con el foco) y deshabilitado en Firefox 71 y Safari en macOS y en Chrome 79 y Edge 18 en Windows 10.</em></p> + +<p><img alt="Captura de pantalla del atributo deshabilitado y predeterminado: estilo para una entrada de texto activa (con el foco) en Firefox, Safari, Chrome y Edge." src="https://mdn.mozillademos.org/files/17021/disabled.png" style="height: 113px; width: 442px;"></p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: HTML5 ha mejorado el campo de texto básico original de una sola línea al añadir valores especiales para el atributo {{htmlattrxref ("type", "input")}} que imponen restricciones de validación específicas y otras características, por ejemplo, específicas para introducir direcciones URL o números. Los expondremos en el artículo siguiente: <a href="/en-US/docs/Learn/Forms/HTML5_input_types">Los tipos de entrada en HTML5</a>.</p> +</div> + +<h4 id="Campo_de_contraseña">Campo de contraseña</h4> + +<p>Uno de los tipos de entrada originales era el tipo de campo de texto <code>password</code>:</p> + +<pre class="brush: html notranslate"><input type="password" id="pwd" name="pwd"></pre> + +<p>El valor de la contraseña no añade restricciones especiales al texto que se introduce, pero oculta el valor que se introduce en el campo (por ejemplo, con puntos o asteriscos) para impedir que otros puedan leerlo.</p> + +<p>Ten en cuenta que esto es solo una función de interfaz de usuario; a menos que envíes tu formulario en modo seguro, se enviará como texto plano, lo que es malo desde el punto de vista de la seguridad porque alguien con malas intenciones podría interceptar tus datos y robar tus contraseñas, datos de tarjetas de crédito o cualquier otra cosa que hayas enviado. La mejor manera de proteger a los usuarios de esto es alojar cualquier página que contenga formularios en una ubicación de conexión segura (es decir, en una dirección <code>https://</code>), de modo que los datos se cifren antes de enviarse.</p> + +<p>Los navegadores reconocen las implicaciones de seguridad de enviar datos de formulario por una conexión insegura y disponen de mensajes de advertencia para disuadir a los usuarios de usar formularios no seguros. Para obtener más información sobre las implementaciones de Firefox al respecto, consulta el artículo <a href="/es/docs/Seguridad/ContraseñasInseguras">Contraseñas inseguras</a>.</p> + +<h3 id="Contenido_oculto">Contenido oculto</h3> + +<p>Otro control de texto original es el tipo de entrada <code>hidden</code>. Se usa para crear un control de formulario que es invisible para el usuario, pero que aun así se envía al servidor junto con el resto de los datos del formulario una vez se transmiten; por ejemplo, es posible que desees enviar una marca de tiempo al servidor que indique cuándo se realizó un pedido. Al estar oculto, el usuario no puede ver ni editar su valor intencionadamente, el control nunca recibirá el foco y un lector de pantalla tampoco lo detectará.</p> + +<pre class="brush: html notranslate"><input type="hidden" id="timestamp" name="timestamp" value="1286705410"> +</pre> + +<p>Si creas un elemento así, es necesario establecer sus atributos <code>name</code> y <code>value</code>. Su valor puede establecerse dinámicamente a través de JavaScript. El tipo de entrada oculta no debe tener ninguna etiqueta asociada.</p> + +<p>Otros tipos de entrada de texto, como {{HTMLElement ("input / search", "search")}}, {{HTMLElement ("input / url", "url")}} y {{HTMLElement ("input / tel" , "tel")}}, se añadieron con HTML5. Se tratarán en el próximo artículo: Tipos de entrada HTML5.</p> + +<h2 id="Elementos_de_selección_casillas_de_verificación_y_botones_de_opción">Elementos de selección: casillas de verificación y botones de opción</h2> + +<p>Los elementos de selección (o <em>checkable items</em>, en inglés) son controles cuyo estado puede cambiar cuando se hace clic en ellos o en sus etiquetas asociadas. Hay dos tipos de elementos de selección: las casillas de verificación (o <em>check boxes</em>) y los botones de opción (o <em>radio buttons</em>). Ambos usan el atributo <code>checked</code> para indicar si el control de formulario está seleccionado por defecto o no.</p> + +<p>Vale la pena señalar que estos controles no se comportan exactamente como otros controles de formulario. Para la mayoría de los controles de formulario, cuando se envía el formulario, se envían todos los controles que tienen un atributo <a href="/en-US/docs/Web/HTML/Attributes/name"><code>name</code></a>, incluso si en ellos no se ha introducido ningún valor. En el caso de elementos de selección, sus valores se envían solo si están seleccionados. Si no están seleccionados, no se envía nada, ni siquiera su nombre. Si están seleccionados pero no tienen ningún valor asignado, el nombre se envía con el valor <em>on.</em></p> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar los ejemplos de esta sección en GitHub como <a href="https://github.com/mdn/learning-area/blob/master/html/forms/native-form-widgets/checkable-items.html">checkable-items.html</a> (<a href="https://mdn.github.io/learning-area/html/forms/native-form-widgets/checkable-items.html">o consultarlos en vivo</a>).</p> +</div> + +<p>Para una usabilidad/accesibilidad óptima, te recomendamos delimitar cada lista de elementos que estén relacionados entre sí dentro de un elemento {{htmlelement ("fieldset")}} con un elemento {{htmlelement ("legend")}} que proporcione una descripción general de la lista. Cada par individual de elementos {{htmlelement ("label")}}/{{htmlelement ("input")}} ha de estar contenido en un elemento de lista propio (o similar). El elemento {{htmlelement ('label')}} asociado se coloca en general inmediatamente después del botón de opción o la casilla de verificación, con las instrucciones para el grupo de botones de opción o casillas de verificación, que suelen ser el contenido del elemento {{htmlelement ("legend")}}. Observa las estructuras de ejemplo en los ejemplos asociados anteriores.</p> + +<h3 id="Casillas_de_verificación">Casillas de verificación</h3> + +<p>Las casillas de verificación se crean estableciendo el atributo <a href="/en-US/docs/Web/HTML/Attributes/type"><code>type</code></a> del elemento {{HTMLElement ("input")}} en el valor {{HTMLElement ("input / checkbox", "checkbox")}}.</p> + +<pre class="brush: html notranslate"><input type="checkbox" id="carrots" name="carrots" value="carrots" checked> +</pre> + +<p>Al incluir el atributo <code><a href="/en-US/docs/Web/HTML/Attributes/checked">checked</a></code>, la casilla de verificación se marca automáticamente cuando se carga la página. Al hacer clic en la casilla de verificación o en su etiqueta asociada, la casilla de verificación se activa o desactiva.</p> + +<p>Las capturas de pantalla siguientes muestran casillas de verificación predeterminadas, activas (con el foco) y deshabilitadas en Firefox 71 y Safari 13 en macOS y Chrome 79 y Edge 18 en Windows 10:</p> + +<p><img alt="Casillas de verificación predeterminadas, activas y deshabilitadas en Firefox 71 y Safari 13 en Mac y Chrome 79 y Edge 18 en Windows 10" src="https://mdn.mozillademos.org/files/17024/checkboxes.png" style="height: 203px; width: 293px;"></p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Las casillas de verificación y los botones de opción con atributo <code><a href="/en-US/docs/Web/HTML/Attributes/checked">checked</a></code> al cargarse coinciden con la pseudoclase {{cssxref ('<code>:default</code>')}}, incluso aunque ya no estén seleccionadas. Las que están seleccionadas coinciden con la pseudoclase <code>{{cssxref(':checked')}}</code>.</p> +</div> + +<p id="Radio_button">Debido a su naturaleza activa-inactiva, las casillas de verificación se consideran botones de conmutación, y muchos desarrolladores y diseñadores han ampliado el estilo de casilla de verificación predeterminado para crear botones que parecen interruptores de conmutación. Aquí puedes ver un <a href="https://mdn.github.io/learning-area/html/forms/toggle-switch-example/">ejemplo en acción</a> (observa también el <a href="https://github.com/mdn/learning-area/blob/master/html/forms/toggle-switch-example/index.html">código fuente</a>).</p> + +<h3 id="Botón_de_opción">Botón de opción</h3> + +<p>Un botón de opción se crea estableciendo el atributo {{htmlattrxref ("type", "input")}} del elemento {{HTMLElement ("input")}} en el valor <code>radio</code>:</p> + +<pre class="brush: html notranslate"><input type="radio" id="soup" name="meal" checked></pre> + +<p>Es posible asociar diversos botones de opción. Si comparten el mismo valor de atributo {{htmlattrxref ("name", "input")}}, se considera que están en el mismo grupo de botones. Solo un botón dentro de un grupo puede estar activado en cada momento. Esto significa que cuando uno de ellos se selecciona, todos los demás se deseleccionan automáticamente. Al enviar el formulario, solo se envía el valor del botón de opción seleccionado. Si ninguno de ellos está seleccionado, se considera que el conjunto completo de botones de opción está en un estado desconocido y no se envía ningún valor con el formulario. Cuando en un grupo de botones con el mismo nombre se selecciona uno de los botones de opción, no es posible deseleccionar todos los botones sin reiniciar el formulario.</p> + +<pre class="brush: html notranslate"><fieldset> + <legend>¿Cuál es tu comida favorita?</legend> + <ul> + <li> + <label for="soup">Sopa</label> + <input type="radio" id="soup" name="meal" value="soup" checked> + </li> + <li> + <label for="curry">Curry</label> + <input type="radio" id="curry" name="meal" value="curry"> + </li> + <li> + <label for="pizza">Pizza</label> + <input type="radio" id="pizza" name="meal" value="pizza"> + </li> + </ul> +</fieldset></pre> + +<p>Las capturas de pantalla siguientes muestran botones de opción sin seleccionar y seleccionados, algunos con el foco y otros desactivados sin seleccionar y seleccionados, en Firefox 71 y Safari 13 en MacOS y Chrome 79 y Edge 18 en Windows 10.</p> + +<p><img alt="Botones de opción en Firefox 71 y Safari 13 en Mac y Chrome 79 y Edge 18 en Windows 10" src="https://mdn.mozillademos.org/files/17022/radios.png" style="height: 142px; width: 196px;"></p> + +<h2 id="Botones">Botones</h2> + +<p>El botón de opción no es realmente un botón, a pesar de su nombre; sigamos adelante y echemos un vistazo a los controles de formulario que son botones propiamente. Hay tres tipos de entrada según el tipo de botones que se utilicen:</p> + +<dl> + <dt><code>submit</code></dt> + <dd>Envía los datos del formulario al servidor. Para los elementos {{HTMLElement ("button")}}, omitir el atributo <code>type</code> (o introducir un valor de tipo no válido) da como resultado un botón de envío (<em>submit</em>).</dd> + <dt><code>reset</code></dt> + <dd>Restablece todos los controles de formulario a sus valores por defecto.</dd> + <dt><code>button</code></dt> + <dd>Botones que no tienen efecto automático, pero que se pueden personalizar con código JavaScript.</dd> +</dl> + +<p>Además, el elemento {{htmlelement ("button")}} puede tomar un atributo <code>type</code> para imitar estos tres tipos de entrada. La diferencia principal entre los dos es que los elementos <code><button></code> propiamente admiten aplicación de estilo en mayor medida.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: El tipo de entrada <code>image</code> también se representa como un botón. También desarrollaremos este tema más adelante.</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar los ejemplos de esta sección en GitHub como <a href="https://github.com/mdn/learning-area/blob/master/html/forms/native-form-widgets/button-examples.html">button-examples.html</a> (<a href="https://mdn.github.io/learning-area/html/forms/native-form-widgets/button-examples.html">o consultarlos en vivo</a>).</p> +</div> + +<p>A continuación puedes encontrar ejemplos de cada tipo de botón <code><input></code>, junto con el tipo de botón equivalente.</p> + +<h3 id="enviar">enviar</h3> + +<pre class="brush: html notranslate"><button type="submit"> + Este es un <strong>botón de envío</strong> +</button> + +<input type="submit" value="Este es un botón de envío"></pre> + +<h3 id="reiniciar">reiniciar</h3> + +<pre class="brush: html notranslate"><button type="reset"> + Este es un <strong>botón de reinicio</strong> +</button> + +<input type="reset" value="Este es un botón de reinicio"></pre> + +<h3 id="anónimo">anónimo</h3> + +<pre class="brush: html notranslate"><button type="button"> + Este es un <strong>botón anónimo</strong> +</button> + +<input type="button" value="Este es un botón anónimo"></pre> + +<p>Los botones siempre se comportan igual, independientemente de su usas un elemento {{HTMLElement ("button")}} o un elemento {{HTMLElement ("input")}}. Sin embargo, como puedes ver en los ejemplos, los elementos {{HTMLElement ("button")}} te permiten usar HTML en tu contenido, que se inserta entre las etiquetas <code><button></code> de apertura y cierre. Los elementos {{HTMLElement ("input")}}, por otro lado, son elementos vacíos; el contenido que muestran está inserto en el atributo <code>value</code> y, por lo tanto, solo acepta contenido de texto sin formato.</p> + +<p>Los ejemplos siguientes muestran los tipos de entrada de botones predeterminados, activos y deshabilitados: en Firefox 71 y Safari 13 en macOS, y Chrome 79 y Edge 18 en Windows 10.</p> + +<p><img alt="Tipos de entrada de botones predeterminados, activos y deshabilitados en Firefox 71 y Safari 13 en Mac y Chrome 79 y Edge 18 en Windows 10" src="https://mdn.mozillademos.org/files/17023/buttons.png" style="height: 182px; width: 286px;"></p> + +<h3 id="Botón_de_imagen">Botón de imagen</h3> + +<p>El control <strong>botón de imagen</strong> se muestra exactamente como un elemento {{HTMLElement ("img")}}, excepto que cuando el usuario hace clic en él, se comporta como un botón de envío.</p> + +<p>Se crea un botón de imagen usando un elemento {{HTMLElement ("input")}} con su atributo {{htmlattrxref ("type","input")}} establecido en el valor <code>image</code>. Este elemento admite exactamente el mismo conjunto de atributos que el elemento {{HTMLElement ("img")}}, además de todos los atributos que admiten el resto de botones de formulario.</p> + +<pre class="brush: html notranslate"><input type="image" alt="¡Púlsame!" src="my-img.png" width="80" height="30"></pre> + +<p>Si el botón de imagen se usa para enviar un formulario, este control no envía su valor; en lugar de ello se envían las coordenadas X e Y del clic que se ha hecho sobre la imagen (las coordenadas son relativas a la imagen, lo que significa que la esquina superior izquierda de la imagen representa la coordenada (0, 0)). Las coordenadas se envían como dos pares clave/valor:</p> + +<ul> + <li>La clave del valor X es el valor del atributo {{htmlattrxref ("name","input")}} seguido de la cadena de caracteres «<em>.x</em>».</li> + <li>La clave del valor Y es el valor del atributo {{htmlattrxref ("name","input")}} seguido de la cadena de caracteres «<em>.y</em>».</li> +</ul> + +<p>Por ejemplo, cuando haces clic en las coordenadas (123, 456) de la imagen y se hace el envío por el método <code>get</code>, verás los valores añadidos a la URL de la manera siguiente:</p> + +<pre class="notranslate">http://foo.com?pos.x=123&pos.y=456</pre> + +<p>Esta es una forma muy cómoda de construir un «mapa dinámico». La forma en que se envían y recuperan estos valores se detalla en el artículo <a href="/es/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Enviar los datos del formulario</a>.</p> + +<h2 id="Selector_de_archivos">Selector de archivos</h2> + +<p>Hay un último tipo de <code><input></code> que nos llegó a principios del HTML: el tipo entrada de archivo. Los formularios pueden enviar archivos a un servidor (esta acción específica también se detalla en el artículo <a href="/es/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Enviar los datos del formulario</a>). El control de selección de archivos se puede usar para elegir uno o más archivos para enviar.</p> + +<p>Para crear un <a href="/en-US/docs/Web/HTML/Element/input/file">control de selección de archivos</a>, utilizas el elemento {{HTMLElement ("input")}} con su atributo {{htmlattrxref ("type","input")}} establecido en <code>file</code>. Es posible restringir los tipos de archivos que se aceptan utilizando el atributo {{htmlattrxref ("accept","input")}}. Además, puedes permitir que el usuario elija más de un archivo añadiendo el atributo {{htmlattrxref ("multiple","input")}}.</p> + +<h4 id="Ejemplo">Ejemplo</h4> + +<p>En este ejemplo, se crea un control de selección de archivos que solicita archivos de imágenes gráficas. El usuario puede seleccionar múltiples archivos en este caso.</p> + +<pre class="brush: html notranslate"><input type="file" name="file" id="file" accept="image/*" multiple></pre> + +<p>En algunos dispositivos móviles, el control de selección de archivos puede acceder a fotos, vídeos y audio capturados directamente por la cámara y el micrófono del dispositivo y añadir información de captura al atributo <code>accept</code> de la manera siguiente:</p> + +<pre class="notranslate"><input type="file" accept="image/*;capture=camera"> +<input type="file" accept="video/*;capture=camcorder"> +<input type="file" accept="audio/*;capture=microphone"></pre> + +<h2 id="Atributos_comunes">Atributos comunes</h2> + +<p>Muchos de los elementos que se utilizan para definir controles de formulario tienen sus atributos específicos propios. Sin embargo, hay un conjunto de atributos que son comunes para todos los elementos de formulario. Ya has conocido algunos, pero a continuación encontrarás una lista de esos atributos comunes para referencias futuras:</p> + +<table> + <thead> + <tr> + <th scope="col">Nombre del atributo</th> + <th scope="col">Valor por defecto</th> + <th scope="col">Descripción</th> + </tr> + </thead> + <tbody> + <tr> + <td><code><a href="/en-US/docs/Web/HTML/Attributes/autofocus">autofocus</a></code></td> + <td>false</td> + <td>Este atributo booleano te permite especificar que el elemento ha de tener el foco de entrada automáticamente cuando se carga la página. En un documento, solo un elemento asociado a un formulario puede tener este atributo especificado.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/Web/HTML/Attributes/disabled">disabled</a></code></td> + <td>false</td> + <td>Este atributo booleano indica que el usuario no puede interactuar con el elemento. Si no se especifica este atributo, el elemento hereda su configuración del elemento que lo contiene, por ejemplo, {{HTMLElement ("fieldset")}}. Si el elemento que lo contiene no tiene el atributo establecido en <code>disabled</code>, el elemento está habilitado.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/Web/HTML/Attributes/form">form</a></code></td> + <td></td> + <td>El elemento <code><form></code> con el que está asociado el control, que se usa cuando no está anidado dentro de ese formulario. El valor del atributo debe ser el atributo <code>id</code> de un elemento {{HTMLElement ("form")}} del mismo documento. Esto te permite asociar un formulario con un control de formulario que esté fuera de aquel, incluso si está dentro de un elemento de formulario diferente.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/Web/HTML/Attributes/name">name</a></code></td> + <td></td> + <td>El nombre del elemento; se envía con los datos del formulario.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/Web/HTML/Attributes/value">value</a></code></td> + <td></td> + <td>El valor inicial del elemento.</td> + </tr> + </tbody> +</table> + +<h2 id="Conclusión">Conclusión</h2> + +<p>Este artículo ha expuesto los tipos de entrada más antiguos: el conjunto original que se introdujo en los primeros días de HTML, que es compatible con todos los navegadores. En el artículo siguiente veremos los valores del atributo <code>type</code> que se han añadido en HTML5 más recientemente.</p> + +<p>{{PreviousMenuNext("Learn/Forms/How_to_structure_an_HTML_form", "Learn/Forms/HTML5_input_types", "Learn/Forms")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Forms/Your_first_HTML_form">Tu primer formulario HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">Cómo estructurar un formulario HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/The_native_form_widgets">Los controles básicos de formulario originales</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/HTML5_input_types">Tipos de entrada HTML5</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Additional_form_controls">Controles de formulario adicionales</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/UI_pseudo-classes">Pseudoclases UI</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Styling_HTML_forms">Aplicar estilo a formularios HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Form_validation">Validación de datos en un formulario</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Enviar los datos de un formulario</a></li> +</ul> + +<h3 id="Temas_avanzados">Temas avanzados</h3> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript">Enviar formularios con JavaScript</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets">Cómo crear widgets de formularios personalizados</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/HTML_forms_in_legacy_browsers">Formularios HTML en navegadores antiguos</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Advanced_styling_for_HTML_forms">Cuestiones avanzadas de aplicación de estilo para formularios HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Property_compatibility_table_for_form_widgets">Tabla de compatibilidad de los controles de formulario</a></li> +</ul> diff --git a/files/es/learn/forms/form_validation/index.html b/files/es/learn/forms/form_validation/index.html new file mode 100644 index 0000000000..e967b68973 --- /dev/null +++ b/files/es/learn/forms/form_validation/index.html @@ -0,0 +1,845 @@ +--- +title: Validación de formularios de datos +slug: Learn/HTML/Forms/Validacion_formulario_datos +tags: + - Ejemplo + - Guía + - HTML + - Intermedio + - JavaScript + - Web + - formulários +translation_of: Learn/Forms/Form_validation +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Forms/UI_pseudo-classes", "Learn/Forms/Sending_and_retrieving_form_data", "Learn/HTML/Forms")}}</div> + +<p>Antes de enviar datos al servidor, es importante asegurarse de que se completan todos los controles de formulario requeridos, y en el formato correcto. Esto se denomina <strong>validación de formulario en el lado del cliente</strong> y ayuda a garantizar que los datos que se envían coinciden con los requisitos establecidos en los diversos controles de formulario. Este artículo te guiará por los conceptos básicos y ejemplos de validación de formularios en el lado del cliente.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, y entender cómo funcionan el <a href="/es/docs/Learn/HTML">HTML</a>, el <a href="/es/docs/Learn/CSS">CSS</a> y el <a href="/es/docs/Learn/JavaScript">JavaScript</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender qué es la validación de formularios en el lado del cliente, porqué es importante y cómo aplicar diversas técnicas para implementarla.</td> + </tr> + </tbody> +</table> + +<p>La validación en el lado del cliente es una verificación inicial y una característica importante para garantizar una buena experiencia de usuario; mediante la detección de datos no válidos en el lado del cliente, el usuario puede corregirlos de inmediato. Si el servidor lo recibe y, a continuación, lo rechaza; se produce un retraso considerable en la comunicación entre el servidor y el cliente que insta al usuario a corregir sus datos.</p> + +<p>Sin embargo, ¡la validación en el lado del cliente <em>no debe considerarse </em> una medida de seguridad exhaustiva! Tus aplicaciones siempre deben realizar comprobaciones de seguridad de los datos enviados por el formulario <em>en el lado del servidor</em>, <strong>así como también</strong> en el lado del cliente, porque la validación en el lado del cliente es demasiado fácil de evitar, por lo que los usuarios malintencionados pueden enviar fácilmente datos incorrectos a tu servidor. Lee <a href="/es/docs/Learn/Server-side/Primeros_pasos/seguridad_sitios_web">Seguridad en los sitios web</a> para ver qué <em>podría</em> suceder. Cómo implementar la validación en el lado del servidor está fuera del alcance de este módulo, pero debes tenerlo en cuenta.</p> + +<h2 id="¿Qué_es_la_validación_de_formularios">¿Qué es la validación de formularios?</h2> + +<p>Ve a cualquier sitio web popular que incluya un formulario de registro y observa que proporcionan comentarios cuando no introduces tus datos en el formato que se espera. Recibirás mensajes como:</p> + +<ul> + <li>«Este campo es obligatorio» (No se puede dejar este campo en blanco).</li> + <li>«Introduzca su número de teléfono en el formato xxx-xxxx» (Se requiere un formato de datos específico para que se considere válido).</li> + <li>«Introduzca una dirección de correo electrónico válida» (los datos que introdujiste no están en el formato correcto).</li> + <li>«Su contraseña debe tener entre 8 y 30 caracteres y contener una letra mayúscula, un símbolo y un número». (Se requiere un formato de datos muy específico para tus datos).</li> +</ul> + +<p>Esto se llama <strong>validación de formulario</strong>. Cuando introduces los datos, el navegador y/o el servidor web verifican que estén en el formato correcto y dentro de las restricciones establecidas por la aplicación. La validación realizada en el navegador se denomina validación <strong>en el lado del cliente</strong>, mientras que la validación realizada en el servidor se denomina validación <strong>en el lado del servidor</strong>. En este capítulo nos centraremos en la validación en el lado del cliente.</p> + +<p>Si la información está en el formato correcto, la aplicación permite que los datos se envíen al servidor y (en general) que se guarden en una base de datos; si la información no está en el formato correcto, da al usuario un mensaje de error que explica lo que debe corregir y le permite volver a intentarlo.</p> + +<p>Queremos que completar formularios web sea lo más fácil posible. Entonces, ¿por qué insistimos en validar nuestros formularios? Hay tres razones principales:</p> + +<ul> + <li><strong>Queremos obtener los datos correctos en el formato correcto.</strong> Nuestras aplicaciones no funcionarán correctamente si los datos de nuestros usuarios se almacenan en el formato incorrecto, son incorrectos o se omiten por completo.</li> + <li><strong>Queremos proteger los datos de nuestros usuarios</strong>. Obligar a nuestros usuarios a introducir contraseñas seguras facilita proteger la información de su cuenta.</li> + <li><strong>Queremos protegernos a nosotros mismo</strong>. Hay muchas formas en que los usuarios maliciosos puedan usar mal los formularios desprotegidos y dañar la aplicación (consulta <a href="/es/docs/Learn/Server-side/Primeros_pasos/seguridad_sitios_web">Seguridad del sitio web</a>).</li> +</ul> + +<div class="warning"><strong>Atención:</strong> No confíes nunca en los datos que se pasan al servidor desde el cliente. Incluso si tu formulario se valida correctamente y evita la introducción de datos con formato incorrecto en el lado del cliente, un usuario malintencionado puede alterar la petición de red.</div> + +<h2 id="Diferentes_tipos_de_validación_en_el_lado_del_cliente">Diferentes tipos de validación en el lado del cliente</h2> + +<p>Hay dos tipos diferentes de validación por parte del cliente que encontrarás en la web:</p> + +<ul> + <li>La <strong>validación de formularios incorporada</strong> utiliza características de validación de formularios HTML5, que hemos visto en muchos lugares a lo largo de este módulo. Esta validación generalmente no requiere mucho JavaScript. La validación de formularios incorporada tiene un mejor rendimiento que JavaScript, pero no es tan personalizable como la validación con JavaScript.</li> + <li>La <strong>validación con JavaScript</strong> se codifica utilizando JavaScript. Esta validación es completamente personalizable, pero debes crearlo todo (o usar una biblioteca).</li> +</ul> + +<h2 id="Usar_la_validación_de_formulario_incorporada">Usar la validación de formulario incorporada</h2> + +<p>Una de las características más importantes de los <a href="/en-US/docs/Learn/Forms/HTML5_input_types">controles de formulario de HTML5</a> es la capacidad de validar la mayoría de los datos de usuario sin depender de JavaScript. Esto se realiza mediante el uso de atributos de validación en los elementos del formulario. Los hemos visto anteriormente en el curso, pero recapitulamos aquí:</p> + +<ul> + <li><code><a href="/en-US/docs/Web/HTML/Attributes/required">required</a></code>: Especifica si un campo de formulario debe completarse antes de que se pueda enviar el formulario.</li> + <li><code><a href="/en-US/docs/Web/HTML/Attributes/minlength">minlength</a></code> y <code><a href="/en-US/docs/Web/HTML/Attributes/maxlength">maxlength</a></code>: Especifican la longitud mínima y máxima de los datos de texto (cadenas).</li> + <li><code><a href="/en-US/docs/Web/HTML/Attributes/min">min</a></code> y <code><a href="/en-US/docs/Web/HTML/Attributes/max">max</a></code>: Especifican los valores mínimo y máximo de los tipos de entrada numéricos.</li> + <li><code>type</code>: Especifica si los datos deben ser un número, una dirección de correo electrónico o algún otro tipo de preajuste específico. </li> + <li><code><a href="/en-US/docs/Web/HTML/Attributes/pattern">pattern</a></code>: Especifica una <a href="/es/docs/Web/JavaScript/Guide/Regular_Expressions">expresión regular</a> que define un patrón que los datos que se introduzcan deben seguir.</li> +</ul> + +<p>Si los datos que se introducen en un campo de formulario siguen todas las reglas que especifican los atributos anteriores, se consideran válidos. Si no, se consideran no válidos.</p> + +<p>Cuando un elemento es válido, se cumplen los aspectos siguientes:</p> + +<ul> + <li>El elemento coincide con la pseudoclase {{cssxref(":valid")}} de CSS, lo que te permite aplicar un estilo específico a los elementos válidos.</li> + <li>Si el usuario intenta enviar los datos, el navegador envía el formulario siempre que no haya nada más que lo impida (por ejemplo, JavaScript).</li> +</ul> + +<p>Cuando un elemento no es válido, se cumplen los aspectos siguientes:</p> + +<ul> + <li>El elemento coincide con la pseudoclase {{cssxref(":invalid")}} de CSS, y a veces con otras pseudoclases de interfaz de usuario (UI) –por ejemplo, {{cssxref(":out-of-range")}}– dependiendo del error, que te permite aplicar un estilo específico a elementos no válidos.</li> + <li>Si el usuario intenta enviar los datos, el navegador bloquea el formulario y muestra un mensaje de error.</li> +</ul> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Hay varios errores que evitan que el formulario se envíe, incluidos {{domxref('validityState.badInput', 'badInput')}}, {{domxref('validityState.patternMismatch','patternMismatch')}}, {{domxref('validityState.rangeOverflow','rangeOverflow')}} o {{domxref('validityState.rangeUnderflow','rangeUnderflow')}}, {{domxref('validityState.stepMismatch','stepMismatch')}}, {{domxref('validityState.tooLong','tooLong')}} o {{domxref('validityState.tooShort','tooShort')}}, {{domxref('validityState.typeMismatch','typeMismatch')}}, {{domxref('validityState.valueMissing','valueMissing')}} o {{domxref('validityState.customError','customError')}}.</p> +</div> + +<h2 id="Ejemplos_de_validación_de_formularios_incorporados">Ejemplos de validación de formularios incorporados</h2> + +<p>En esta sección probaremos algunos de los atributos que hemos comentado antes.</p> + +<h3 id="Archivo_de_inicio_sencillo">Archivo de inicio sencillo</h3> + +<p>Vamos a empezar con un ejemplo sencillo: una entrada que te permite elegir si prefieres un plátano o una cereza. Este ejemplo implica una simple entrada ({{HTMLElement("input")}}) de texto con una etiqueta ({{htmlelement("label")}}) asociada y un botón de envío ({{htmlelement ("button")}}). Puedes encontrar el código fuente en GitHub en <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-start.html">fruit-start.html</a> y el ejemplo en vivo a continuación.</p> + +<pre class="brush: html notranslate"><form> + <label for="choose">¿Prefieres un plátano o una cereza?</label> + <input id="choose" name="i_like"> + <button>Enviar</button> +</form></pre> + +<pre class="brush: css notranslate">input:invalid { + border: 2px dashed red; +} + +input:valid { + border: 2px solid black; +}</pre> + +<p>{{EmbedLiveSample("Archivo_de_inicio_sencillo", "100%", 80)}}</p> + +<p>Para empezar, haz una copia de <code>fruit-start.html</code> en un nuevo directorio de tu disco duro.</p> + +<h3 id="El_atributo_required">El atributo <code>required</code></h3> + +<p>La característica de validación de HTML5 más simple es el atributo <code><a href="/en-US/docs/Web/HTML/Attributes/required">required</a></code>. Añade este atributo al elemento para que una entrada sea obligatoria. Cuando se establece este atributo, el elemento coincide con la pseudoclase de la interfaz de usuario {{cssxref(':required')}} y el formulario no se envía; muestra un mensaje de error al enviarlo si la entrada está vacía. Si está vacía, la entrada también se considera inválida, coincidiendo con la pseudoclase de interfaz de usuario {{cssxref(':invalid')}}.</p> + +<p>Añade un atributo <code>required</code> a tu entrada, como se muestra a continuación.</p> + +<pre class="brush: html notranslate"><form> + <label for="choose">¿Prefieres un plátano o una cereza? (requerido) </label> + <input id="choose" name="i_like" <strong>required</strong>> + <button>Enviar</button> +</form></pre> + +<p>Ten en cuenta el CSS que en el archivo de ejemplo se ha incluido:</p> + +<pre class="brush: css notranslate">input:invalid { + border: 2px dashed red; +} + +input:invalid:required { + background-image: linear-gradient(to right, pink, lightgreen); +} + +input:valid { + border: 2px solid black; +}</pre> + +<p>Este CSS da un borde discontinuo rojo cuando la entrada no es válida, y un borde negro sólido más sutil cuando es válida. También añadimos un gradiente de fondo cuando la entrada es obligatoria <em>y</em> no válida. Prueba el nuevo comportamiento en el ejemplo siguiente:</p> + +<p>{{EmbedLiveSample("El_atributo_required", "100%", 80)}}</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes encontrar este ejemplo en vivo en GitHub como <a href="https://mdn.github.io/learning-area/html/forms/form-validation/fruit-required.html">fruit-validation.html</a> (consulta también el <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-required.html">código fuente</a>).</p> +</div> + +<p>Intenta enviar el formulario sin introducir ningún valor. Observa que la entrada no válida recibe el cursor, aparece un mensaje de error predeterminado («Complete este campo») y el formulario no se puede enviar.</p> + +<p>La presencia del atributo <code>required</code> en cualquier elemento que admite este atributo significa que el elemento coincide con la pseudoclase {{cssxref(':required')}}, tenga o no un valor. Si en el elemento {{HTMLElement("input")}} no se ha introducido ningún valor, <code>input</code> coincidirá con la pseudoclase {{cssxref(':invalid')}}.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Para una buena experiencia de usuario, indica al usuario que campos de formulario se requieren. No solo es una buena experiencia de usuario, sino que lo exigen las pautas de <a href="/es/docs/Learn/Accessibility">accesibilidad</a> de WCAG. Además, solo requiere que los usuarios introduzcan los datos que realmente necesitas: Por ejemplo, ¿por qué realmente necesitas saber el género o el tratamiento de alguien?</p> +</div> + +<h3 id="Validación_de_una_expresión_regular">Validación de una expresión regular</h3> + +<p>Otra característica útil de validación es el atributo <a href="/en-US/docs/Web/HTML/Attributes/pattern"><code>pattern</code></a>, que espera una <a href="/es/docs/Web/JavaScript/Guide/Regular_Expressions">expresión regular</a> como valor. Una expresión regular (<em>regex</em>) es un patrón que se puede usar para establecer combinaciones de caracteres en cadenas de texto, por lo que las expresiones regulares son ideales para la validación de formularios y sirven para una gran variedad de otros usos en JavaScript.</p> + +<p>Las expresiones regulares son bastante complejas y no vamos a exponerlas exhaustivamente en este artículo. A continuación hay algunos ejemplos para que te hagas una idea de cómo funcionan.</p> + +<ul> + <li><code>a</code>: coincide con un carácter que es <code>a</code> (ni <code>b</code>, ni <code>aa</code>, etc.).</li> + <li><code>abc</code>: coincide con <code>a</code>, seguido de <code>b</code>, seguido de <code>c</code>.</li> + <li><code>ab?c</code>: coincide con <code>a</code>, seguida opcionalmente de una sola <code>b</code>, seguida de <code>c</code> (<code>ac</code> o <code>abc</code>).</li> + <li><code>ab*c</code>: coincide con <code>a</code>, seguido opcionalmente de cualquier número de <code>b</code>, seguido de <code>c</code>. (<code>ac</code>, <code>abc</code>, <code>abbbbbc</code>, etc.)</li> + <li><code>a|b</code>: coincide con un carácter que es <code>a</code> o <code>b</code>.</li> + <li><code>abc|xyz</code>: coincide exactamente con <code>abc</code> o <code>xyz</code> (pero no con <code>abcxyz</code> <code>a</code> o <code>y</code>, y así sucesivamente).</li> +</ul> + +<p>Hay muchas más posibilidades que no exponemos aquí. Para obtener una lista completa y muchos ejemplos, consulta nuestro documento de <a href="/es/docs/Web/JavaScript/Guide/Regular_Expressions">expresiones regulares</a>.</p> + +<p>Implementemos un ejemplo. Actualiza tu HTML para añadir un atributo <a href="/en-US/docs/Web/HTML/Attributes/pattern"><code>pattern</code></a> como este:</p> + +<pre class="brush: html notranslate"><form> + <label for="choose">¿Prefieres un plátano o una cereza?</label> + <input id="choose" name="i_like" required pattern="[Pp]látano|[Cc]ereza "> + <button>Enviar</button> +</form> +</pre> + +<div class="hidden"> +<pre class="brush: css notranslate">input:invalid { + border: 2px dashed red; +} + +input:valid { + border: 2px solid black; +}</pre> +</div> + +<p>Esto nos da la siguiente actualización; pruébalo:</p> + +<p>{{EmbedLiveSample("Validación de una expresión regular", "100%", 80)}}</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes encontrar este ejemplo en vivo en GitHub como <a href="https://mdn.github.io/learning-area/html/forms/form-validation/fruit-pattern.html">fruit-pattern.html</a> (consulta también su <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-pattern.html">código fuente</a>).</p> +</div> + +<p>En este ejemplo, el elemento {{HTMLElement("input")}} acepta uno de los cuatro valores posibles: las cadenas «plátano», «Plátano», «cereza» o «Cereza». Las expresiones regulares distinguen entre mayúsculas y minúsculas, pero hemos hecho que admita versiones en mayúsculas y minúsculas utilizando un patrón «Aa» adicional anidado dentro de corchetes.</p> + +<p>En este punto, intenta cambiar el valor dentro del atributo <a href="/en-US/docs/Web/HTML/Attributes/pattern"><code>pattern</code></a> para que se vean iguales que algunos de los ejemplos vistos anteriormente, y observa que esto afecta a los valores que puedes añadir para que el valor de entrada sea válido. Intenta escribir algo por tu cuenta y mira cómo va. ¡Haz que estén relacionadas con la fruta siempre que sea posible para que tus ejemplos tengan sentido!</p> + +<p>Si un valor no vacío de {{HTMLElement("input")}} no coincide con el patrón de la expresión regular, <code>input</code> coincidirá con la pseudoclase {{cssxref(':invalid')}}.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Algunos tipos de elementos {{HTMLElement ("input")}} no necesitan validar una expresión regular con el atributo <a href="/en-US/docs/Web/HTML/Attributes/pattern"><code>pattern</code></a>. Especificar el tipo de correo electrónico (<code>email</code>), por ejemplo, valida el valor de las entradas con un patrón de dirección de correo electrónico bien formado o un patrón que coincida con una lista de direcciones de correo electrónico separadas por comas si tiene el atributo <a href="/en-US/docs/Web/HTML/Attributes/multiple"><code>multiple</code></a>.</p> +</div> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: El elemento {{HTMLElement("textarea")}} no admite el atributo <a href="/en-US/docs/Web/HTML/Attributes/pattern"><code>pattern</code></a>.</p> +</div> + +<h3 id="Restringir_la_longitud_de_tus_entradas">Restringir la longitud de tus entradas</h3> + +<p>Puedes restringir la longitud de los caracteres de todos los campos de texto creados por {{HTMLElement("input")}} o {{HTMLElement("textarea")}} utilizando los atributos <a href="/en-US/docs/Web/HTML/Attributes/minlength"><code>minlength</code></a> y <code><a href="/en-US/docs/Web/HTML/Attributes/maxlength">maxlength</a></code>. Un campo no es válido si tiene un valor y ese valor tiene menos caracteres que el valor de longitud mínima (<a href="/en-US/docs/Web/HTML/Attributes/minlength"><code>minlength</code></a>), o más que el valor de longitud máxima (<code><a href="/en-US/docs/Web/HTML/Attributes/maxlength">maxlength</a></code>).</p> + +<p>Los navegadores a menudo no permiten que el usuario escriba un valor más largo de lo esperado en los campos de texto. Lo que otorga una mejor experiencia de usuario que <code>maxlength</code> es proporcionar comentarios de recuento de caracteres de manera accesible y permitirles editar su contenido a un tamaño más reducido. Un ejemplo de esto es el límite de caracteres de Twitter. JavaScript, incluidas las <a href="https://github.com/mimo84/bootstrap-maxlength">soluciones que utilizan <code>maxlength</code></a>, se puede utilizar para proporcionar esta funcionalidad.</p> + +<h3 id="Restringir_los_valores_de_tus_entradas">Restringir los valores de tus entradas</h3> + +<p>Los atributos <code><a href="/en-US/docs/Web/HTML/Attributes/min">min</a></code> y <code><a href="/en-US/docs/Web/HTML/Attributes/max">max</a></code> se pueden usar para proporcionar a los campos numéricos (es decir, <code><a href="/en-US/docs/Web/HTML/Element/input/number"><input type="number"></a></code>) un rango de valores válidos. El campo no será válido si contiene un valor fuera de este rango.</p> + +<p>Veamos otro ejemplo. Crea una nueva copia del archivo <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-start.html">fruit-start.html</a>.</p> + +<p>Ahora elimina el contenido del elemento <code><body></code> y reemplázalo con lo siguiente:</p> + +<pre class="brush: html notranslate"><form> + <div> + <label for="choose">¿Prefieres un plátano o una cereza?</label> + <input type="text" id="choose" name="i_like" required minlength="6" maxlength="6"> + </div> + <div> + <label for="number">¿Cuántos te gustaría comer?</label> + <input type="number" id="number" name="amount" value="1" min="1" max="10"> + </div> + <div> + <button>Enviar</button> + </div> +</form></pre> + +<ul> + <li>Aquí verás que le hemos dado al campo de <code>text</code> unos valores <code>minlength</code> y <code>maxlength</code> de seis, que es la misma longitud que tienen el plátano y la cereza.</li> + <li>También le hemos dado al campo <code>number</code> un <code>min</code> de uno y un <code>max</code> de diez. Los números introducidos que queden fuera de este rango se mostrarán como no válidos; los usuarios no podrán usar las flechas de incremento/decremento para mover el valor fuera de este rango. Si el usuario introduce un número desde el teclado fuera de este rango, los datos no serán válidos. El número no es obligatorio, por lo que eliminar el valor aún dará como resultado un valor válido.</li> +</ul> + +<div class="hidden"> +<pre class="brush: css notranslate">input:invalid { + border: 2px dashed red; +} + +input:valid { + border: 2px solid black; +} + +div { + margin-bottom: 10px; +}</pre> +</div> + +<p>Aquí está el ejemplo que se ejecuta en vivo:</p> + +<p>{{EmbedLiveSample("Restringir_los_valores_de_tus_entradas", "100%", 100)}}</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes encontrar este ejemplo en vivo en GitHub como <a href="https://mdn.github.io/learning-area/html/forms/form-validation/fruit-length.html">fruit-length.html</a> (consulta también su <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-length.html">código fuente</a>).</p> +</div> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: <code><input type="number"></code> (y otros tipos, como <code>range</code> y <code>date</code>) también pueden tomar un atributo <a href="/en-US/docs/Web/HTML/Attributes/step"><code>step</code></a>, que especifica en qué incremento aumenta o disminuye el valor cuando se utilizan los controles de entrada (como el botones numéricos arriba y abajo). En el ejemplo anterior no hemos incluido un atributo <code>step</code>, por lo que el valor predeterminado es <code>1</code>. Esto significa que los valores de coma flotante, como 3.2, también se mostrarán como no válidos.</p> +</div> + +<h3 id="Ejemplo_completo">Ejemplo completo</h3> + +<p>Aquí hay un ejemplo completo que muestra el uso de las funciones de validación integradas en HTML. En primer lugar, un poco de HTML:</p> + +<pre class="brush: html notranslate"><form> + <p> + <fieldset> + <legend>¿Tienes carné de conducir?<abbr title="Este campo es obligatorio" aria-label="required">*</abbr></legend> + <!-- Solo se puede seleccionar un botón de opción en un grupo con el mismo nombre, + y, por lo tanto, solo un botón de opción en un grupo con el mismo nombre que tiene marcado el atributo «requerido» + basta para hacer de una selección un requisito --> + <input type="radio" required name="driver" id="r1" value="yes"><label for="r1">Sí</label> + <input type="radio" required name="driver" id="r2" value="no"><label for="r2">No</label> + </fieldset> + </p> + <p> + <label for="n1">¿Qué edad tienes?</label> + <!-- El atributo pattern puede actuar como una alternativa para los navegadores que + no implementan el tipo de entrada de número, pero admiten el atributo pattern. + Ten en cuenta que los navegadores que admiten el atributo pattern lo harán + fallar silenciosamente cuando se use con un campo numérico. + Su uso aquí solo actúa como una alternativa --> + <input type="number" min="12" max="120" step="1" id="n1" name="age" + pattern="\d+"> + </p> + <p> + <label for="t1">¿Cuál es tu fruta favorita?<abbr title="Este campo es obligatorio" aria-label="required">*</abbr></label> + <input type="text" id="t1" name="fruit" list="l1" required + pattern="[Bb]anana|[Cc]herry|[Aa]pple|[Ss]trawberry|[Ll]emon|[Oo]range "> + <datalist id="l1"> + <option>Plátano</option> + <option>Cereza</option> + <option>Manzana</option> + <option>Fresa</option> + <option>Limón</option> + <option>Naranja</option> + </datalist> + </p> + <p> + <label for="t2">¿Cuál es tu dirección de correo electrónico? </label> + <input type="email" id="t2" name="email"> + </p> + <p> + <label for="t3">Deja un mensaje</label> + <textarea id="t3" name="msg" maxlength="140" rows="5"></textarea> + </p> + <p> + <button>Enviar</button> + </p> +</form></pre> + +<p>Y ahora, algo de CSS para añadir estilo al HTML:</p> + +<pre class="brush: css notranslate">form { + font: 1em sans-serif; + max-width: 320px; +} + +p > label { + display: block; +} + +input[type="text"], +input[type="email"], +input[type="number"], +textarea, +fieldset { + width : 100%; + border: 1px solid #333; + box-sizing: border-box; +} + +input:invalid { + box-shadow: 0 0 5px 1px red; +} + +input:focus:invalid { + box-shadow: none; +}</pre> + +<p>Esto se traduce de la siguiente manera:</p> + +<p>{{EmbedLiveSample("Ejemplo_completo", "100%", 420)}}</p> + +<p>Consulta <a href="/es/docs/HTML/HTML5/Validacion_de_restricciones#Atributos_relacionados_con_validaciones">Atributos relacionados con la validación</a> para obtener una lista completa de los atributos que se pueden usar para restringir los valores de entrada y los tipos de entrada que los admiten.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes encontrar este ejemplo en vivo en GitHub como <a href="https://mdn.github.io/learning-area/html/forms/form-validation/full-example.html">full-example.html</a> (consulta también su <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/full-example.html">código fuente</a>).</p> +</div> + +<h2 id="Validar_formularios_utilizando_JavaScript">Validar formularios utilizando JavaScript</h2> + +<p>Debes usar JavaScript si quieres controlar la apariencia de los mensajes de error nativos o tratar con navegadores heredados que no admiten la validación de formularios incorporados en HTML. En esta sección veremos las diferentes formas de hacer esto.</p> + +<h3 id="La_API_de_validación_de_restricciones">La API de validación de restricciones</h3> + +<p>La mayoría de los navegadores admiten la <a href="/en-US/docs/Web/API/Constraint_validation">API de validación de restricciones</a>, que consta de un conjunto de métodos y propiedades disponibles en las interfaces DOM de elementos de formulario siguientes:</p> + +<ul> + <li><code><a href="/en-US/docs/Web/API/HTMLButtonElement">HTMLButtonElement</a></code> (representa un elemento <code><a href="/en-US/docs/Web/HTML/Element/button"><button></a></code>)</li> + <li><code><a href="/en-US/docs/Web/API/HTMLFieldSetElement">HTMLFieldSetElement</a></code> (representa un elemento <code><a href="/en-US/docs/Web/HTML/Element/fieldset"><fieldset></a></code>)</li> + <li><code><a href="/en-US/docs/Web/API/HTMLInputElement">HTMLInputElement</a></code> (representa un elemento <code><a href="/en-US/docs/Web/HTML/Element/input"><input></a></code>)</li> + <li><code><a href="/en-US/docs/Web/API/HTMLOutputElement">HTMLOutputElement</a></code> (representa un elemento <code><a href="/en-US/docs/Web/HTML/Element/output"><output></a></code>)</li> + <li><code><a href="/en-US/docs/Web/API/HTMLSelectElement">HTMLSelectElement</a></code> (representa un elemento <code><a href="/en-US/docs/Web/HTML/Element/select"><select></a></code>)</li> + <li><code><a href="/en-US/docs/Web/API/HTMLTextAreaElement">HTMLTextAreaElement</a></code> (representa un elemento <code><a href="/en-US/docs/Web/HTML/Element/textarea"><textarea></a></code>)</li> +</ul> + +<p id="Constraint_validation_API_properties">La API de validación de restricciones hace que las propiedades siguientes estén disponibles en los elementos anteriores.</p> + +<ul> + <li><code>validationMessage</code>: Devuelve un mensaje localizado que describe las restricciones de validación que el control no satisface (si corresponde). Si el control no es candidato para la validación de restricciones (<code>willValidate</code> es <code>false</code>) o el valor del elemento satisface sus restricciones (es válido), esto devolverá una cadena vacía.</li> + <li><code>validity</code>: Devuelve un objeto <code>ValidityState</code> que contiene varias propiedades que describen el estado de validez del elemento. Puedes encontrar todos los detalles de todas las propiedades disponibles en la página de referencia {{domxref("ValidityState")}}; a continuación se enumeran algunos de los más comunes: + <ul> + <li>{{domxref("ValidityState.patternMismatch", "patternMismatch")}}: Devuelve <code>true</code> si el valor no coincide con el {{htmlattrxref("pattern", "input")}} especificado, y <code>false</code> si coincide. Si es verdadero, el elemento coincide con la pseudoclase {{cssxref(":invalid")}} de CSS.</li> + <li>{{domxref("ValidityState.tooLong", "tooLong")}}: Devuelve <code>true</code> si el valor es mayor que la longitud máxima especificada por el atributo {{htmlattrxref("maxlength", "input")}}, o <code>false</code> si es menor o igual al máximo. Si es verdadero, el elemento coincide con la pseudoclase {{cssxref(":invalid")}} de CSS.</li> + <li>{{domxref("ValidityState.tooShort", "tooShort")}}: Devuelve <code>true</code> si el valor es menor que la longitud mínima especificada por el atributo {{htmlattrxref("minlength", "input")}}, o <code>false</code> si es mayor o igual al mínmo. Si es verdadero, el elemento coincide con la pseudoclase {{cssxref(":invalid")}} de CSS.</li> + <li>{{domxref("ValidityState.rangeOverflow", "rangeOverflow")}}: Devuelve <code>true</code> si el valor es mayor que el máximo especificado por el atributo {{htmlattrxref("max", "input")}}, o <code>false</code> si es menor o igual que el máximo. Si es verdadero, el elemento coincide con las pseudoclases {{cssxref(":invalid")}} y {{cssxref(":out-of-range")}} de CSS.</li> + <li>{{domxref("ValidityState.rangeUnderflow", "rangeUnderflow")}}: Devuelve <code>true</code> si el valor es menor que el mínimo especificado por el atributo {{htmlattrxref("min", "input")}}, o <code>false</code> si es mayor o igual que el mínimo. Si es verdadero, el elemento coincide con las pseudoclases {{cssxref(":invalid")}} y {{cssxref(":out-of-range")}} de CSS.</li> + <li>{{domxref("ValidityState.typeMismatch", "typeMismatch")}}: Devuelve <code>true</code> si el valor no está en la sintaxis requerida (cuando {{htmlattrxref("type", "input")}} es <code>email</code> o <code>url</code>), o <code>false</code> si la sintaxis es correcta. Si es verdadero, el elemento coincide con la pseudoclase {{cssxref(":invalid")}} de CSS.</li> + <li><code>valid</code>: Devuelve <code>true</code> si el elemento cumple con todas sus restricciones de validación y por lo tanto se considera válido, o <code>false</code> si falla alguna restricción. Si es verdadero, el elemento coincide con la pseudoclase {{cssxref(":valid")}} de CSS; o con la pseudoclase {{cssxref(":invalid")}} de CSS de lo contrario.</li> + <li><code>valueMissing</code>: Devuelve <code>true</code> si el elemento tiene un atributo {{htmlattrxref("required", "input")}} pero no tiene valor, o <code>false</code> de lo contrario. Si es verdadero, el elemento coincide con la pseudoclase {{cssxref(":invalid")}} de CSS.</li> + </ul> + </li> + <li><code>willValidate</code>: Devuelve <code>true</code> si el elemento se valida cuando se envía el formulario; <code>false</code> de lo contrario.</li> +</ul> + +<p id="Constraint_validation_API_methods">La API de validación de restricciones también pone a disposición los siguientes métodos en los elementos anteriores.</p> + +<ul> + <li><code>checkValidity()</code>: Devuelve <code>true</code> si el valor del elemento no tiene problemas de validez; <code>false</code> en caso contrario. Si el elemento no es válido, este método también activa un <a href="/es/docs/Web/API/HTMLInputElement/invalid_event">evento <code>invalid</code></a> en el elemento.</li> + <li><code>setCustomValidity(<em>message</em>)</code>: Añade un mensaje de error personalizado al elemento; si configuras un mensaje de error personalizado, el elemento se considera no válido y se muestra el error especificado. Esto te permite utilizar el código JavaScript para establecer un fallo de validación distinto de los ofrecidos por las restricciones estándar de validación de HTML5. El mensaje se muestra al usuario cuando se informa del problema.</li> +</ul> + +<h4 id="Implementar_un_mensaje_de_error_personalizado">Implementar un mensaje de error personalizado</h4> + +<p>Como has visto en los ejemplos de restricciones de validación de HTML5 anteriores, cada vez que un usuario intenta enviar un formulario no válido, el navegador muestra un mensaje de error. La forma en que se muestra este mensaje depende del navegador.</p> + +<p>Estos mensajes automatizados tienen dos inconvenientes:</p> + +<ul> + <li>No hay una forma estándar de cambiar su aspecto con CSS.</li> + <li>Dependen de la configuración regional del navegador, lo que significa que puedes tener una página en un idioma pero un mensaje de error en otro idioma, como se ve en la siguiente captura de pantalla de Firefox.</li> +</ul> + +<p><img alt="Ejemplo de un mensaje de error en francés en una página de Firefox en inglés" src="/files/4329/error-firefox-win7.png" style="height: 97px; width: 228px;"></p> + +<p>La personalización de estos mensajes de error es uno de los casos de uso más comunes de la <a href="/en-US/docs/Web/API/Constraint_validation" rel="external">API de validación de restricciones</a>. Veamos un ejemplo simple de cómo hacer esto.</p> + +<p>Comenzaremos con un HTML simple (siéntete libre de poner esto en un archivo HTML en blanco; usa una copia nueva de <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-start.html">fruit-start.html</a> como base, si lo deseas):</p> + +<pre class="brush: html notranslate"><form> + <label for="mail">Me gustaría que me proporcionara una dirección de correo electrónico:<label> + <input type="email" id="mail" name="mail"> + <button>Enviar</button> +</form></pre> + +<p>Y añade a la página el JavaScript siguiente:</p> + +<pre class="brush: js notranslate">const email = document.getElementById("mail"); + +email.addEventListener("input", function (event) { + if (email.validity.typeMismatch) { + email.setCustomValidity("¡Se esperaba una dirección de correo electrónico!"); + } else { + email.setCustomValidity(""); + } +});</pre> + +<p>Aquí guardamos una referencia para la entrada de la dirección de correo electrónico, luego le añadimos un detector de eventos que ejecuta el código de <code>content</code> cada vez que el valor de la entrada cambia.</p> + +<p>Dentro del código que contiene, verificamos si la propiedad <code>validity.typeMismatch</code> de la entrada de la dirección de correo electrónico devuelve <code>true</code>, lo que significa que el valor que contiene no coincide con el patrón para una dirección de correo electrónico bien formada. Si es así, llamamos al método <a href="/es/docs/HTML/HTML5/Validacion_de_restricciones"><code>setCustomValidity()</code></a> con un mensaje personalizado. Esto hace que la entrada no sea válida, de modo que cuando intentas enviar el formulario, el envío falla y se muestra el mensaje de error personalizado.</p> + +<p>Si la propiedad <code>validity.typeMismatch</code> devuelve <code>false</code>, llamamos al método <code>setCustomValidity()</code> con una cadena vacía. Esto hace que la entrada sea válida, y el formulario se envía.</p> + +<p>Puedes probarlo a continuación:</p> + +<p>{{EmbedGHLiveSample("/en-US/learning-area/html/forms/form-validation/custom-error-message.html", '100%', 80)}}</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puede encontrar este ejemplo vivo en GitHub como <a href="https://mdn.github.io/learning-area/html/forms/form-validation/custom-error-message.html">custom-error-message.html</a> (véase también su <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/custom-error-message.html">código fuente</a>).</p> +</div> + +<h4 id="Un_ejemplo_más_detallado">Un ejemplo más detallado</h4> + +<p>Ahora que hemos visto un ejemplo realmente sencillo, veamos cómo podemos usar esta API para construir una validación personalizada un poco más compleja.</p> + +<p>En primer lugar, el código HTML. Una vez más, siéntete libre de construir esto junto con nosotros:</p> + +<pre class="brush: html notranslate"><form novalidate> + <p> + <label for="mail"> + <span>Por favor, introduzca una dirección de correo electrónico: </span> + <input type="email" id="mail" name="mail" required minlength="8"> + <span class="error" aria-live="polite"></span> + </label> + </p> + <button>Enviar</button> +</form></pre> + +<p>Este sencillo formulario usa el atributo <code><a href="/en-US/docs/Web/HTML/Attributes/novalidate">novalidate</a></code> para desactivar la validación automática del navegador; esto permite que nuestra secuencia de comandos tome control sobre la validación. Sin embargo, esto no deshabilita la compatibilidad para la API de validación de restricciones ni la aplicación de pseudoclases de CSS como {{cssxref(":valid")}}, etc. Eso significa que, aunque el navegador no verifica automáticamente la validez del formulario antes de enviar los datos, puedes hacerlo tú mismo y diseñar el formulario en consecuencia.</p> + +<p>Nuestra entrada para validar es <code><a href="/es/docs/Web/HTML/Elemento/input/email"><input type="email"></a></code>, que es obligatoria y tiene una longitud mínima (<code>minlength</code>) de 8 caracteres. Vamos a verificar esto con nuestro propio código para que muestre un mensaje de error personalizado para cada elemento.</p> + +<p>Nuestro objetivo es mostrar los mensajes de error dentro de un elemento <code><span></code>. El atributo <a href="/en-US/docs/Accessibility/ARIA/ARIA_Live_Regions"><code>aria-live</code></a> se establece en ese <code><span></code> para asegurar que todo el mundo podrá ver nuestro mensaje de error personalizado, incluidos los usuarios de lectores de pantalla.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Un punto clave a tener en cuenta es que establecer el atributo <code>novalidate</code> en el formulario impide que el formulario muestre sus propios cuadros de diálogo de error, y nos permite mostrar los mensajes de error personalizados en el DOM de la manera que nosotros elijamos.</p> +</div> + +<p>Ahora aplicaremos algo de CSS básico para mejorar ligeramente el aspecto del formulario y proporcionar algunos comentarios visuales cuando los datos de entrada no sean válidos:</p> + +<pre class="brush: css notranslate">body { + font: 1em sans-serif; + width: 200px; + padding: 0; + margin : 0 auto; +} + +p * { + display: block; +} + +input[type=email]{ + -webkit-appearance: none; + appearance: none; + + width: 100%; + border: 1px solid #333; + margin: 0; + + font-family: inherit; + font-size: 90%; + + box-sizing: border-box; +} + +/* Este es nuestro diseño para los campos no válidos */ +input:invalid{ + border-color: #900; + background-color: #FDD; +} + +input:focus:invalid { + outline: none; +} + +/* Este es el diseño para nuestros mensajes de error */ +.error { + width : 100%; + padding: 0; + + font-size: 80%; + color: white; + background-color: #900; + border-radius: 0 0 5px 5px; + + box-sizing: border-box; +} + +.error.active { + padding: 0.3em; +}</pre> + +<p>Vamos a ver el JavaScript que implementa la validación de error personalizada.</p> + +<pre class="brush: js notranslate">// Hay muchas formas de elegir un nodo DOM; aquí obtenemos el formulario y, a continuación, el campo de entrada +// del correo electrónico, así como el elemento span en el que colocaremos el mensaje de error. +const form = document.getElementsByTagName('form')[0]; + +const email = document.getElementById('mail'); +const emailError = document.querySelector('#mail + span.error'); + +email.addEventListener('input', function (event) { + // Cada vez que el usuario escribe algo, verificamos si + // los campos del formulario son válidos. + + if (email.validity.valid) { + // En caso de que haya un mensaje de error visible, si el campo + // es válido, eliminamos el mensaje de error. + emailError.innerHTML = ''; // Restablece el contenido del mensaje + emailError.className = 'error'; // Restablece el estado visual del mensaje + } else { + // Si todavía hay un error, muestra el error exacto + showError(); + } +}); + +form.addEventListener('submit', function (event) { + // si el campo de correo electrónico es válido, dejamos que el formulario se envíe + + if(!email.validity.valid) { + // Si no es así, mostramos un mensaje de error apropiado + showError(); + // Luego evitamos que se envíe el formulario cancelando el evento + event.preventDefault(); + } +}); + +function showError() { + if(email.validity.valueMissing) { + // Si el campo está vacío + // muestra el mensaje de error siguiente. + emailError.textContent = 'Debe introducir una dirección de correo electrónico.'; + } else if(email.validity.typeMismatch) { + // Si el campo no contiene una dirección de correo electrónico + // muestra el mensaje de error siguiente. + emailError.textContent = 'El valor introducido debe ser una dirección de correo electrónico.'; + } else if(email.validity.tooShort) { + // Si los datos son demasiado cortos + // muestra el mensaje de error siguiente. + emailError.textContent = 'El correo electrónico debe tener al menos ${ email.minLength } caracteres; ha introducido ${ email.value.length }.'; + } + + // Establece el estilo apropiado + emailError.className = 'error activo'; +}</pre> + +<p>Los comentarios explican las cosas bastante bien, pero de una manera muy breve:</p> + +<ul> + <li>Cada vez que cambiamos el valor de la entrada, verificamos si contiene datos válidos. Si es así, eliminamos cualquier mensaje de error que se muestre. Si los datos no son válidos, ejecutamos <code>showError()</code> para mostrar el error correspondiente.</li> + <li>Cada vez que intentamos enviar el formulario, verificamos nuevamente si los datos son válidos. Si es así, dejamos que envíe el formulario. Si no, ejecutamos <code>showError()</code> para mostrar el error correspondiente y detenemos el envío del formulario con <code><a href="/en-US/docs/Web/API/Event/preventDefault">preventDefault()</a></code>.</li> + <li>La función <code>showError()</code> usa varias propiedades de la entrada <code>validity</code> para determinar cuál es el error y luego muestra un mensaje de error según corresponda.</li> +</ul> + +<p>Este es el resultado:</p> + +<p>{{EmbedGHLiveSample("/en-US/learning-area/html/forms/form-validation/detailed-custom-validation.html", '100%', 150)}}</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes encontrar este ejemplo en vivo en GitHub como <a href="https://mdn.github.io/learning-area/html/forms/form-validation/detailed-custom-validation.html">detailed-custom-validation.html</a> (consulta también su <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/detailed-custom-validation.html">código fuente</a>).</p> +</div> + +<p>La API de validación de restricciones te proporciona una herramienta poderosa para manejar la validación de formularios, y te permite tener un control enorme sobre la interfaz de usuario más allá de lo que puedas hacer solo con HTML y CSS.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Para obtener más información, consulta nuestra <a href="/es/docs/HTML/HTML5/Validacion_de_restricciones">guía de validación de restricciones</a> y la referencia de <a href="/en-US/docs/Web/API/Constraint_validation">API de validación de restricciones</a>.</p> +</div> + +<h3 id="Validar_formularios_sin_una_API_incorporada">Validar formularios sin una API incorporada</h3> + +<p>En algunos casos, como la compatibilidad heredada del navegador o los <a href="/es/docs/Learn/HTML/Forms/como_crear_widgets_de_formularios_personalizados">controles personalizados</a>, no podrás o no querrás usar la API de validación de restricciones. Todavía puedes usar JavaScript para validar tu formulario, pero vas a tener que escribirlo.</p> + +<p>Antes de validar el formulario, hazte estas preguntas:</p> + +<dl> + <dt>¿Qué tipo de validación debería realizar?</dt> + <dd>Debes determinar cómo validar los datos: operaciones de cadena, conversión de tipos, expresiones regulares, etc. Tú decides.</dd> + <dt>¿Qué debo hacer si el formulario no se valida?</dt> + <dd>Esto es claramente un problema de la interfaz de usuario. Tienes que decidir cómo se comportará el formulario. ¿El formulario va a enviar los datos de todos modos? ¿Deberías resaltar los campos que dan error? ¿Deberías mostrar mensajes de error?</dd> + <dt>¿Cómo puedo ayudar al usuario a corregir datos no válidos?</dt> + <dd>Para reducir la frustración del usuario, es muy importante proporcionar tanta información útil como sea posible para guiarlo a fin de que corrija sus entradas de datos. Debes ofrecer sugerencias por adelantado para que sepan lo que se espera de ellos, así como mensajes de error claros. Si deseas profundizar en los requisitos de interfaz de usuario para la validación de formularios, aquí hay algunos artículos útiles que debes leer: + <ul> + <li>SmashingMagazine: <a href="http://uxdesign.smashingmagazine.com/2012/06/27/form-field-validation-errors-only-approach/" rel="external">Form-Field Validation: The Errors-Only Approach</a> [Validación de campo de formulario: El enfoque de solo errores]</li> + <li>SmashingMagazine: <a href="http://www.smashingmagazine.com/2009/07/07/web-form-validation-best-practices-and-tutorials/" rel="external">Web Form Validation: Best Practices and Tutorials </a> [Validación de formularios web: Buenas prácticas y tutoriales]</li> + <li>Six Revision: <a href="http://sixrevisions.com/user-interface/best-practices-for-hints-and-validation-in-web-forms/" rel="external">Best Practices for Hints and Validation in Web Forms</a> [Buenas prácticas para sugerencias y validación de formularios web]</li> + <li>A List Apart: <a href="http://www.alistapart.com/articles/inline-validation-in-web-forms/" rel="external">Inline Validation in Web Forms</a> [Validación en línea de formularios web]</li> + </ul> + </dd> +</dl> + +<h4 id="Un_ejemplo_que_no_usa_la_API_de_validación_de_restricciones">Un ejemplo que no usa la API de validación de restricciones</h4> + +<p>Para ilustrar esto, mostramos una versión simplificada del ejemplo anterior que funciona con navegadores con compatibilidad heredada.</p> + +<p>El HTML es casi el mismo; solo hemos eliminado las funciones de validación de HTML.</p> + +<pre class="brush: html notranslate"><form> + <p> + <label for="mail"> + <span>Por favor, introduzca una dirección de correo electrónico: </span> + <input type="text" class="mail" id="mail" name="mail"> + <span class="error" aria-live="polite"></span> + </label> + </p> + <!-- Algunos navegadores con compatibilidad heredada deben tener el atributo «type» + establecido explícitamente en el elemento «button» de «submit»--> + <button type="submit">Enviar</button> +</form></pre> + +<p>Del mismo modo, no es necesario cambiar mucho el CSS; acabamos de convertir la pseudoclase {{cssxref(":invalid")}} de CSS en una clase real y evitamos usar el selector de atributos que no funciona en Internet Explorer 6.</p> + +<pre class="brush: css notranslate">body { + font: 1em sans-serif; + width: 200px; + padding: 0; + margin : 0 auto; +} + +form { + max-width: 200px; +} + +p * { + display: block; +} + +input.mail { + -webkit-appearance: none; + + width: 100%; + border: 1px solid #333; + margin: 0; + + font-family: inherit; + font-size: 90%; + + box-sizing: border-box; +} + +/* Este es nuestro diseño para los campos no válidos */ +input.invalid{ + border-color: #900; + background-color: #FDD; +} + +input:focus.invalid { + outline: none; +} + +/* Este es el diseño para nuestros mensajes de error */ +.error { + width : 100%; + padding: 0; + + font-size: 80%; + color: white; + background-color: #900; + border-radius: 0 0 5px 5px; + box-sizing: border-box; +} + +.error.active { + padding: 0.3em; +}</pre> + +<p>Los grandes cambios están en el código JavaScript, que necesita hacer mucho más trabajo pesado.</p> + +<pre class="brush: js notranslate">// Hay menos formas de elegir un nodo DOM con navegadores antiguos +const form = document.getElementsByTagName('form')[0]; +const email = document.getElementById('mail'); + +// Lo siguiente es un truco para llegar al siguiente nodo de elementos hermanos en el DOM +// Esto es peligroso porque puedes construir fácilmente un bucle infinito. +// En los navegadores modernos es mejor usar element.nextElementSibling +let error = email; +while ((error = error.nextSibling).nodeType != 1); + +// según la especificación HTML5 +const emailRegExp = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/; + +// Muchos navegadores antiguos no son compatibles con el método addEventListener. +// Aquí hay una manera simple de manejar esto; está lejos de ser la única. +function addEvent(element, event, callback) { + let previousEventCallBack = element["on"+event]; + element["on"+event] = function (e) { + const output = callback(e); + + // Una devolución de llamada que devuelve «false» detiene la cadena de devolución de llamada + // e interrumpe la ejecución de la devolución de llamada del evento. + if (output === false) return false; + + if (typeof previousEventCallBack === 'function') { + output = previousEventCallBack(e); + if(output === false) return false; + } + } +}; + +// Ahora podemos reconstruir nuestra restricción de validación +// Debido a que no confiamos en la pseudoclase de CSS, tenemos que +// establecer explícitamente la clase valid/invalid en nuestro campo de correo electrónico +addEvent(window, "load", function () { + // Aquí probamos si el campo está vacío (recuerda, el campo no es obligatorio) + // Si no es así, verificamos si su contenido es una dirección de correo electrónico con el formato correcto. + const test = email.value.length === 0 || emailRegExp.test(email.value); + + email.className = test ? "valid" : "invalid"; +}); + +// Esto define lo que sucede cuando el usuario escribe en el campo +addEvent(email, "input", function () { + const test = email.value.length === 0 || emailRegExp.test(email.value); + if (test) { + email.className = "valid"; + error.innerHTML = ""; + error.className = "error"; + } else { + email.className = "invalid"; + } +}); + +// Esto define lo que sucede cuando el usuario intenta enviar los datos. +addEvent(form, "submit", function () { + const test = email.value.length === 0 || emailRegExp.test(email.value); + + if (!test) { + email.className = "invalid"; + error.innerHTML = "I expect an e-mail, darling!"; + error.className = "error active"; + + // Algunos navegadores antiguos no son compatibles con el método event.preventDefault () + return false; + } else { + email.className = "valid"; + error.innerHTML = ""; + error.className = "error"; + } +});</pre> + +<p>El resultado es el siguiente:</p> + +<p>{{EmbedLiveSample("Validar_formularios_sin_una_API_incorporada", "100%", 130)}}</p> + +<p>Como puedes ver, no es tan difícil construir un sistema de validación por tu cuenta. La parte difícil es hacer que sea lo suficientemente genérico para que se pueda usar en diferentes plataformas y en cualquier forma. Hay muchas bibliotecas de archivos disponibles para realizar la validación de formularios, como por ejemplo <a href="http://rickharrison.github.com/validate.js/" rel="external">Validate.js</a></p> + +<p>.</p> + +<h2 id="Prueba_tus_habilidades!">Prueba tus habilidades!</h2> + +<p>Has llegado al final de este artículo pero ¿puedes recordar la información más importante?Puedes encontrar pruebas adicionales para comprovar que has comprendido la información antes de que continue — visita <a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/Forms/Test_your_skills:_Form_validation">Prueba tus habilidades: Validación de formularios</a>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>La validación de formularios en el lado del cliente a veces requiere JavaScript si deseas personalizar el estilo y los mensajes de error, pero <em>siempre</em> requiere que pienses cuidadosamente en el usuario. Recuerda que siempre debes ayudar a tus usuarios a corregir los datos que proporcionan. Para ese fin, asegúrate de:</p> + +<ul> + <li>Mostrar mensajes de error explícitos.</li> + <li>Ser permisivo con el formato de entrada.</li> + <li>Señalar exactamente dónde se produce el error, especialmente en formularios extensos.</li> +</ul> + +<p>Una vez que hayas verificado que el formulario se ha completado correctamente, puedes proceder a enviarlo. Vamos a exponer el <a href="/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data">envío de los datos del formulario</a> en el próximo artículo.</p> + +<p>{{PreviousMenuNext("Learn/Forms/UI_pseudo-classes", "Learn/Forms/Sending_and_retrieving_form_data", "Learn/HTML/Forms")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Forms/Your_first_form">Tu primer formulario</a></li> + <li><a href="/en-US/docs/Learn/Forms/How_to_structure_a_web_form">Cómo estructurar un formulario web</a></li> + <li><a href="/en-US/docs/Learn/Forms/Basic_native_form_controls">Los controles de formulario básicos originales</a></li> + <li><a href="/en-US/docs/Learn/Forms/HTML5_input_types">Los tipos de entrada en HTML5</a></li> + <li><a href="/en-US/docs/Learn/Forms/Other_form_controls">Otros controles de formulario</a></li> + <li><a href="/en-US/docs/Learn/Forms/Styling_web_forms">Aplicar estilo a formularios web</a></li> + <li><a href="/en-US/docs/Learn/Forms/Advanced_form_styling">Aplicación de estilo a formularios avanzada</a></li> + <li><a href="/en-US/docs/Learn/Forms/UI_pseudo-classes">Pseudoclases UI</a></li> + <li><a href="/en-US/docs/Learn/Forms/Form_validation">Validación de formularios en el lado del cliente</a></li> + <li><a href="/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data">Enviar los datos de un formulario</a></li> +</ul> + +<h3 id="Temas_avanzados">Temas avanzados</h3> + +<ul> + <li><a href="/en-US/docs/Learn/Forms/How_to_build_custom_form_controls">Cómo construir controles de formulario personalizados</a></li> + <li><a href="/en-US/docs/Learn/Forms/Sending_forms_through_JavaScript">Enviar formularios por JavaScript</a></li> + <li><a href="/en-US/docs/Learn/Forms/Property_compatibility_table_for_form_widgets">Tabla de compatibilidad de propiedades para controles de formulario</a></li> +</ul> diff --git a/files/es/learn/forms/how_to_build_custom_form_controls/index.html b/files/es/learn/forms/how_to_build_custom_form_controls/index.html new file mode 100644 index 0000000000..73ae6e6590 --- /dev/null +++ b/files/es/learn/forms/how_to_build_custom_form_controls/index.html @@ -0,0 +1,786 @@ +--- +title: Cómo crear widgets de formularios personalizados +slug: Learn/HTML/Forms/como_crear_widgets_de_formularios_personalizados +translation_of: Learn/Forms/How_to_build_custom_form_controls +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Learn/HTML/Forms/Form_validation", "Learn/HTML/Forms/Sending_forms_through_JavaScript", "Learn/HTML/Forms")}}</div> + +<p class="summary">Hay muchos casos donde los <a href="/en-US/docs/HTML/Forms/The_native_form_widgets" title="/en-US/docs/HTML/Forms/The_native_form_widgets">widgets de formularios HTML disponibles</a> simplemente no son suficientes. si desea <a href="/en-US/docs/Advanced_styling_for_HTML_forms" title="/en-US/docs/Advanced_styling_for_HTML_forms">establecer un estilo avanzado</a> en algunos widgets como el elemento {{HTMLElement("select")}} o si desea proporcionar comportamientos personalizados, no tiene más opción que crear sus propios widgets.</p> + +<p>En este aartículo, veremos cómo construir dicho widget. Para ello, trabajaremos con un ejemplo: Reconstruir el elemento {{HTMLElement("select")}}.</p> + +<div class="note"> +<p><strong>Nota:</strong> Nos enfocaremos en construir los widgets, no en cómo hacer que el código sea genérico y reutilizable; eso implicaría algún código JavaScript no trivial y manipulación del DOM en un contexto desconocido, y eso está fuera del alcance de este artículo.</p> +</div> + +<h2 id="Diseño_estructura_y_semántica">Diseño, estructura, y semántica</h2> + +<p>Antes de crear un widget personalizado, debería iniciar por averiguar exactamente qué es lo que desea. Esto le ahorarrá tiempo considerable. En particular, es importante definir claramente todos los estados de su widget. Para hacer esto, es bueno comenzar con un widget existente, cuyos estados y comportamientos son bien conocidos, por lo que simplemente puede imitarlos tanto como sea posible.</p> + +<p>En nuestro ejemplo, reconstruiremos el elemento {{HTMLElement("select")}}. Este es el resultado que queremos lograr:</p> + +<p><img alt="The three states of a select box" src="/files/4481/custom-select.png" style="height: 135px; width: 366px;"></p> + +<p>Esta captura de pantall muestra los tres estados principales de nuestro widget: el estado normal (a la izquiera); el estado activo (en el centro) y el estado abierto (a la derecha).</p> + +<p>En términos de comportamiento, queremos que nuestro widget sea utilizable tanto con un ratón como con un teclado, al igual que cualquier widget nativo. Comencemos por definir cómo el widget llega a cada estado:</p> + +<dl> + <dt>El widget está en su estado normal cuando:</dt> + <dd> + <ul> + <li>La página carga</li> + <li>El widget estaba activo y el usuario hace clic en cualquier lugar fuera del widget</li> + <li>El widget estaba activo y el usuario mueve el foco a otro widget usando el teclado</li> + </ul> + + <div class="note"> + <p><strong>Nota:</strong> Mover el foco al rededor de la página generalmente se hace presionando la tecla de tabulación, pero este no es el estándar en todas partes. Por ejemplo, el ciclo a través de enlaces en una página se realiza en Safari de forma predeterminada usando la combinación <a href="http://www.456bereastreet.com/archive/200906/enabling_keyboard_navigation_in_mac_os_x_web_browsers/" title="http://www.456bereastreet.com/archive/200906/enabling_keyboard_navigation_in_mac_os_x_web_browsers/">combinación Opction+Tab</a>.</p> + </div> + </dd> + <dt>El widget está en su estado activo cuando:</dt> + <dd> + <ul> + <li>El usuario hace clic en él</li> + <li>El usuario presiona la tecla tab y obtiene foco</li> + <li>El widget estaba en su estado abierto y el usuario hace clic en el widget.</li> + </ul> + </dd> + <dt>El widget está en su estado abierto cuando:</dt> + <dd> + <ul> + <li>El widget está en cualquier otro estado diferente a abierto y el usuario hace clic en él.</li> + </ul> + </dd> +</dl> + +<p>Una vez que sabemos cómo cambiar los estados, es importante definir cómo cambiar el valor del widget:</p> + +<dl> + <dt>El valor cambia cuando:</dt> + <dd> + <ul> + <li>El usuario hace clic en una opción cuando el widget está en estado abierto</li> + <li>El usuario pulsa las teclas de flecha hacia arriba o hacia abajocuando el widget está en estado activo</li> + </ul> + </dd> +</dl> + +<p>Finalmente, definamos cómo se comportarán las opciones del widget:</p> + +<ul> + <li>Cuando se abre el widget, se resalta la opción seleccionada</li> + <li>Cuando el ratón está sobre una opción, la opción se resalta y la opción resaltada anteriormente vuelve a su estado normal</li> +</ul> + +<p>Para los fines de nuestro ejemplo, nos detendremos con eso; sin embargo, si eres un lector cuidadoso, notarás que faltan algunos comportamientos. Por ejemplo, ¿qué crees que sucederá si el usuario pulsa la tecla de tabulación mientras el widget está en estado abierto? La respuesta es ... nada. OK, el comportamiento correcto parece obvio, pero el hecho es que, como no está definido en nuestras especificaciones, es muy fácil pasar por alto este comportamiento. Esto es especialmente cierto en un entorno de equipo cuando las personas que diseñan el comportamiento del widget son diferentes de las que lo implementan.</p> + +<p>Otro ejemplo divertido: ¿qué pasará si el usuario pulsa las teclas de flecha hacia arriba o hacia abajo mientras el widget está en estado abierto? Este es un poco más complicado. Si considera que el estado activo y el estado abierto son completamente diferentes, la respuesta es nuevamente "no pasará nada" porque no definimos ninguna interacción de teclado para el estado abierto. Por otro lado, si considera que el estado activo y el estado abierto se superponen un poco, el valor puede cambiar pero la opción definitivamente no se resaltará en consecuencia, una vez más porque no definimos ninguna interacción del teclado sobre las opciones cuando el widget es en su estado abierto (solo hemos definido lo que debería suceder cuando se abre el widget, pero nada después de eso).</p> + +<p>En nuestro ejemplo, las especificaciones faltantes son obvias, así que las manejaremos, pero puede ser un problema real en widgets nuevos y exóticos, para los cuales nadie tiene la menor idea de cuál es el comportamiento correcto. Por lo tanto, siempre es bueno pasar tiempo en esta etapa de diseño, porque si defines un comportamiento deficiente u olvidas definir uno, será muy difícil redefinirlo una vez que los usuarios se hayan acostumbrado. Si tiene dudas, solicite las opiniones de los demás y, si tiene el presupuesto para ello, no dude en realizar las pruebas de usuario. Este proceso se llama Diseño UX. Si desea obtener más información sobre este tema, debe consultar los siguientes recursos útiles:</p> + +<ul> + <li><a href="http://www.uxmatters.com/" rel="external" title="http://www.uxmatters.com/">UXMatters.com</a></li> + <li><a href="http://uxdesign.com/" rel="external" title="http://uxdesign.com/">UXDesign.com</a></li> + <li><a href="http://uxdesign.smashingmagazine.com/" rel="external" title="http://uxdesign.smashingmagazine.com/">The UX Design section of SmashingMagazine</a></li> +</ul> + +<div class="note"> +<p><strong>Nota: </strong>Ademas, en la mayoría de los sistemas hay una forma de abrir el elemento {{HTMLElement("select")}} para ver todas las opciones disponibles (esto es lo mismo que hacer clic en el elemento {{HTMLElement("select")}} con un ratón). Esto se logra con Alt+Flecha abajo en Windows y no fué implementado en nuestro ejemplo —pero sería facil hacerlo, ya que el mecanismo ya se implementó para el evento <code>clic</code>.</p> +</div> + +<h3 id="Definiendo_la_estructura_y_semántica_HTML">Definiendo la estructura y semántica HTML</h3> + +<p>Ahora que se ha decidido la funcionalidad básica del widget, es hora de comenzar a construir nuestro widget. El primer paso es definir su estructura HTML y darle una semántica básica. Esto es lo que necesitamos para reconstruir un elemento {{HTMLElement("select")}}:</p> + +<pre class="brush: html"><!-- Este es nuestro contenedor principal para nuestro widget. + El atributo tabindex es lo que permite al usuario enforcar el widget. + Veremos más adelante que es mejor configurarlo a través de JavaScript. --> +<div class="select" tabindex="0"> + + <!-- Este contenedor será usado para mostrar el valor actual del widget --> + <span class="value">Cherry</span> + + <!-- Este contenedor contedrá todas las opciones disponibles para nuestro widget. + Como es una lista, tiene sentido usar el elemento ul. --> + <ul class="optList"> + <!-- Cada opción solo contiene el valor que se mostrará, veremos más tarde + cómo manejar el valor real que será enviado con el formulario de datos --> + <li class="option">Cherry</li> + <li class="option">Lemon</li> + <li class="option">Banana</li> + <li class="option">Strawberry</li> + <li class="option">Apple</li> + </ul> + +</div></pre> + +<p>Tenga en cuanta el uso de nombres de clases; estos identifican cada parte relevante independientemente de los elementos HTML subyacentes reales utilizados. Esto es importante para garantizar que no vinculamos nuestro CSS y JavaScript a una estructura HTML sólida, de modo que podamos realizar cambios despues en la implementación sin romper el código que usa el widget. Pro ejemplo, si desea implementar el equivalente del elemento {{HTMLElement("optgroup")}}.</p> + +<h3 id="Creating_the_look_and_feel_using_CSS">Creating the look and feel using CSS</h3> + +<p>Now that we have a structure, we can start designing our widget. The whole point of building this custom widget is to be able to style this widget exactly as we want. To that end, we will split our CSS work into two parts: the first part will be the CSS rules absolutely necessary to have our widget behave like a {{HTMLElement("select")}} element, and the second part will consist of the fancy styles used to make it look the way we want.</p> + +<h4 id="Required_styles">Required styles</h4> + +<p>The required styles are those necessary to handle the three states of our widget.</p> + +<pre class="brush: css">.select { + /* This will create a positioning context for the list of options */ + position: relative; + + /* This will make our widget become part of the text flow and sizable at the same time */ + display : inline-block; +}</pre> + +<p>We need an extra class <code>active</code> to define the look and feel of our widget when it is in its active state. Because our widget is focusable, we double this custom style with the {{cssxref(":focus")}} pseudo-class in order to be sure they will behave the same.</p> + +<pre class="brush: css">.select.active, +.select:focus { + outline: none; + + /* This box-shadow property is not exactly required, however it's so important to be sure + the active state is visible that we use it as a default value, feel free to override it. */ + box-shadow: 0 0 3px 1px #227755; +}</pre> + +<p>Now, let's handle the list of options:</p> + +<pre class="brush: css">/* The .select selector here is syntactic sugar to be sure the classes we define are + the ones inside our widget. */ +.select .optList { + /* This will make sure our list of options will be displayed below the value + and out of the HTML flow */ + position : absolute; + top : 100%; + left : 0; +}</pre> + +<p>We need an extra class to handle when the list of options is hidden. This is necessary in order to manage the differences between the active state and the open state that do not exactly match.</p> + +<pre class="brush: css">.select .optList.hidden { + /* This is a simple way to hide the list in an accessible way, + we will talk more about accessibility in the end */ + max-height: 0; + visibility: hidden; +}</pre> + +<h4 id="Beautification">Beautification</h4> + +<p>So now that we have the basic functionality in place, the fun can start. The following is just an example of what is possible, and will match the screenshot at the beginning of this article. However, you should feel free to experiment and see what you can come up with.</p> + +<pre class="brush: css">.select { + /* All sizes will be expressed with the em value for accessibility reasons + (to make sure the widget remains resizable if the user uses the + browser's zoom in a text-only mode). The computations are made + assuming 1em == 16px which is the default value in most browsers. + If you are lost with px to em conversion, try http://riddle.pl/emcalc/ */ + font-size : 0.625em; /* this (10px) is the new font size context for em value in this context */ + font-family : Verdana, Arial, sans-serif; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + /* We need extra room for the down arrow we will add */ + padding : .1em 2.5em .2em .5em; /* 1px 25px 2px 5px */ + width : 10em; /* 100px */ + + border : .2em solid #000; /* 2px */ + border-radius : .4em; /* 4px */ + box-shadow : 0 .1em .2em rgba(0,0,0,.45); /* 0 1px 2px */ + + /* The first declaration is for browsers that do not support linear gradients. + The second declaration is because WebKit based browsers haven't unprefixed it yet. + If you want to support legacy browsers, try http://www.colorzilla.com/gradient-editor/ */ + background : #F0F0F0; + background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); + background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); +} + +.select .value { + /* Because the value can be wider than our widget, we have to make sure it will not + change the widget's width */ + display : inline-block; + width : 100%; + overflow : hidden; + + vertical-align: top; + + /* And if the content overflows, it's better to have a nice ellipsis. */ + white-space : nowrap; + text-overflow: ellipsis; +}</pre> + +<p>We don't need an extra element to design the down arrow; instead, we're using the {{cssxref(":after")}} pseudo-element. However, it could also be implemented using a simple background image on the <code>select</code> class.</p> + +<pre class="brush: css">.select:after { + content : "▼"; /* We use the unicode caracter U+25BC; see http://www.utf8-chartable.de */ + position: absolute; + z-index : 1; /* This will be important to keep the arrow from overlapping the list of options */ + top : 0; + right : 0; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + height : 100%; + width : 2em; /* 20px */ + padding-top : .1em; /* 1px */ + + border-left : .2em solid #000; /* 2px */ + border-radius: 0 .1em .1em 0; /* 0 1px 1px 0 */ + + background-color : #000; + color : #FFF; + text-align : center; +}</pre> + +<p>Next, let's style the list of options:</p> + +<pre class="brush: css">.select .optList { + z-index : 2; /* We explicitly said the list of options will always overlap the down arrow */ + + /* this will reset the default style of the ul element */ + list-style: none; + margin : 0; + padding: 0; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + /* This will ensure that even if the values are smaller than the widget, + the list of options will be as large as the widget itself */ + min-width : 100%; + + /* In case the list is too long, its content will overflow vertically + (which will add a vertical scrollbar automatically) but never horizontally + (because we haven't set a width, the list will adjust its width automatically. + If it can't, the content will be truncated) */ + max-height: 10em; /* 100px */ + overflow-y: auto; + overflow-x: hidden; + + border: .2em solid #000; /* 2px */ + border-top-width : .1em; /* 1px */ + border-radius: 0 0 .4em .4em; /* 0 0 4px 4px */ + + box-shadow: 0 .2em .4em rgba(0,0,0,.4); /* 0 2px 4px */ + background: #f0f0f0; +}</pre> + +<p>For the options, we need to add a <code>highlight</code> class to be able to identify the value the user will pick (or has picked).</p> + +<pre class="brush: css">.select .option { + padding: .2em .3em; /* 2px 3px */ +} + +.select .highlight { + background: #000; + color: #FFFFFF; +}</pre> + +<p>So here's the result with our three states:</p> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">Basic state</th> + <th scope="col" style="text-align: center;">Active state</th> + <th scope="col" style="text-align: center;">Open state</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{EmbedLiveSample("Basic_state",120,130, "", "HTML/Forms/How_to_build_custom_form_widgets/Example_1")}}</td> + <td>{{EmbedLiveSample("Active_state",120,130, "", "HTML/Forms/How_to_build_custom_form_widgets/Example_1")}}</td> + <td>{{EmbedLiveSample("Open_state",120,130, "", "HTML/Forms/How_to_build_custom_form_widgets/Example_1")}}</td> + </tr> + <tr> + <td colspan="3" style="text-align: center;"><a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_1" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_1">Check out the source code</a></td> + </tr> + </tbody> +</table> + +<h2 id="Bring_your_widget_to_life_with_JavaScript">Bring your widget to life with JavaScript</h2> + +<p>Now that our design and structure are ready, we can write the JavaScript code to make the widget actually work.</p> + +<div class="warning"> +<p><strong>Warning:</strong> The following code is educational and should not be used as-is. Among many things, as we'll see, it is not future-proof and it will not work on legacy browsers. It also has redundant parts that should be optimized in production code.</p> +</div> + +<div class="note"> +<p><strong>Note:</strong> Creating reusable widgets is something that can be a bit tricky. The <a href="http://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html" rel="external" title="http://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html">W3C Web Component draft</a> is one of the answers to this specific issue. <a href="http://x-tags.org/" rel="external" title="http://x-tags.org/">The X-Tag project</a> is a test implementation of this specification; we encourage you to take a look at it.</p> +</div> + +<h3 id="Why_isn't_it_working">Why isn't it working?</h3> + +<p>Before we start, it's important to remember something very important about JavaScript: inside a browser, <strong>it's an unreliable technology</strong>. When you are building custom widgets, you'll have to rely on JavaScript because it's a necessary thread to tie everything together. However, there are many cases in which JavaScript isn't able to run in the browser:</p> + +<ul> + <li>The user has turned off JavaScript: This is the most unusual case ever; very few people turn off JavaScript nowadays.</li> + <li>The script is not loading. This is one of the most common cases, especially in the mobile world where the network is not very reliable.</li> + <li>The script is buggy. You should always consider this possibility.</li> + <li>The script is in conflict with a third party script. This can happen with tracking scripts or any bookmarklets the user uses.</li> + <li>The script is in conflict with, or is affected by, a browser extension (such as Firefox's <a href="https://addons.mozilla.org/fr/firefox/addon/noscript/" rel="external" title="https://addons.mozilla.org/fr/firefox/addon/noscript/">NoScript</a> extension or Chrome's <a href="https://chrome.google.com/webstore/detail/notscripts/odjhifogjcknibkahlpidmdajjpkkcfn" rel="external" title="https://chrome.google.com/webstore/detail/notscripts/odjhifogjcknibkahlpidmdajjpkkcfn">NotScripts</a> extension).</li> + <li>The user is using a legacy browser, and one of the features you require is not supported. This will happen frequently when you make use of cutting-edge APIs.</li> +</ul> + +<p>Because of these risks, it's really important to seriously consider what will happen if JavaScript isn't working. Dealing in detail with this issue is out of the scope of this article because it's closely linked to how you want to make your script generic and reusable, but we'll consider the basics of this in our example.</p> + +<p>In our example, if our JavaScript code isn't running, we'll fall back to displaying a standard {{HTMLElement("select")}} element. To achieve this, we need two things.</p> + +<p>First, we need to add a regular {{HTMLElement("select")}} element before each use of our custom widget. This is actually also required in order to be able to send data from our custom widget along with the rest of our form data; more about this later.</p> + +<pre class="brush: html"><body class="no-widget"> + <form> + <select name="myFruit"> + <option>Cherry</option> + <option>Lemon</option> + <option>Banana</option> + <option>Strawberry</option> + <option>Apple</option> + </select> + + <div class="select"> + <span class="value">Cherry</span> + <ul class="optList hidden"> + <li class="option">Cherry</li> + <li class="option">Lemon</li> + <li class="option">Banana</li> + <li class="option">Strawberry</li> + <li class="option">Apple</li> + </ul> + </div> + </form> + +</body></pre> + +<p>Second, we need two new classes to let us hide the unneeded element (that is, the "real" {{HTMLElement("select")}} element if our script isn't running, or the custom widget if it is running). Note that by default, our HTML code hides our custom widget.</p> + +<pre class="brush: css">.widget select, +.no-widget .select { + /* This CSS selector basically says: + - either we have set the body class to "widget" and thus we hide the actual {{HTMLElement("select")}} element + - or we have not changed the body class, therefore the body class is still "no-widget", + so the elements whose class is "select" must be hidden */ + position : absolute; + left : -5000em; + height : 0; + overflow : hidden; +}</pre> + +<p>Now we just need a JavaScript switch to determine if the script is running or not. This switch is very simple: if at page load time our script is running, it will remove the <code>no-widget</code> class and add the <code>widget</code> class, thereby swapping the visibility of the {{HTMLElement("select")}} element and of the custom widget.</p> + +<pre class="brush: js">window.addEventListener("load", function () { + document.body.classList.remove("no-widget"); + document.body.classList.add("widget"); +});</pre> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">Without JS</th> + <th scope="col" style="text-align: center;">With JS</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{EmbedLiveSample("No_JS",120,130, "", "HTML/Forms/How_to_build_custom_form_widgets/Example_2")}}</td> + <td>{{EmbedLiveSample("JS",120,130, "", "HTML/Forms/How_to_build_custom_form_widgets/Example_2")}}</td> + </tr> + <tr> + <td colspan="2" style="text-align: center;"><a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_2" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_2">Check out the source code</a></td> + </tr> + </tbody> +</table> + +<div class="note"> +<p><strong>Note:</strong> If you really want to make your code generic and reusable, instead of doing a class switch it's far better to just add the widget class to hide the {{HTMLElement("select")}} elements, and to dynamically add the DOM tree representing the custom widget after every {{HTMLElement("select")}} element in the page.</p> +</div> + +<h3 id="Making_the_job_easier">Making the job easier</h3> + +<p>In the code we are about to build, we will use the standard DOM API to do all the work we need. However, although DOM API support has gotten much better in browsers, there are always issues with legacy browsers (especially with good old Internet Explorer).</p> + +<p>If you want to avoid trouble with legacy browsers, there are two ways to do so: using a dedicated framework such as <a href="http://jquery.com/" rel="external" title="http://jquery.com/">jQuery</a>, <a href="https://github.com/julienw/dollardom" rel="external" title="https://github.com/julienw/dollardom">$dom</a>, <a href="http://prototypejs.org/" rel="external" title="http://prototypejs.org/">prototype</a>, <a href="http://dojotoolkit.org/" rel="external" title="http://dojotoolkit.org/">Dojo</a>, <a href="http://yuilibrary.com/" rel="external" title="http://yuilibrary.com/">YUI</a>, or the like, or by polyfilling the missing feature you want to use (which can easily be done through conditional loading, with the <a href="http://yepnopejs.com/" rel="external" title="http://yepnopejs.com/">yepnope</a> library for example).</p> + +<p>The features we plan to use are the following (ordered from the riskiest to the safest):</p> + +<ol> + <li>{{domxref("element.classList","classList")}}</li> + <li>{{domxref("EventTarget.addEventListener","addEventListener")}}</li> + <li><code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach" title="/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach">forEach</a></code> (This is not DOM but modern JavaScript)</li> + <li>{{domxref("element.querySelector","querySelector")}} and {{domxref("element.querySelectorAll","querySelectorAll")}}</li> +</ol> + +<p>Beyond the availability of those specific features, there is still one issue remaining before starting. The object returned by the {{domxref("element.querySelectorAll","querySelectorAll()")}} function is a {{domxref("NodeList")}} rather than an <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array" title="/en-US/docs/JavaScript/Reference/Global_Objects/Array">Array</a></code>. This is important because <code>Array</code> objects support the <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach" title="/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach">forEach</a></code> function, but {{domxref("NodeList")}} doesn't. Because {{domxref("NodeList")}} really looks like an <code>Array</code> and because <code>forEach</code> is so convenient to use, we can easily add the support of <code>forEach</code> to {{domxref("NodeList")}} in order to make our life easier, like so:</p> + +<pre class="brush: js">NodeList.prototype.forEach = function (callback) { + Array.prototype.forEach.call(this, callback); +}</pre> + +<p>We weren't kidding when we said it's easy to do.</p> + +<h3 id="Building_event_callbacks">Building event callbacks</h3> + +<p>The ground is ready, we can now start to define all the functions that will be used each time the user interacts with our widget.</p> + +<pre class="brush: js">// This function will be used each time we want to deactivate a custom widget +// It takes one parameter +// select : the DOM node with the `select` class to deactivate +function deactivateSelect(select) { + + // If the widget is not active there is nothing to do + if (!select.classList.contains('active')) return; + + // We need to get the list of options for the custom widget + var optList = select.querySelector('.optList'); + + // We close the list of option + optList.classList.add('hidden'); + + // and we deactivate the custom widget itself + select.classList.remove('active'); +} + +// This function will be used each time the user wants to (de)activate the widget +// It takes two parameters: +// select : the DOM node with the `select` class to activate +// selectList : the list of all the DOM nodes with the `select` class +function activeSelect(select, selectList) { + + // If the widget is already active there is nothing to do + if (select.classList.contains('active')) return; + + // We have to turn off the active state on all custom widgets + // Because the deactivateSelect function fulfill all the requirement of the + // forEach callback function, we use it directly without using an intermediate + // anonymous function. + selectList.forEach(deactivateSelect); + + // And we turn on the active state for this specific widget + select.classList.add('active'); +} + +// This function will be used each time the user wants to open/closed the list of options +// It takes one parameter: +// select : the DOM node with the list to toggle +function toggleOptList(select) { + + // The list is kept from the widget + var optList = select.querySelector('.optList'); + + // We change the class of the list to show/hide it + optList.classList.toggle('hidden'); +} + +// This function will be used each time we need to highlight an option +// It takes two parameters: +// select : the DOM node with the `select` class containing the option to highlight +// option : the DOM node with the `option` class to highlight +function highlightOption(select, option) { + + // We get the list of all option available for our custom select element + var optionList = select.querySelectorAll('.option'); + + // We remove the highlight from all options + optionList.forEach(function (other) { + other.classList.remove('highlight'); + }); + + // We highlight the right option + option.classList.add('highlight'); +};</pre> + +<p>That's all you need in order to handle the various states of the custom widget.</p> + +<p>Next, we bind these functions to the appropriate events:</p> + +<pre class="brush: js">// We handle the event binding when the document is loaded. +window.addEventListener('load', function () { + var selectList = document.querySelectorAll('.select'); + + // Each custom widget needs to be initialized + selectList.forEach(function (select) { + + // as well as all its `option` elements + var optionList = select.querySelectorAll('.option'); + + // Each time a user hovers their mouse over an option, we highlight the given option + optionList.forEach(function (option) { + option.addEventListener('mouseover', function () { + // Note: the `select` and `option` variable are closures + // available in the scope of our function call. + highlightOption(select, option); + }); + }); + + // Each times the user click on a custom select element + select.addEventListener('click', function (event) { + // Note: the `select` variable is a closure + // available in the scope of our function call. + + // We toggle the visibility of the list of options + toggleOptList(select); + }); + + // In case the widget gain focus + // The widget gains the focus each time the user clicks on it or each time + // they use the tabulation key to access the widget + select.addEventListener('focus', function (event) { + // Note: the `select` and `selectList` variable are closures + // available in the scope of our function call. + + // We activate the widget + activeSelect(select, selectList); + }); + + // In case the widget loose focus + select.addEventListener('blur', function (event) { + // Note: the `select` variable is a closure + // available in the scope of our function call. + + // We deactivate the widget + deactivateSelect(select); + }); + }); +});</pre> + +<p>At that point, our widget will change state according to our design, but its value doesn't get updated yet. We'll handle that next.</p> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">Live example</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{EmbedLiveSample("Change_states",120,130, "", "HTML/Forms/How_to_build_custom_form_widgets/Example_3")}}</td> + </tr> + <tr> + <td style="text-align: center;"><a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_3" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_3">Check out the source code</a></td> + </tr> + </tbody> +</table> + +<h3 id="Handling_the_widget's_value">Handling the widget's value</h3> + +<p>Now that our widget is working, we have to add code to update its value according to user input and make it possible to send the value along with form data.</p> + +<p>The easiest way to do this is to use a native widget under the hood. Such a widget will keep track of the value with all the built-in controls provided by the browser, and the value will be sent as usual when a form is submitted. There's no point in reinventing the wheel when we can have all this done for us.</p> + +<p>As seen previously, we already use a native select widget as a fallback for accessibility reasons; we can simply synchronize its value with that of our custom widget:</p> + +<pre class="brush: js">// This function updates the displayed value and synchronizes it with the native widget. +// It takes two parameters: +// select : the DOM node with the class `select` containing the value to update +// index : the index of the value to be selected +function updateValue(select, index) { + // We need to get the native widget for the given custom widget + // In our example, that native widget is a sibling of the custom widget + var nativeWidget = select.previousElementSibling; + + // We also need to get the value placeholder of our custom widget + var value = select.querySelector('.value'); + + // And we need the whole list of options + var optionList = select.querySelectorAll('.option'); + + // We set the selected index to the index of our choice + nativeWidget.selectedIndex = index; + + // We update the value placeholder accordingly + value.innerHTML = optionList[index].innerHTML; + + // And we highlight the corresponding option of our custom widget + highlightOption(select, optionList[index]); +}; + +// This function returns the current selected index in the native widget +// It takes one parameter: +// select : the DOM node with the class `select` related to the native widget +function getIndex(select) { + // We need to access the native widget for the given custom widget + // In our example, that native widget is a sibling of the custom widget + var nativeWidget = select.previousElementSibling; + + return nativeWidget.selectedIndex; +};</pre> + +<p>With these two functions, we can bind the native widgets to the custom ones:</p> + +<pre class="brush: js">// We handle event binding when the document is loaded. +window.addEventListener('load', function () { + var selectList = document.querySelectorAll('.select'); + + // Each custom widget needs to be initialized + selectList.forEach(function (select) { + var optionList = select.querySelectorAll('.option'), + selectedIndex = getIndex(select); + + // We make our custom widget focusable + select.tabIndex = 0; + + // We make the native widget no longer focusable + select.previousElementSibling.tabIndex = -1; + + // We make sure that the default selected value is correctly displayed + updateValue(select, selectedIndex); + + // Each time a user clicks on an option, we update the value accordingly + optionList.forEach(function (option, index) { + option.addEventListener('click', function (event) { + updateValue(select, index); + }); + }); + + // Each time a user uses their keyboard on a focused widget, we update the value accordingly + select.addEventListener('keyup', function (event) { + var length = optionList.length, + index = getIndex(select); + + // When the user hits the down arrow, we jump to the next option + if (event.keyCode === 40 && index < length - 1) { index++; } + + // When the user hits the up arrow, we jump to the previous option + if (event.keyCode === 38 && index > 0) { index--; } + + updateValue(select, index); + }); + }); +});</pre> + +<p>In the code above, it's worth noting the use of the <code><a href="/en-US/docs/Web/API/HTMLElement/tabIndex" title="/en-US/docs/Web/API/HTMLElement/tabIndex">tabIndex</a></code> property. Using this property is necessary to ensure that the native widget will never gain focus, and to make sure that our custom widget gains focus when the user uses his keyboard or his mouse.</p> + +<p>With that, we're done! Here's the result:</p> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">Live example</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{EmbedLiveSample("Change_states",120,130, "", "HTML/Forms/How_to_build_custom_form_widgets/Example_4")}}</td> + </tr> + <tr> + <td style="text-align: center;"><a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_4" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_4">Check out the source code</a></td> + </tr> + </tbody> +</table> + +<p>But wait a second, are we really done?</p> + +<h2 id="Make_it_accessible">Make it accessible</h2> + +<p>We have built something that works and though we're far from a fully-featured select box, it works nicely. But what we've done is nothing more than fiddle with the DOM. It has no real semantics, and even though it looks like a select box, from the browser's point of view it isn't one, so assistive technologies won't be able to understand it's a select box. In short, this pretty new select box isn't accessible!</p> + +<p>Fortunately, there is a solution and it's called <a href="/en-US/docs/Accessibility/ARIA" title="/en-US/docs/Accessibility/ARIA">ARIA</a>. ARIA stands for "Accessible Rich Internet Application", and it's <a href="http://www.w3.org/TR/wai-aria/" rel="external" title="http://www.w3.org/TR/wai-aria/">a W3C specification</a> specifically designed for what we are doing here: making web applications and custom widgets accessible. It's basically a set of attributes that extend HTML so that we can better describe roles, states and properties as though the element we've just devised was the native element it tries to pass for. Using these attributes is dead simple, so let's do it.</p> + +<h3 id="The_role_attribute">The <code>role</code> attribute</h3> + +<p>The key attribute used by <a href="/en-US/docs/Accessibility/ARIA" title="/en-US/docs/Accessibility/ARIA">ARIA</a> is the <a href="/en-US/docs/Accessibility/ARIA/ARIA_Techniques" title="/en-US/docs/Accessibility/ARIA/ARIA_Techniques"><code>role</code></a> attribute. The <a href="/en-US/docs/Accessibility/ARIA/ARIA_Techniques" title="/en-US/docs/Accessibility/ARIA/ARIA_Techniques"><code>role</code></a> attribute accepts a value that defines what an element is used for. Each role defines its own requirements and behaviors. In our example, we will use the <code><a href="/en-US/docs/Accessibility/ARIA/ARIA_Techniques/Using_the_listbox_role" title="/en-US/docs/Accessibility/ARIA/ARIA_Techniques/Using_the_listbox_role">listbox</a></code> role. It's a "composite role", which means elements with that role expect to have children, each with a specific role (in this case, at least one child with the <code>option</code> role).</p> + +<p>It's also worth noting that ARIA defines roles that are applied by default to standard HTML markup. For example, the {{HTMLElement("table")}} element matches the role <code>grid</code>, and the {{HTMLElement("ul")}} element matches the role <code>list</code>. Because we use a {{HTMLElement("ul")}} element, we want to make sure the <code>listbox</code> role of our widget will supersede the <code>list</code> role of the {{HTMLElement("ul")}} element. To that end, we will use the role <code>presentation</code>. This role is designed to let us indicate that an element has no special meaning, and is used solely to present information. We will apply it to our {{HTMLElement("ul")}} element.</p> + +<p>To support the <code><a href="/en-US/docs/Accessibility/ARIA/ARIA_Techniques/Using_the_listbox_role" title="/en-US/docs/Accessibility/ARIA/ARIA_Techniques/Using_the_listbox_role">listbox</a></code> role, we just have to update our HTML like this:</p> + +<pre class="brush: html"><!-- We add the role="listbox" attribute to our top element --> +<div class="select" role="listbox"> + <span class="value">Cherry</span> + <!-- We also add the role="presentation" to the ul element --> + <ul class="optList" role="presentation"> + <!-- And we add the role="option" attribute to all the li elements --> + <li role="option" class="option">Cherry</li> + <li role="option" class="option">Lemon</li> + <li role="option" class="option">Banana</li> + <li role="option" class="option">Strawberry</li> + <li role="option" class="option">Apple</li> + </ul> +</div></pre> + +<div class="note"> +<p><strong>Note:</strong> Including both the <code>role</code> attribute and a <code>class</code> attribute is only necessary if you want to support legacy browsers that do not support the <a href="/en-US/docs/CSS/Attribute_selectors" title="/en-US/docs/CSS/Attribute_selectors">CSS attribute selectors</a>.</p> +</div> + +<h3 id="The_aria-selected_attribute">The <code>aria-selected</code> attribute</h3> + +<p>Using the <a href="/en-US/docs/Accessibility/ARIA/ARIA_Techniques" title="/en-US/docs/Accessibility/ARIA/ARIA_Techniques"><code>role</code></a> attribute is not enough. <a href="/en-US/docs/Accessibility/ARIA" title="/en-US/docs/Accessibility/ARIA">ARIA</a> also provides many states and property attributes. The more and better you use them, the better your widget will be understood by assistive technologies. In our case, we will limit our usage to one attribute: <code>aria-selected</code>.</p> + +<p>The <code>aria-selected</code> attribute is used to mark which option is currently selected; this lets assistive technologies inform the user what the current selection is. We will use it dynamically with JavaScript to mark the selected option each time the user chooses one. To that end, we need to revise our <code>updateValue()</code> function:</p> + +<pre class="brush: js">function updateValue(select, index) { + var nativeWidget = select.previousElementSibling; + var value = select.querySelector('.value'); + var optionList = select.querySelectorAll('.option'); + + // We make sure that all the options are not selected + optionList.forEach(function (other) { + other.setAttribute('aria-selected', 'false'); + }); + + // We make sure the chosen option is selected + optionList[index].setAttribute('aria-selected', 'true'); + + nativeWidget.selectedIndex = index; + value.innerHTML = optionList[index].innerHTML; + highlightOption(select, optionList[index]); +};</pre> + +<p>Here is the final result of all these changes (you'll get a better feel for this by trying it with an assistive technology such as <a href="http://www.nvda-project.org/" rel="external" title="http://www.nvda-project.org/">NVDA</a> or <a href="http://www.apple.com/accessibility/voiceover/" rel="external" title="http://www.apple.com/accessibility/voiceover/">VoiceOver</a>):</p> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">Live example</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{EmbedLiveSample("Change_states",120,130, "", "HTML/Forms/How_to_build_custom_form_widgets/Example_5")}}</td> + </tr> + <tr> + <td style="text-align: center;"><a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_5" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_2">Check out the final source code</a></td> + </tr> + </tbody> +</table> + +<h2 id="Conclusion">Conclusion</h2> + +<p>We have seen all the basics of building a custom form widget, but as you can see it's not trivial to do, and often it's better and easier to rely on third-party libraries instead of coding them from scratch yourself (unless, of course, your goal is to build such a library).</p> + +<p>Here are a few libraries you should consider before coding your own:</p> + +<ul> + <li><a href="http://jqueryui.com/" rel="external" title="http://jqueryui.com/">jQuery UI</a></li> + <li><a href="https://github.com/marghoobsuleman/ms-Dropdown" rel="external" title="https://github.com/marghoobsuleman/ms-Dropdown">msDropDown</a></li> + <li><a href="http://www.emblematiq.com/lab/niceforms/" rel="external" title="http://www.emblematiq.com/lab/niceforms/">Nice Forms</a></li> + <li><a href="https://www.google.fr/search?q=HTML+custom+form+controls&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:fr:official&client=firefox-a" rel="external" title="https://www.google.fr/search?q=HTML+custom+form+controls&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:fr:official&client=firefox-a">And many more…</a></li> +</ul> + +<p>If you want to move forward, the code in this example needs some improvement before it becomes generic and reusable. This is an exercise you can try to perform. Two hints to help you in this: the first argument for all our functions is the same, which means those functions need the same context. Building an object to share that context would be wise. Also, you need to make it feature-proof; that is, it needs to be able to work better with a variety of browsers whose compatibility with the Web standards they use vary. Have fun!</p> + +<p>{{PreviousMenuNext("Learn/HTML/Forms/Form_validation", "Learn/HTML/Forms/Sending_forms_through_JavaScript", "Learn/HTML/Forms")}}</p> + +<p> </p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Forms/Your_first_HTML_form">Your first HTML form</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">How to structure an HTML form</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/The_native_form_widgets">The native form widgets</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Sending form data</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Form_validation">Form data validation</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets">How to build custom form widgets</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript">Sending forms through JavaScript</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/HTML_forms_in_legacy_browsers">HTML forms in legacy browsers</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Styling_HTML_forms">Styling HTML forms</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Advanced_styling_for_HTML_forms">Advanced styling for HTML forms</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Property_compatibility_table_for_form_widgets">Property compatibility table for form widgets</a></li> +</ul> + +<p> </p> diff --git a/files/es/learn/forms/how_to_structure_a_web_form/index.html b/files/es/learn/forms/how_to_structure_a_web_form/index.html new file mode 100644 index 0000000000..45f58520d1 --- /dev/null +++ b/files/es/learn/forms/how_to_structure_a_web_form/index.html @@ -0,0 +1,320 @@ +--- +title: Cómo estructurar un formulario HTML +slug: Learn/HTML/Forms/How_to_structure_an_HTML_form +translation_of: Learn/Forms/How_to_structure_a_web_form +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Forms/Your_first_form", "Learn/Forms/Basic_native_form_controls", "Learn/Forms")}}</div> + +<p class="summary">Una vez examinados los conceptos básicos, vamos a ver más en detalle los elementos que se utilizan para proporcionar estructura y significado a las diferentes partes de un formulario.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática y de <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">lenguajes HTML</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender cómo se estructuran los formularios HTML y se les proporciona semántica para dotarlos de criterios de usabilidad y accesibilidad.</td> + </tr> + </tbody> +</table> + +<p>La flexibilidad que presentan los formularios los convierte en una de las estructuras más complejas en <a href="/es/docs/Learn/HTML" title="/en-US/docs/HTML">HTML</a>, puesto que puedes crear cualquier tipo de formulario básico a partir de los elementos y atributos destinados a esta función. El uso de una estructura correcta al crear un formulario HTML te ayudará a garantizar que el formulario presente las características de usabilidad y <a href="/es/docs/Learn/Accessibility">accesibilidad </a> adecuadas.</p> + +<h2 id="El_elemento_<form>">El elemento <form></h2> + +<p>El elemento {{HTMLElement ("form")}} define formalmente un formulario y los atributos que determinan el comportamiento del formulario. Cada vez que desees crear un formulario HTML, debes empezar utilizando este elemento y anidando todo el contenido dentro de él. Muchas tecnologías de asistencia y complementos del navegador pueden descubrir elementos {{HTMLElement ("form")}} e implementar códigos de apoyo (<em>hooks</em>) especiales para que sean más fáciles de usar.</p> + +<p>Ya lo vimos en el artículo anterior.</p> + +<div class="warning"><strong>Advertencia:</strong> Está estrictamente prohibido anidar un formulario dentro de otro formulario. Anidar formularios no es una buena idea porque puede ocasionar comportamientos impredecibles.</div> + +<p>Siempre es posible usar controles de formulario fuera de un elemento {{HTMLElement ("form")}}. Si la haces, por defecto ese control no tiene nada que ver con ningún formulario, a menos que lo asocies a algún formulario con el atributo <a href="/en-US/docs/Web/HTML/Attributes/form"><code>form</code></a>. Esto se introdujo para permitir vincular explícitamente un control a un formulario, incluso si este no está dentro de él.</p> + +<p>A continuación vamos a exponer los elementos estructurales que encontrarás en un formulario.</p> + +<h2 id="Los_elementos_<fieldset>_y_<legend>">Los elementos <fieldset> y <legend></h2> + +<p>El elemento {{HTMLElement ("fieldset")}} es una forma cómoda de crear grupos de controles de formulario (también denominados <em>widgets</em>) que comparten el mismo propósito, con fines semánticos y de aplicación de estilo. Puedes etiquetar un elemento {{HTMLElement ("fieldset")}} incluyendo un elemento {{HTMLElement ("legend")}} justo debajo de la etiqueta de apertura {{HTMLElement ("fieldset")}}. El contenido textual del elemento {{HTMLElement ("legend")}} describe formalmente el propósito del elemento {{HTMLElement ("fieldset")}} que está incluido dentro.</p> + +<p>Muchas tecnologías de asistencia utilizarán el elemento {{HTMLElement ("legend")}} como si fuera una parte de la etiqueta de cada control dentro del elemento {{HTMLElement ("fieldset")}} correspondiente. Por ejemplo, algunos lectores de pantalla como <a href="http://www.freedomscientific.com/products/software/jaws/" rel="external" title="http://www.freedomscientific.com/products/fs/jaws-product-page.asp">Jaws</a> y <a href="http://www.nvda-project.org/" rel="external" title="http://www.nvda-project.org/">NVDA</a> leerán el contenido de la leyenda antes de decir la etiqueta de cada control.</p> + +<p>Un pequeño ejemplo:</p> + +<pre class="brush:html; notranslate"><form> + <fieldset> + <legend>Tamaño del zumo de fruta</legend> + <p> + <input type="radio" name="size" id="size_1" value="small"> + <label for="size_1">Pequeño</label> + </p> + <p> + <input type="radio" name="size" id="size_2" value="medium"> + <label for="size_2">Mediano</label> + </p> + <p> + <input type="radio" name="size" id="size_3" value="large"> + <label for="size_3">Grande</label> + </p> + </fieldset> +</form></pre> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar este ejemplo en <a href="https://github.com/mdn/learning-area/blob/master/html/forms/html-form-structure/fieldset-legend.html">fieldset-legend.html</a> (<a href="https://mdn.github.io/learning-area/html/forms/html-form-structure/fieldset-legend.html">consúltalo en vivo</a>).</p> +</div> + +<p>Al leer el formulario anterior, un lector de pantalla dirá «Tamaño del zumo de fruta: pequeño» para el primer control de formulario, «Tamaño del zumo de fruta: mediano» para el segundo y «Tamaño del zumo de fruta: grande» para el tercero.</p> + +<p>El caso de uso que se muestra en este ejemplo es uno de los más importantes. Cada vez que tengas un conjunto de botones de opción, debes anidarlos dentro de un elemento {{HTMLElement ("fieldset")}}. Hay otros casos de uso y el elemento {{HTMLElement ("fieldset")}} también se puede usar en general para seccionar un formulario. Idealmente, los formularios largos deberían tener una extensión de varias páginas, pero si un formulario se alarga y ha de estar contenido en una sola página, colocar las diferentes secciones relacionadas dentro de diferentes conjuntos de campos mejora su usabilidad.</p> + +<p>Debido a la influencia que tiene sobre las tecnologías de asistencia, el elemento {{HTMLElement ("fieldset")}} es uno de los elementos clave para crear formularios accesibles. Sin embargo, no hay que abusar de él. Si es posible, cada vez que crees un formulario, intenta <a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility#Screenreaders">escuchar cómo lo interpreta un lector de pantalla</a>. Si suena raro, intenta mejorar la estructura del formulario.</p> + +<h2 id="El_elemento_<label>">El elemento <label></h2> + +<p>Como vimos en el artículo anterior, el elemento {{HTMLElement ("label")}} es la forma formal de definir una etiqueta para un control de un formulario HTML. Este es el elemento más importante si deseas crear formularios accesibles porque cuando se implementan correctamente, los lectores de pantalla leen la etiqueta de un elemento de formulario junto con las instrucciones relacionadas, y esto además resulta muy útil para los usuarios videntes. Tomemos este ejemplo que vimos en el artículo anterior:</p> + +<pre class="brush: html notranslate"><label for="name">Nombre:</label> <input type="text" id="name" name="user_name"></pre> + +<p>Con la etiqueta <code><label></code> asociada correctamente con <code><input></code> por su atributo <code>for</code> (que contiene el atributo <code>id</code> del elemento <code><input></code>), un lector de pantalla leerá algo como «Nombre, editar texto».</p> + +<p>Hay otra forma de asociar un control de formulario con una etiqueta: asociarlo implícitamente anidando el control de formulario dentro de <code><label></code>.</p> + +<pre class="brush: html notranslate"><label for="name"> + Nombre: <input type="text" id="name" name="user_name"> +</label></pre> + +<p>Incluso en estos casos, se aconseja establecer el atributo <code>for</code> para garantizar que todas las tecnologías de asistencia comprendan la relación entre la etiqueta y el control de formulario.</p> + +<p>Si no hay ninguna etiqueta, o si el control de formulario no está asociado implícita o explícitamente con alguna etiqueta, un lector de pantalla leerá algo así como «Editar texto en blanco», lo cual no es de mucha ayuda.</p> + +<h3 id="¡También_se_puede_hacer_clic_en_las_etiquetas!">¡También se puede hacer clic en las etiquetas!</h3> + +<p>Otra ventaja de configurar correctamente las etiquetas es que puedes hacer clic o pulsar en la etiqueta para activar el control de formulario correspondiente. Esto es útil para controles como entradas de texto, donde puedes hacer clic tanto en la etiqueta como en la entrada de texto para proporcionar el foco al control de formulario, pero es útil especialmente para botones de opción y casillas de verificación, porque la zona sensible de este control puede ser muy pequeña, y puede ser útil para facilitar su activación.</p> + +<p>Por ejemplo, al hacer clic en el texto de la etiqueta «Me gustan las cerezas» del ejemplo siguiente, cambiará el estado seleccionado de la casilla de verificación <em>taste_cherry</em>:</p> + +<pre class="brush:html; notranslate"><form> + <p> + <input type="checkbox" id="taste_1" name="taste_cherry" value="cherry"> + <label for="taste_1">Me gustan las cerezas</label> + </p> + <p> + <input type="checkbox" id="taste_2" name="taste_banana" value="banana"> + <label for="taste_2">Me gustan los plátanos</label> + </p> +</form></pre> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar este ejemplo en <a href="https://github.com/mdn/learning-area/blob/master/html/forms/html-form-structure/checkbox-label.html">checkbox-label.html</a> (<a href="https://mdn.github.io/learning-area/html/forms/html-form-structure/checkbox-label.html">consúltalo en vivo</a>).</p> +</div> + +<h3 id="Etiquetas_múltiples">Etiquetas múltiples</h3> + +<p>Estrictamente hablando, es posible poner varias etiquetas en un solo control de formulario, pero no suele ser una buena idea porque algunas tecnologías de asistencia pueden tener problemas para manejarlas. En caso de tener varias etiquetas, hay que anidar el control de formulario y sus etiquetas dentro de un único elemento {{htmlelement ("label")}}.</p> + +<p>Consideremos este ejemplo:</p> + +<pre class="brush: html notranslate"><p>Los campos obligatorios se marcan con un <abbr title = "required">*</abbr>.</p> + +<!-- Así que esto: --> +<div> + <label for="username">Nombre:</label> + <input type="text" name="username"> + <label for="username"><abbr title="required" aria-label="required">*</abbr></label> +</div> + +<!-- sería mejor hacerlo así: --> +<div> + <label for="username"> + <span>Nombre:</span> + <input id="username" type="text" name="username"> + <abbr title="required" aria-label="required">*</abbr> + </label> +</div> + +<!-- Pero probablemente lo mejor es esto: --> +<div> + <label for="username">Nombre: <abbr title="required" aria-label="required">*</abbr></label> + <input id="username" type="text" name="username"> +</div></pre> + +<p>{{EmbedLiveSample("Etiquetas_múltiples", 120, 120)}}</p> + +<p>El párrafo de la parte superior establece una regla para los elementos que son obligatorios. La regla ha de incluirse <em>antes</em> de usarse para que tanto los usuarios videntes como los usuarios que utilizan tecnologías de asistencia y lectores de pantalla, sepan lo que significa antes de encontrar un elemento obligatorio. Pero si bien esto ayuda a informar a los usuarios de lo que significa un asterisco, no es posible confiar plenamente en ello. Cuando un lector de pantalla se encuentre con un asterisco pronunciará «estrella». Cuando un usuario vidente pase el ratón por encima, debería aparecer una etiqueta de «obligatorio», lo cual se logra con el uso del atributo <code>title</code>. Pero los títulos que se leen en voz alta dependen de la configuración del lector de pantalla, por lo que es más fiable incluir también el atributo <code><a href="/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute">aria-label</a></code>, que los lectores de pantalla siempre leen.</p> + +<p>Las variantes anteriores aumentan en efectividad a medida que se avanza por ellas:</p> + +<ul> + <li>En el primer ejemplo, la etiqueta no se lee en absoluto con la entrada de texto; solo se obtiene «Editar texto en blanco», y además las etiquetas se leen por separado. Los múltiples elementos <code><label></code> confunden al lector de pantalla.</li> + <li>En el segundo ejemplo, las cosas son un poco más claras: la etiqueta que se lee junto con la entrada de texto es «Editar texto nombre estrella nombre obligatorio», pero las etiquetas aún se leen por separado. Las cosas continúan siendo un poco confusas, pero esta vez funciona algo mejor porque <code><input></code> tiene una etiqueta asociada.</li> + <li>El tercer ejemplo es el mejor: la etiqueta se lee en conjunto, y la etiqueta que se lee con la entrada es «Editar texto nombre requerido».</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Es posible que obtengas resultados ligeramente diferentes dependiendo de tu lector de pantalla. Esta prueba se hizo con VoiceOver (NVDA se comporta de manera similar). Nos encantaría conocer tus experiencias.</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar este ejemplo en GitHub como <a href="https://github.com/mdn/learning-area/blob/master/html/forms/html-form-structure/required-labels.html">required-labels.html</a> (<a href="https://mdn.github.io/learning-area/html/forms/html-form-structure/required-labels.html">o consultarlo en vivo</a>). No pruebes el ejemplo con las dos o tres versiones sin los comentarios porque los lectores de pantalla se confundirán si hay múltiples etiquetas y múltiples entradas con el mismo ID.</p> +</div> + +<h2 id="Estructuras_HTML_comunes_que_se_utilizan_en_los_formularios">Estructuras HTML comunes que se utilizan en los formularios</h2> + +<p>Más allá de las estructuras específicas de los formularios web, es bueno recordar que el marcado de los formularios es solo HTML. Esto significa que puedes usar todo el poder del HTML para estructurar un formulario web.</p> + +<p>Como puedes ver en los ejemplos, es una práctica común delimitar una etiqueta y su control de formulario con un elemento {{HTMLElement ("li")}} dentro de una lista {{HTMLElement ("ul")}} o {{HTMLElement ("ol")}}. Los elementos {{HTMLElement ("p")}} y {{HTMLElement ("div")}} también se usan con frecuencia. Se recomiendan las listas para estructurar múltiples casillas de verificación o botones de opción.</p> + +<p>Además del elemento {{HTMLElement ("fieldset")}}, también es una práctica común usar títulos HTML (por ejemplo, {{htmlelement ("h1")}}, {{htmlelement ("h2")}}), y seccionar (por ejemplo, {{htmlelement ("section")}}), para estructurar formas complejas.</p> + +<p>Depende de ti, sobre todo, encontrar un estilo de codificación cómodo que dé como resultado formas con buena accesibilidad y usabilidad. Las secciones independientes con funciones diferentes deben estar contenidas en elementos {{htmlelement ("section")}} separados, con elementos {{htmlelement ("fieldset")}} para contener botones de opción.</p> + +<h3 id="Aprendizaje_activo_construir_una_estructura_de_formulario">Aprendizaje activo: construir una estructura de formulario</h3> + +<p>Pongamos en práctica estas ideas y creemos un formulario un poco más complicado: un formulario de pago. Este formulario contendrá una serie de tipos de control que quizás aún no comprendas. No te preocupes por esto por ahora; en el artículo siguiente descubrirás cómo funcionan (<a href="/es/docs/Learn/HTML/Forms/The_native_form_widgets">Los controles básicos de formulario originales</a>). Por ahora, lee con detenimiento las descripciones y sigue las instrucciones, y empieza a formarte una idea de qué elementos de delimitación se utilizan para estructurar el formulario y por qué.</p> + +<ol> + <li>Para comenzar, haz una copia local de nuestro <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">archivo de plantilla en blanco</a> y el <a href="https://github.com/mdn/learning-area/blob/master/html/forms/html-form-structure/payment-form.css">CSS de nuestro formulario de pago</a> en un nuevo directorio de tu ordenador.</li> + <li>Añade dentro del elemento HTML {{htmlelement ("head")}} la línea siguiente para aplicar el CSS al HTML: + <pre class="brush: html notranslate"><link href="payment-form.css" rel="stylesheet"></pre> + </li> + <li>A continuación, añade el elemento externo {{htmlelement ("form")}} para crear tu formulario: + <pre class="brush: html notranslate"><form> + +</form></pre> + </li> + <li>Añade un encabezado y un párrafo dentro de las etiquetas <code><form></code>> para informar a los usuarios cómo se marcan los campos obligatorios: + <pre class="brush: html notranslate"><h1>Forma de pago</h1> +<p>Los campos obligatorios van seguidos de <strong> <abbr title = "required"> * </abbr> </strong>.</p></pre> + </li> + <li>A continuación añadimos al formulario una sección de código más grande, justo debajo de nuestra entrada anterior. Aquí verás que delimitamos con un elemento {{htmlelement ("section")}} independiente los campos con la información de contacto. Además, hay un conjunto de dos botones de opción, cada uno de los cuales colocamos dentro de su elemento de lista ({{htmlelement ("li")}}) propio. También hay dos entradas de texto estándar {{htmlelement ("input")}} y sus elementos {{htmlelement ("label")}} asociados, cada uno anidado dentro de un elemento {{htmlelement ("p")}} y una entrada de texto para introducir una contraseña. Añade este código a tu formulario: + <pre class="brush: html notranslate"><section> + <h2>Información de contacto</h2> + <fieldset> + <legend>Título</legend> + <ul> + <li> + <label for="title_1"> + <input type="radio" id="title_1" name="title" value="K" > + Rey + </label> + </li> + <li> + <label for="title_2"> + <input type="radio" id="title_2" name="title" value="Q"> + Reina + </label> + </li> + <li> + <label for="title_3"> + <input type="radio" id="title_3" name="title" value="J"> + Bufón + </label> + </li> + </ul> + </fieldset> + <p> + <label for="name"> + <span>Nombre:</span> + <strong><abbr title="required">*</abbr></strong> + </label> + <input type="text" id="name" name="username"> + </p> + <p> + <label for="mail"> + <Span>Correo electrónico:</ span> + <strong><abbr title="required">*</abbr></strong> + </label> + <input type="email" id="mail" name="usermail"> + </p> + <p> + <label for="pwd"> + <span>Contraseña:</span> + <strong><abbr title="required">*</abbr></strong> + </label> + <input type="password" id="pwd" name="password"> + </p> +</section></pre> + </li> + <li>La segunda <code><section></code> de nuestro formulario es la información de pago. Hay tres controles diferentes, junto con sus etiquetas, cada uno contenido dentro de un elemento <code><p></code>. El primero es un menú desplegable ({{htmlelement ("select")}}) para seleccionar el tipo de tarjeta de crédito. El segundo es un elemento <code><input></code> de tipo <code>tel</code>, para introducir un número de tarjeta de crédito. Si bien podríamos haber usado el tipo <code>number</code>, no queremos una interfaz de usuario con control de número. El último es un elemento <code><input></code> de tipo <code>date</code>, para introducir la fecha de caducidad de la tarjeta; aparecerá como un control de selección de fecha en navegadores compatibles, y como una entrada de texto normal en navegadores no compatibles. Estos tipos de entrada más nuevos volverán a aparecer en el artículo <a href="/en-US/docs/Learn/Forms/HTML5_input_types">Tipos de entrada HTML5</a>.<br> + <br> + Introduce los datos siguientes a continuación de la sección anterior: + <pre class="brush: html notranslate"><section> + <h2>Información de pago</h2> + <p> + <label for="card"> + <span>Tipo de tarjeta:</span> + </label> + <select id="card" name="usercard"> + <option value="visa">Visa</option> + <option value="mc">Mastercard</option> + <option value="amex">American Express</option> + </select> + </p> + <p> + <label for="number"> + <span>Número de tarjeta:</span> + <strong><abbr title="required">*</abbr></strong> + </label> + <input type="tel" id="number" name="cardnumber"> + </p> + <p> + <label for="date"> + <span>Fecha de caducidad:</span> + <strong><abbr title="required">*</abbr></strong> + <em>el formato mm/aa</em> + </label> + <input type="date" id="date" name="expiration"> + </p> +</section></pre> + </li> + <li>La última sección que añadimos es mucho más simple y contiene solo un {{htmlelement ("button")}} de tipo <code>submit</code>, para enviar los datos del formulario. Añádelo al final de tu formulario: + <pre class="brush: html notranslate"><p> <button type="submit">Validar el pago</button> </p></pre> + </li> +</ol> + +<p>Debajo puedes ver en acción el formulario terminado (también lo encontrarás en GitHub; consulta el <a href="https://github.com/mdn/learning-area/blob/master/html/forms/html-form-structure/payment-form.html">código fuente</a> de nuestro payment-form.html y <a href="https://mdn.github.io/learning-area/html/forms/html-form-structure/payment-form.html">ejecútalo en vivo</a>):</p> + +<p>{{EmbedLiveSample("A_payment_form","100%",620, "", "/en-US/Learn/Forms/How_to_structure_a_web_form/Example")}}</p> + +<h2 id="¡Prueba_tus_habilidades!">¡Prueba tus habilidades!</h2> + +<p>Has llegado al final de este artículo pero ¿puedes recordar la información más importante? Puedes encontrar pruebas adicionales para comprobar que has comprendido la información antes de continuar — visita <a class="external external-icon" href="https://wiki.developer.mozilla.org/en-US/docs/Learn/Forms/Test_your_skills:_Form_structure" rel="noopener">Prueba tus habilidades: Estructura de formularios</a>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Ahora tienes todos los conocimientos necesarios para estructurar adecuadamente tus formularios web. Expondremos muchas de las características que se presentan aquí en los artículos siguientes, y el próximo artículo analizará con más detalle el uso de todos los diferentes tipos de controles de formulario que vas a querer usar para recopilar la información de tus usuarios.</p> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li><a href="http://www.alistapart.com/articles/sensibleforms/" rel="external" title="http://www.alistapart.com/articles/sensibleforms/">A List Apart: <em>Sensible Forms: A Form Usability Checklist</em></a></li> +</ul> + +<p>{{PreviousMenuNext("Learn/Forms/Your_first_form", "Learn/Forms/Basic_native_form_controls", "Learn/Forms")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Forms/Your_first_HTML_form">Tu primer formulario HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">Cómo estructurar un formulario HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/The_native_form_widgets">Los controles básicos de formulario originales</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/HTML5_input_types">Tipos de entrada HTML5</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Additional_form_controls">Controles de formulario adicionales</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/UI_pseudo-classes">Pseudoclasses UI</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Styling_HTML_forms">Aplicar estilo a formularios HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Form_validation">Validación de datos en un formulario</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Enviar los datos de un formulario</a></li> +</ul> + +<h3 id="Temas_avanzados">Temas avanzados</h3> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript">Enviar formularios con JavaScript</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets">Cómo crear controles de formulario personalizados</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/HTML_forms_in_legacy_browsers">Formularios HTML en navegadores antiguos</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Advanced_styling_for_HTML_forms">Cuestiones avanzadas de aplicación de estilo para formularios HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Property_compatibility_table_for_form_widgets">Tabla de compatibilidad de los controles de formulario</a> según su código propietario</li> +</ul> diff --git a/files/es/learn/forms/html5_input_types/index.html b/files/es/learn/forms/html5_input_types/index.html new file mode 100644 index 0000000000..d463399e93 --- /dev/null +++ b/files/es/learn/forms/html5_input_types/index.html @@ -0,0 +1,276 @@ +--- +title: Tipos de input de HTML5 +slug: Learn/HTML/Forms/Tipos_input_HTML5 +translation_of: Learn/Forms/HTML5_input_types +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Forms/Basic_native_form_controls", "Learn/Forms/Other_form_controls", "Learn/Forms")}}</div> + +<p class="summary">En el <a href="/en-US/docs/Learn/Forms/Basic_native_form_controls">artículo anterior</a> vimos el elemento {{htmlelement("input")}} y los valores de su atributo <code>type</code>, disponibles desde los inicios de HTML. Ahora veremos en detalle la funcionalidad de los controles de formulario más recientes, incluyendo algunos tipos de input nuevos, los cuales fueron añadidos en HTML5 para permitir la recolección de tipos de datos específicos</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Requisitos previos:</th> + <td>Formación básica en informática, y una <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">comprensión básica de HTML</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender los valores de tipo input disponibles más recientes para crear controles de formulario nativos, y cómo implementarlos utilizando HTML.</td> + </tr> + </tbody> +</table> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: La mayoría de las características discutidas en este artículo tienen un amplio soporte en todos los navegadores, anotaremos cualquier excepción. Si quieres más detalles referente al soporte de navegadores, deberías consultar nuestra <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element#Forms">referéncia de elementos de formulario HTML</a>, y en particular nuestra referéncia extensiva de <a href="/en-US/docs/Web/HTML/Element/input">Tipos de <input></a>.</p> +</div> + +<p>Debido a que la apariéncia de un control de formulario puede ser algo distinta con respecto a unas especificaciones del diseñador, los desarrolladores web a veces construyen sus propios controles de formulario personalizados. Cubrimos este aspecto en un tutorial avanzado: <a href="/en-US/docs/Learn/Forms/How_to_build_custom_form_widgets">Cómo construir widgets de formulario personalizados</a>.</p> + +<h2 id="Campo_de_dirección_de_correo_electrónico">Campo de dirección de correo electrónico</h2> + +<p>Este tipo de campo se define utilizando el valor <code>email</code> en el atributo {{htmlattrxref("type","input")}} del elemento <input>:</p> + +<pre class="brush: html notranslate"><input type="email" id="email" name="email"></pre> + +<p>Cuando se utiliza este valor {{htmlattrxref("type","input")}} , se le obliga al usuario a escribir dentro del campo una dirección de correo electrónico válida. Cualquier otro contenido ocasiona que el navegador muestre un mensaje de error cuando se envía el formulario. Puedes verlo en acción en la siguiente captura de pantalla</p> + +<p><img alt='An invalid email input showing the message "Please enter an email address."' src="https://mdn.mozillademos.org/files/17027/email_address_invalid.png" style="display: block; height: 224px; margin: 0 auto; width: 369px;"></p> + +<p>Puedes utilizar también el atributo <a href="/en-US/docs/Web/HTML/Attributes/multiple"><code>multiple</code></a> en combinación con el tipo input<code>email</code> para permitir que sean introducidas varias direcciones de correo electrónico separadas por comas en el mismo input:</p> + +<pre class="brush: html notranslate"><input type="email" id="email" name="email" multiple></pre> + +<p>En algunos dispositivos, en particular dispositivos táctiles con teclados dinámicos como los smart phones, debería presentarse un teclado virtual que es más adecuado para introducir direcciones de correo electrónico, incluyendo la tecla <code>@</code>. Mira como ejemplo la siguiente captura de pantalla del teclado de Firefox para Android:</p> + +<p><img alt="firefox for android email keyboard, with ampersand displayed by default." src="https://mdn.mozillademos.org/files/17054/fx-android-email-type-keyboard.jpg" style="border-style: solid; border-width: 1px; display: block; height: 324px; margin: 0 auto; width: 400px;"></p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes encontrar ejemplos sobre los tipos de entrada de texto básicos en <a href="https://mdn.github.io/learning-area/html/forms/basic-input-examples/">Ejemplos input básicos</a> (Consulta también el <a href="https://github.com/mdn/learning-area/blob/master/html/forms/basic-input-examples/index.html">código fuente</a>).</p> +</div> + +<p>Mejorar la experiéncia del usuario para usuarios con estos dispositivos, es otra buena razón para utilizar estos tipos de input más recientes.</p> + +<h3 id="Validación_del_lado_cliente">Validación del lado cliente</h3> + +<p>Como puedes haber visto anteriormente, <code>email</code>, junto con otros tipos de <code>input</code> más recientes, proporciona la validación de errores <em>en el lado cliente</em> de forma predeterminada, realizados por el navegador antes de que los datos obtenidos se envíen al servidor. <em>Es</em> una ayuda útil guiar a los usuarios a rellenar un formulario de forma precisa y puede ahorrar tiempo: es útil saber de inmediato que tu dato no es correcto, en vez de tener que esperar el viaje de ida y vuelta al servidor.</p> + +<p>Pero <em>no debería ser considerado</em> una medida de seguridad exhaustiva! Tus aplicaciones siempre deben realizar comprobaciones de seguridad en cada dato, tanto en el <em>lado servidor</em> como en el lado cliente debido a que la validación en el lado cliente es muy fácil desactivarla, por lo que usuarios malintencionados pueden enviar fácilmente datos incorrectos al servidor. Lee <a href="/en-US/docs/Learn/Server-side/First_steps/Website_security">Seguridad en el sitio web</a> para tener una idea de lo que <em>podría</em> ocurrir; Implementar validación en el lado servidor está más allá del alcance de este módulo-guía, pero debería tenerlo en cuenta.</p> + +<p>Ten en cuenta que <code>a@b</code> es una dirección de correo electrónico válida de acuerdo a las restricciones proporcionadaas por defecto. Esto es debido a que el tipo de input <code>email</code>, permite por defecto direcciones de correo electrónico de una intranet. Para implementar un comportamiento diferente de validación puedes utilizar el atributo <code><a href="/en-US/docs/Web/HTML/Attributes/pattern">pattern</a></code>, y también puedes utilizar mensajes de error personalizados; Hablaremos de cómo utilizar estas características en <a href="/en-US/docs/Learn/Forms/Form_validation">Validación de formularios en el lado cliente</a> en un artículo posterior.</p> + +<div class="note"> +<p><strong>Nota</strong>: Si los datos introducidos no son una dirección de correo electrónico, habrá coincidéncia con la pseudo clase {{cssxref(':invalid')}}, y la propiedad {{domxref('validityState.typeMismatch')}} devolverá <code>true</code>.</p> +</div> + +<h2 id="Campo_de_búsqueda">Campo de búsqueda</h2> + +<p>Los campos de búsqueda están destinados a ser utilizados para crear cajas de búsqueda en páginas y aplicaciones. Este tipo de campo se define utilizando el valor <code>search</code> en su atributo {{htmlattrxref("type","input")}}:</p> + +<pre class="brush: html notranslate"><input type="search" id="search" name="search"></pre> + +<p>La diferéncia principal entre un campo <code>text</code> y un campo <code>search</code>, es la forma en que el navegador aplica estilo a su apariéncia. A menudo los campos <code>search</code> se muestran con bordes redondeados; y a veces también muestran una "Ⓧ", el cual despeja el campo de cualquier valor cuando se pulsa sobre él. Adicionalmente, en dispositivos con teclado dinámico, la tecla enter del teclado puede leer "<strong>search</strong>" o mostrar un icono de lupa.</p> + +<p>La captura de pantalla siguiente muestra un campo de búsqueda con contenido, en Firefox 71, Safari 13, y Chrome 79 en macOS, y Edge 18 y Chrome 79 en Windows 10. Ten en cuenta que el icono de reseteo sólo aparece si el campo tiene un valor y, aparte de Safari, sólo se muestra cuando el campo tiene el foco.</p> + +<p><img alt="Screenshots of search fields on several platforms." src="https://mdn.mozillademos.org/files/17028/search_focus.png" style="height: 179px; width: 549px;"></p> + +<p>Otra característica que vale la pena señalar es que se puede guardar los valores de un campo <code>search</code> automáticamente y reutilizarse en múltiples páginas del mismo sitio web para ofrecer autocompletado. Esta característica suele ocurrir de forma automática en la mayoría de navegadores modernos.</p> + +<h2 id="Campo_número_de_teléfono">Campo número de teléfono</h2> + +<p>Se puede crear un campo especial para introducir números de teléfono utilizando <code>tel</code> como valor del atributo {{htmlattrxref("type","input")}}:</p> + +<pre class="brush: html notranslate"><input type="tel" id="tel" name="tel"></pre> + +<p>Cuando se accede desde un dispositivo táctil con teclados dinámicos, muchos de ellos mostrarán un teclado numérico cuando se encuentren con <code>type="tel"</code>, lo que significa que este tipo es útil no sólo para ser utilizado para números de teléfono, sino también cuando sea útil un teclado numérico.</p> + +<p>La siguiente captura de pantalla del teclado de Firefox para Android proporciona un ejemplo:</p> + +<p><img alt="firefox for android email keyboard, with ampersand displayed by default." src="https://mdn.mozillademos.org/files/17056/fx-android-tel-type-keyboard.jpg" style="border-style: solid; border-width: 1px; display: block; height: 276px; margin: 0px auto; width: 400px;"></p> + +<p>Debido a la gran variedad de formatos de número de teléfono existentes, este tipo de campo no cumple con ningún tipo de restricción sobre el valor introducido por el usuario. (Esto significa que puede incluir letras, etc...).</p> + +<p>Como mencionamos anteriormente, se puede utilizar el atributo <code><a href="/en-US/docs/Web/HTML/Attributes/pattern">pattern</a></code> para que asuma restricciones, sobre el cuál aprenderemos en <a href="/en-US/docs/Learn/Forms/Form_validation">Validación de formulario en el lado cliente</a>.</p> + +<h2 id="Campo_URL">Campo URL</h2> + +<p>Se puede crear un tipo especial de campo para introducir URLs utilizando el valor <code>url</code> para el atributo {{htmlattrxref("type","input")}}:</p> + +<pre class="brush: html notranslate"><input type="url" id="url" name="url"></pre> + +<p>Este tipo añade restricciones de validación en el campo. El navegador informará de un error si no se introdujo el protocolo (como <code>http:</code>), o si de algún modo el URL está mal formado. En dispositivos con teclados dinámicos a menudo mostrará por defecto algunas o todas las teclas como los dos puntos, el punto, y la barra inclinada.</p> + +<p>Mira el siguiente ejemplo tomado de Firefox para Android:</p> + +<p><img alt="firefox for android email keyboard, with ampersand displayed by default." src="https://mdn.mozillademos.org/files/17057/fx-android-url-type-keyboard.jpg" style="border-style: solid; border-width: 1px; display: block; height: 325px; margin: 0px auto; width: 400px;"></p> + +<div class="note"><strong>Nota:</strong> Solo porque el URL esté bien formado no significa necesariamente que la dirección al que hace referéncia exista!</div> + +<h2 id="Campo_numérico">Campo numérico</h2> + +<p>Se pueden crear controles para introducir números con el {{htmlattrxref("type","input")}} <code>number</code> de {{HTMLElement("input")}}. Este control se parece a un campo de texto pero solo permite números de punto flotante, y normalmente proporciona botones deslizadores para incrementar o reducir el valor del control. En dispositivos con teclados dinámicos generalmente se muestra el teclado numérico.</p> + +<p>La siguiente captura de pantalla tomada de Firefox para Android proporciona un ejemplo:</p> + +<p><img alt="firefox for android email keyboard, with ampersand displayed by default." src="https://mdn.mozillademos.org/files/17055/fx-android-number-type-keyboard.jpg" style="border-style: solid; border-width: 1px; display: block; height: 275px; margin: 0px auto; width: 400px;"></p> + +<p>Con el tipo de input <code>number</code> puedes limitar los valores mínimo y máximo permitidos definiendo los atributos {{htmlattrxref("min","input")}} y {{htmlattrxref("max","input")}}.</p> + +<p>También puedes utilizar el atributo <code>step</code> para cambiar el incremento y decremento causado por los botones deslizadores. Por defecto, el tipo de input number sólo valida si el número es un entero. Para permitir números decimales, especifica <code><a href="/en-US/docs/Web/HTML/Attributes/step">step="any"</a></code>. Si se omite, su valor por defecto es <code>1</code>, lo que significa que solo son válidos números enteros.</p> + +<p>Miremos algunos ejemplos. El primero de los siguientes crea un control numérico cuyo valor está restringido a cualquier valor entre <code>1</code> y <code>10</code>, y sus botones cambian su valor en incrementos o decrementos de <code>2</code>.</p> + +<pre class="brush: html notranslate"><input type="number" name="age" id="age" min="1" max="10" step="2"></pre> + +<p>El segundo crea un control numérico cuyo valor está restringido a cualquier valor entre el <code>0</code> y <code>1</code> ambos inclusive, y sus botones cambian su valor en incrementos o decrementos de <code>0.01</code>.</p> + +<pre class="brush: html notranslate"><input type="number" name="change" id="pennies" min="0" max="1" step="0.01"></pre> + +<p>El tipo de input <code>number</code> tiene sentido cuando esté limitado el rango de valores válidos, por ejemplo la edad de una persona o su altura. Si el rango es demasiado grande para que los cambios de incremento tengan sentido ( por ejemplo los códigos postales de USA, cuyo rango va de <code>00001</code> a <code>99999</code>), entonces sería una mejor opción utilizar el tipo <code>tel</code>: proporciona el teclado numérico mientras que omite el componente de interfaz de usuario de los deslizadores de número.</p> + +<div class="blockIndicator note"> +<p><strong>Ten en cuenta que</strong>: En versiones inferiores a la 10 de Internet Explorer no se soportan las entradas <code>number</code></p> +</div> + +<h2 id="Slider_controls">Slider controls</h2> + +<p>Otra forma de tomar un número es usando un <strong>slider</strong>. Podrás observar cómo son bastantes parecidas a los sitios inmobiliarios, dónde quieres determinar un máximo de precio por propiedad y filtrar tu búsqueda en el. Observaremos un ejemplo en vivo.</p> + +<p>{{EmbedGHLiveSample("learning-area/html/forms/range-example/index.html", '100%', 200)}}</p> + +<p>Usage-wise, sliders are less accurate than text fields. Therefore, they are used to pick a number whose <em>precise</em> value is not necessarily important.</p> + +<p>A slider is created using the {{HTMLElement("input")}} with its {{htmlattrxref("type","input")}} attribute set to the value <code>range</code>. The slider-thumb can be moved via mouse or touch, or with the arrows of the keypad.</p> + +<p>It's important to properly configure your slider. To that end, it's highly recommended that you set the <code><a href="/en-US/docs/Web/HTML/Attributes/min">min</a></code>, <code><a href="/en-US/docs/Web/HTML/Attributes/max">max</a></code>, and <code><a href="/en-US/docs/Web/HTML/Attributes/step">step</a></code> attributes which set the minimum, maximum and increment values, respectively.</p> + +<p>Let's look at the code behind the above example, so you can see how its done. First of all, the basic HTML:</p> + +<pre class="brush: html notranslate"><label for="price">Choose a maximum house price: </label> +<input type="range" name="price" id="price" min="50000" max="500000" step="100" value="250000"> +<output class="price-output" for="price"></output></pre> + +<p>This example creates a slider whose value may range between <code>50000</code> and <code>500000</code>, which increments/decrements by 100 at a time. We've given it default value of <code>250000</code>, using the <code>value</code> attribute.</p> + +<p>One problem with sliders is that they don't offer any kind of visual feedback as to what the current value is. This is why we've included an {{htmlelement("output")}} element — to contain the current value (we'll also look at this element in the next article). You could display an input value or the output of a calculation inside any element, but <code><output></code> is special — like <code><label></code>, it can take a <code>for</code> attribute that allows you to associate it with the element or elements that the output value came from.</p> + +<p>To actually display the current value, and update it as it changed, you must use JavaScript, but this is relatively easy to do:</p> + +<pre class="brush: js notranslate">const price = document.querySelector('#price') +const output = document.querySelector('.price-output') + +output.textContent = price.value + +price.addEventListener('input', function() { + output.textContent = price.value +});</pre> + +<p>Here we store references to the <code>range</code> input and the <code>output</code> in two variables. Then we immediately set the <code>output</code>'s <code><a href="/en-US/docs/Web/API/Node/textContent">textContent</a></code> to the current <code>value</code> of the input. Finally, an event listener is set to ensure that whenever the range slider is moved, the <code>output</code>'s <code>textContent</code> is updated to the new value.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: <code>range</code> inputs are not supported in versions of Internet Explorer below 10.</p> +</div> + +<h2 id="Date_and_time_pickers">Date and time pickers</h2> + +<p>Gathering date and time values has traditionally been a nightmare for web developers. For good user experience, it is important to provide a calendar selection UI, enabling users to select dates without necessating context switching to a native calendar application or potentially entering them in differing formats that are hard to parse. The last minute of the previous millenium can be expressed in the following different ways, for example: 1999/12/31, 23:59 or 12/31/99T11:59PM.</p> + +<p>HTML date controls are available to handle this specific kind of data, providing calendar widgets and making the data uniform.</p> + +<p>A date and time control is created using the {{HTMLElement("input")}} element and an appropriate value for the {{htmlattrxref("type","input")}} attribute, depending on whether you wish to collect dates, times, or both. Here's a live example that falls back to {{htmlelement("select")}} elements in non-supporting browsers:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/forms/datetime-local-picker-fallback/index.html", '100%', 200)}}</p> + +<p>Let's look at the different available types in brief. Note that the usage of these types is quite complex, especially considering browser support (see below); to find out the full details, follow the links below to the reference pages for each type, including detailed examples.</p> + +<h3 id="datetime-local"><code>datetime-local</code></h3> + +<p><code><a href="/en-US/docs/Web/HTML/Element/input/datetime-local"><input type="datetime-local"></a></code> creates a widget to display and pick a date with time with no specific time zone information.</p> + +<pre class="brush: html notranslate"><input type="datetime-local" name="datetime" id="datetime"></pre> + +<h3 id="month"><code>month</code></h3> + +<p><code><a href="/en-US/docs/Web/HTML/Element/input/month"><input type="month"></a></code> creates a widget to display and pick a month with a year.</p> + +<pre class="brush: html notranslate"><input type="month" name="month" id="month"></pre> + +<h3 id="time"><code>time</code></h3> + +<p><code><a href="/en-US/docs/Web/HTML/Element/input/time"><input type="time"></a></code> creates a widget to display and pick a time value. While time may <em>display</em> in 12-hour format, the <em>value returned</em> is in 24-hour format.</p> + +<pre class="brush: html notranslate"><input type="time" name="time" id="time"></pre> + +<h3 id="week"><code>week</code></h3> + +<p><code><a href="/en-US/docs/Web/HTML/Element/input/week"><input type="week"></a></code> creates a widget to display and pick a week number and its year.</p> + +<p>Weeks start on Monday and run to Sunday. Additionally, the first week 1 of each year contains the first Thursday of that year—which may not include the first day of the year, or may include the last few days of the previous year.</p> + +<pre class="brush: html notranslate"><input type="week" name="week" id="week"></pre> + +<h3 id="Constraining_datetime_values">Constraining date/time values</h3> + +<p>All date and time controls can be constrained using the <code><a href="/en-US/docs/Web/HTML/Attributes/min">min</a></code> and <code><a href="/en-US/docs/Web/HTML/Attributes/max">max</a></code> attributes, with further constraining possible via the <code><a href="/en-US/docs/Web/HTML/Attributes/step">step</a></code> attribute (whose value varies according to input type).</p> + +<pre class="brush: html notranslate"><label for="myDate">When are you available this summer?</label> +<input type="date" name="myDate" min="2013-06-01" max="2013-08-31" step="7" id="myDate"></pre> + +<h3 id="Browser_support_for_datetime_inputs">Browser support for date/time inputs</h3> + +<p>You should be warned that the date and time widgets don't have the best browser support. At the moment, Chrome, Edge, and Opera support them well, but there is no support in Internet Explorer, Safari has some mobile support (but no desktop support), and Firefox supports <code>time</code> and <code>date</code> only.</p> + +<p>The reference pages linked to above provide suggestions on how to program fallbacks for non-supporting browsers; another option is to consider using a JavaScript library to provide a date picker. Most modern frameworks have good components available to provide this functionality, and there are standalone libraries available to (see <a href="https://flatlogic.com/blog/best-javascript-date-picker-libraries/">Top date picker javascript plugins and libraries</a> for some suggestions).</p> + +<h2 id="Color_picker_control">Color picker control</h2> + +<p>Colors are always a bit difficult to handle. There are many ways to express them: RGB values (decimal or hexadecimal), HSL values, keywords, etc.</p> + +<p>A <code>color</code> control can be created using the {{HTMLElement("input")}} element with its {{htmlattrxref("type","input")}} attribute set to the value <code>color</code>:</p> + +<pre class="brush: html notranslate"><input type="color" name="color" id="color"></pre> + +<p>When supported, clicking a color control will tend to display the operating system's default color picking functionality for you to actually make your choice with. The following screenshot taken on Firefox for macOS provides an example:</p> + +<p><img alt="firefox for android email keyboard, with ampersand displayed by default." src="https://mdn.mozillademos.org/files/17058/fx-macos-color.jpg" style="border-style: solid; border-width: 1px; display: block; height: 412px; margin: 0px auto; width: 700px;"></p> + +<p>And here is a live example for you to try out:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/forms/color-example/index.html", '100%', 200)}}</p> + +<p>The value returned is always a lowercase 6-value hexidecimal color.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: <code>color</code> inputs are not supported in Internet Explorer.</p> +</div> + +<h2 id="Summary">Summary</h2> + +<p>That brings us to the end of our tour of the HTML5 form input types. There are a few other control types that cannot be easily grouped together due to their very specific behaviors, but which are still essential to know about. We cover those in the next article.</p> + +<p>{{PreviousMenuNext("Learn/Forms/Basic_native_form_controls", "Learn/Forms/Other_form_controls", "Learn/Forms")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Forms/Your_first_form">Your first form</a></li> + <li><a href="/en-US/docs/Learn/Forms/How_to_structure_a_web_form">How to structure a web form</a></li> + <li><a href="/en-US/docs/Learn/Forms/Basic_native_form_controls">Basic native form controls</a></li> + <li><a href="/en-US/docs/Learn/Forms/HTML5_input_types">The HTML5 input types</a></li> + <li><a href="/en-US/docs/Learn/Forms/Other_form_controls">Other form controls</a></li> + <li><a href="/en-US/docs/Learn/Forms/Styling_web_forms">Styling web forms</a></li> + <li><a href="/en-US/docs/Learn/Forms/Advanced_form_styling">Advanced form styling</a></li> + <li><a href="/en-US/docs/Learn/Forms/UI_pseudo-classes">UI pseudo-classes</a></li> + <li><a href="/en-US/docs/Learn/Forms/Form_validation">Client-side form validation</a></li> + <li><a href="/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data">Sending form data</a></li> +</ul> + +<h3 id="Advanced_Topics">Advanced Topics</h3> + +<ul> + <li><a href="/en-US/docs/Learn/Forms/How_to_build_custom_form_controls">How to build custom form controls</a></li> + <li><a href="/en-US/docs/Learn/Forms/Sending_forms_through_JavaScript">Sending forms through JavaScript</a></li> + <li><a href="/en-US/docs/Learn/Forms/Property_compatibility_table_for_form_widgets">Property compatibility table for form widgets</a></li> +</ul> diff --git a/files/es/learn/forms/index.html b/files/es/learn/forms/index.html new file mode 100644 index 0000000000..a0e77ec827 --- /dev/null +++ b/files/es/learn/forms/index.html @@ -0,0 +1,118 @@ +--- +title: Formularios en HTML5 +slug: HTML/HTML5/Forms_in_HTML5 +tags: + - Forms + - HTML + - HTML5 +--- +<p>{{ gecko_minversion_header("2") }}</p> + +<p>Los elementos y atributos para formularios en HTML5 proveen un mayor grado de marcado semántico que en HTML4 y eliminan gran parte del tedioso trabajo de programar y diseñar que se necesitaba en HTML4. Las funcionalidades de los formularios en HTML5 brindan una experiencia mejor para los usuarios al permitir que los formularios tengan un comportamiento más consistente entre diferentes sitios web y al darle una devolución inmediata acerca de la información ingresada. También proveen esta experiencia a los usuarios que han deshabilitado javascript en sus navegadores.</p> + +<p>Este documento describe los elementos nuevos o que han cambiado que están disponibles en Gecko/Firefox.</p> + +<h3 id="El_elemento_<input>">El elemento <code><input></code></h3> + +<p>El elemento <code>{{ HTMLElement("input") }}</code> tiene nuevos valores para el atributo {{ htmlattrxref("type", "input") }}.</p> + +<ul> + <li><span style="font-family: courier new;">search</span>: El elemento representa una caja de búsqueda. Los saltos de línea son quitados del valor ingresado pero no se modifica ninguna otra sintaxis.</li> + <li><span style="font-family: courier new;">tel</span>: El elemento representa un control para editar un número de teléfono, porque los números teléfonicos varían ampliamente en el mundo. Puedes usar atributos como {{ htmlattrxref("pattern", "input") }} y {{ htmlattrxref("maxlength", "input") }} para restringir los valores ingresados en la caja.</li> + <li><span style="font-family: courier new;">url</span>: El elemento representa un control para editar una <a class="external" href="http://es.wikipedia.org/URL" title="http://es.wikipedia.org/URL">URL</a>. Se quitan los saltos de línea y espacios en blanco antes y después del valor ingresados.</li> + <li> + <p><span style="font-family: courier new;">email</span>: El elemento representa una dirección de correo electrónico. Los saltos de línea se quitan automáticamente del valor ingresado. Puede ingresarse una direccón de correo no válida, pero el campo de ingreso sólo funcionará si la dirección ingresada satisface la producción ABNF <span style="font-family: courier new;"><code><code title="">1*( atext / "." ) "@" ldh-str 1*( "." ldh-str )</code></code></span> donde <code title="">atext</code> está definida en RFC 5322, sección 3.2.3 y <code title="">ldh-str</code> está definida en RFC 1034, sección 3.5.</p> + + <div class="note">Nota: si el atributo {{ htmlattrxref("multiple", "input") }} está agregado, pueden ingresarse muchas direcciones de correo electrónico en ese campo {{ HTMLElement("input") }}, como una lista separada por espacios, pero no está implementado actualmente en Firefox.</div> + </li> +</ul> + +<p>El elemento {{ HTMLElement("input") }} también tiene nuevos atributos:</p> + +<ul> + <li>{{ htmlattrxref("list", "input") }}: El ID de un elemento {{ HTMLElement("datalist") }} cuyo contenido, los elementos {{ HTMLElement("option") }}, van a ser usados como ayudas y serán mostrados como propuestas en el área de sugerencias del campo input.</li> + <li>{{ htmlattrxref("pattern", "input") }}: Una expresión regular contra la que es verificado el valor del control, que puede ser usada con valores de {{ htmlattrxref("type", "input") }} de <code>text</code>, <code>tel</code>, <code>search</code>, <code>url</code> y <code>email</code>.</li> + <li>{{ htmlattrxref("formmethod", "input") }}: Una cadena que indica qué método HTTP (GET, POST, PUT o DELETE) debe ser usado cuando se envía; sobrescribe el {{ htmlattrxref("method", "form") }} del elemento {{ HTMLElement("form") }}, si se define. El {{ htmlattrxref("formmethod", "input") }} sólo se aplica cuando el {{ htmlattrxref("type", "input") }} es <span style="font-family: courier new;">image</span> o <span style="font-family: courier new;">submit</span>, y, para los métodos PUT y DELETE, sólo funcionará con un destino que esté en el mismo dominio (política del mismo origen).</li> +</ul> + +<h3 id="El_elemento_<form>">El elemento <code><form></code></h3> + +<p>El elemento {{ HTMLElement("form") }} tiene un nuevo atributo:</p> + +<ul> + <li>{{ htmlattrxref("novalidate", "form") }}: Este atributo previene que el formulario sea validado antes del envío.</li> +</ul> + +<h3 id="El_elemento_<datalist>">El elemento <code><datalist> </code></h3> + +<p>El elemento {{ HTMLElement("datalist") }} representa la lista de elementos {{ HTMLElement("option") }} como sugerencias cuando se llena un campo {{ HTMLElement("input") }}.</p> + +<p>Puedes usar el atributo {{ htmlattrxref("list", "input") }} en un elemento {{ HTMLElement("input") }} para enlazar a un campo de ingreso específico con un elemento {{ HTMLElement("datalist") }} determinado.</p> + +<pre><label>Superhéroe favorito</label> +<input list="superheroes" name="list" /> +<datalist id="superheroes"> + <option label="Iron Man" value="Iron Man"> + <option label="The Hulk" value="The Hulk"> +</datalist> +</pre> + +<h3 id="El_elemento_<output>">El elemento <code><output></code></h3> + +<p>El elemento <code>{{ HTMLElement("output") }}</code> representa el resultado de un cálculo.</p> + +<p>Puedes usar el atributo {{ htmlattrxref("for", "output") }} para especificar una relación entre el elemento output y otros elementos en el documento que afectan el cálculo (por ejemplo, ingreso de datos o parámetros). El valor del atributo {{ htmlattrxref("for", "output") }} es una lista separada por espacios de IDs de otros elementos.</p> + +<h3 id="El_atributo_placeholder">El atributo placeholder</h3> + +<p>El atributo {{ htmlattrxref("placeholder", "input") }} en elementos <code>{{ HTMLElement("input") }}</code> y <code>{{ HTMLElement("textarea") }}</code> provee una ayuda a los usuarios acerca de qué debe ser ingresado en el campo. El texto introducido en el placeholder no debe contener «enters» o saltos de línea.</p> + +<pre><input type="email" id="user-email" placeholder="e.g. john.doe@mozilla.com" required/> +</pre> + +<h3 id="El_atributo_autofocus">El atributo autofocus</h3> + +<p>El atributo <strong>autofocus</strong> te permite especificar que una parte del formulario debe tener foco para ingresar información cuando se carga la página, a menos que el usuario lo cambie, por ejemplo al escribir en otro lugar. Sólo un elemento del formulario en un documento puede tener el atributo <strong>autofocus</strong>, que es de tipo boolean. Este atributo puede ser aplicado a los elementos <code>{{ HTMLElement("input") }}</code>, <code>{{ HTMLElement("button") }}</code>, <code>{{ HTMLElement("select") }}</code> y <code>{{ HTMLElement("textarea") }}</code>. La excepción es que <strong>autofocus</strong> no puede ser aplicado a un elemento <code><input></code> si el atributo {{ htmlattrxref("type", "input") }} <code>hidden</code> está seleccionado (esto quiere decir, no se puede enfocar automáticamente un elemento escondido).</p> + +<pre><input type="text" id="user" autofocus /> +</pre> + +<h3 id="La_propiedad_label.control_del_DOM">La propiedad label.control del DOM</h3> + +<p>La interface <a href="/en/DOM/HTMLLabelElement" title="en/DOM/HTMLLabelElement">HTMLLabelElement</a> DOM brinda una propiedad extra, sumadas a las propiedades que corresponden a los atributos del elemento <code>{{ HTMLElement("label") }}</code> de HTML. La propiedad <strong>control</strong> devuelve el controlador etiquetado, es decir el controlador para quien está hecha la etiqueta, que está determinado por el atributo {{ htmlattrxref("for", "label") }} (si está definido) o por el primer elemento controlador descendiente.</p> + +<h3 id="Validación_restringida">Validación restringida</h3> + +<p>El HTML5 brinda sintaxis y elementos de API para posibilitar la validación de formularios del lado del cliente. Aunque esta funcionalidad no reemplaza la validación del lado del servidor, que todavía es necesaria por seguridad e integridad de la información, la validación del lado del cliente puede brindar una experiencia de usuario mejor al darle al usuario una respuesta inmediata acerca de la información ingresada.</p> + +<h4 id="Sintaxis_de_HTML_para_la_validación_restringida">Sintaxis de HTML para la validación restringida</h4> + +<p>Los siguientes elementos de sintaxis de HTML5 pueden ser usados para restringir datos en el formulario.</p> + +<ul> + <li>El atributo {{ htmlattrxref("required", "input") }} en los elementos {{ HTMLElement("input") }}, {{ HTMLElement("select") }} y {{ HTMLElement("textarea") }} indica que se debe ingresar algún dato. (En el elemento {{ HTMLElement("input") }}, {{ htmlattrxref("required", "input") }} sólo se aplica con ciertos valores del atributo {{ htmlattrxref("type", "input") }}.)</li> + <li>El atributo {{ htmlattrxref("pattern", "input") }} en el elemento {{ HTMLElement("input") }} restringe el valor para que concuerde con una expresión regular específica.</li> + <li>Los atributos {{ htmlattrxref("min", "input") }} y {{ htmlattrxref("max", "input") }} del elemento {{ HTMLElement("input") }} restringen los valores máximos y mínimos que pueden ser ingresados.</li> + <li>El atributo {{ htmlattrxref("step", "input") }} del elemento {{ HTMLElement("input") }} (cuando se usa en combinación con los atributos {{ htmlattrxref("min", "input") }} y {{ htmlattrxref("max", "input") }}) restringe la granularidad de los valores ingresados. Un valor que no se corresponda con un valor permitido no será validado.</li> + <li>El atributo {{ htmlattrxref("maxlength", "input") }} de los elementos {{ HTMLElement("input") }} y {{ HTMLElement("textarea") }} restringe el máximo número de caracteres (en puntos de código unicode) que el usuario puede ingresar.</li> + <li>Los valores <code>url</code> y <code>email</code> para {{ htmlattrxref("type", "input") }} restringen el valor para una URL o dirección de correo válida respectivamente.</li> +</ul> + +<p>Además, puedes prevenir la validación restringida especificando el atributo {{ htmlattrxref("novalidate", "form") }} en el elemento {{ HTMLElement("form") }}, o el atributo {{ htmlattrxref("formnovalidate", "button") }} en el elemento {{ HTMLElement("button") }} y en el elemento {{ HTMLElement("input") }} (cuando {{ htmlattrxref("type", "input") }} es <code>submit</code> o <code>image</code>). Estos atributos indican que el formulario no será validado cuando se envie.</p> + +<h4 id="API_de_validación_restringida">API de validación restringida</h4> + +<p>Las siguientes propiedades y métodos del DOM relacionadas con la validación restringida están disponibles para scripts del lado del cliente:</p> + +<ul> + <li>En objetos <a href="/en/DOM/HTMLFormElement" title="en/DOM/HTMLFormElement">HTMLFormElement</a>, el método <code>checkValidity()</code>, que devuelve verdadero si todos los elementos asociados del formulario que necesitan validación satisfacen las restricciones y falso si no lo hacen.</li> + <li>En <a href="/en/HTML/Content_categories#form-associated" title="en/HTML/Content Categories#form-associated">elementos asociados al formulario</a>: + <ul> + <li>la propiedad <code>willValidate</code>, que es falso si el elemento no satisface las restricciones.</li> + <li>la propiedad <code>validity</code>, que es un objeto <a href="/en/DOM/ValidityState_Interface" title="en/DOM/ValidityState Interface">ValidityState</a> que representa los estados de validación en que está el elemento (p.e., condiciones de restricción que han fallado o exitosas).</li> + <li>la propiedad <code>validationMessage</code>, que es un mensaje que contiene todas las fallas en las restricciones que pertenecen a ese elemento.</li> + <li>el método <code>checkValidity()</code>, que devuelve falso si el elemento falla en satisfacer alguna de las restricciones o verdadero si pasa lo contrario.</li> + <li>el método <code>setCustomValidity()</code>, que establece un mensaje de validación personalizado, permitiendo imponer y validad restricciones más allá de las que están predefinidas.</li> + </ul> + </li> +</ul> diff --git a/files/es/learn/forms/property_compatibility_table_for_form_controls/index.html b/files/es/learn/forms/property_compatibility_table_for_form_controls/index.html new file mode 100644 index 0000000000..115b5580fe --- /dev/null +++ b/files/es/learn/forms/property_compatibility_table_for_form_controls/index.html @@ -0,0 +1,2003 @@ +--- +title: Tabla de compatibilidad de propiedades CSS para controles de formulario +slug: Learn/HTML/Forms/Property_compatibility_table_for_form_controls +translation_of: Learn/Forms/Property_compatibility_table_for_form_controls +--- +<div>{{learnsidebar}}</div> + +<p class="summary">Las siguientes tablas de compatibilidad intentan resumir el estado del soporte de CSS para formularios HTML. Debido a la complejidad de los formularios CSS y HTML, estas tablas no se pueden considerar una referencia perfecta. Sin embargo, le darán una buena idea de lo que se puede y no se puede hacer, lo que le ayudará al aprender a hacer las cosas.</p> + +<h2 id="Cómo_leer_las_tablas">Cómo leer las tablas</h2> + +<h3 id="Valores">Valores</h3> + +<p>Para cada propiedad, hay cuatro valores posibles:</p> + +<dl> + <dt>Si</dt> + <dd>Existe un soporte razonablemente consistente para la propiedad en todos los navegadores. Es posible que aún enfrente efectos secundarios extraños en ciertos casos extremos.</dd> + <dt>Parcial</dt> + <dd>Si bien la propiedad funciona, con frecuencia puede enfrentar efectos secundarios extraños o inconsistencias. Probablemente debería evitar estas propiedades a menos que primero domine esos efectos secundarios.</dd> + <dt>No</dt> + <dd>La propiedad simplemente no funciona o es tan inconsistente que no es confiable.</dd> + <dt>n.a.</dt> + <dd>La propiedad no tiene ningún significado para este tipo de widget.</dd> +</dl> + +<h3 id="Representación">Representación</h3> + +<p>Para cada propiedad hay dos representaciones posibles:</p> + +<dl> + <dt>N (Normal)</dt> + <dd>Indica que la propiedad se aplica tal cual</dd> + <dt>T (Retocada)</dt> + <dd>Indica que la propiedad se aplica con la regla adicional como se muestra a continuación:</dd> +</dl> + +<pre class="brush: css notranslate">* { + /* Turn off the native look and feel */ + -webkit-appearance: none; + appearance: none; + +/* for Internet Explorer */ + background: none; +}</pre> + +<h2 id="Tablas_de_compatibilidad">Tablas de compatibilidad</h2> + +<h3 id="Comportamientos_globales">Comportamientos globales</h3> + +<p>Algunos comportamientos son comunes a muchos navegadores a nivel global::</p> + +<dl> + <dt>{{cssxref("border")}}, {{cssxref("background")}}, {{cssxref("border-radius")}}, {{cssxref("height")}}</dt> + <dd>El uso de una de estas propiedades puede desactivar parcial o totalmente la apariencia nativa de los widgets en algunos navegadores. Tenga cuidado cuando los use.</dd> + <dt>{{cssxref("line-height")}}</dt> + <dd>Esta propiedad se admite de forma inconsistente en todos los navegadores y debe evitarla.</dd> + <dt>{{cssxref("text-decoration")}}</dt> + <dd>Esta propiedad no es compatible con el navegador Opera en widgets de formulario.</dd> + <dt>{{cssxref("text-overflow")}}</dt> + <dd>Opera, Safari, y IE9 no admiten esta propiedad en widgets de formulario.</dd> + <dt>{{cssxref("text-shadow")}}</dt> + <dd>Opera no admite {{cssxref("text-shadow")}} en widgets de formularios e IE9 no lo admite en absoluto.</dd> +</dl> + +<h3 id="Text_fields">Text fields</h3> + +<p>See the <code>{{htmlelement("input/text", "text")}}</code>, <code>{{htmlelement("input/search", "search")}}</code>, and <code>{{htmlelement("input/password", "password")}}</code> input types.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>WebKit browsers (mostly on Mac OSX and iOS) use the native look & feel for the search fields. Therefore, it's required to use <code>-webkit-appearance:none</code> to be able to apply this property to search fields.</li> + <li>On Windows 7, Internet Explorer 9 does not apply the border unless <code>background:none</code> is applied.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>WebKit browsers (mostly on Mac OSX and iOS) use the native look & feel for the search fields. Therefore, it's required to use <code>-webkit-appearance:none</code> to be able to apply this property to search fields.</li> + <li>On Windows 7, Internet Explorer 9 does not apply the border unless <code>background:none</code> is applied.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>WebKit browsers (mostly on Mac OSX and iOS) use the native look & feel for the search fields. Therefore, it's required to use <code>-webkit-appearance:none</code> to be able to apply this property to search fields.</li> + <li>On Windows 7, Internet Explorer 9 does not apply the border unless <code>background:none</code> is applied.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}<sup>[1]</sup></th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>If the {{cssxref("border-color")}} property is not set, some WebKit based browsers will apply the {{cssxref("color")}} property to the border as well as the font on <code>{{htmlelement("textarea")}}</code>s.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td>See the note about {{cssxref("line-height")}}</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td>See the note about Opera</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 supports this property only on <code>{{htmlelement("textarea")}}</code>s, whereas Opera only supports it on single line text fields.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>WebKit browsers (mostly on Mac OSX and iOS) use the native look & feel for the search fields. Therefore, it's required to use <code>-webkit-appearance:none</code> to be able to apply this property to search fields. On Windows 7, Internet Explorer 9 does not apply the border unless <code>background:none</code> is applied.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>WebKit browsers (mostly on Mac OSX and iOS) use the native look & feel for the search fields. Therefore, it's required to use <code>-webkit-appearance:none</code> to be able to apply this property to search fields. On Windows 7, Internet Explorer 9 does not apply the border unless <code>background:none</code> is applied.</li> + <li>On Opera the {{cssxref("border-radius")}} property is applied only if an explicit border is set.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 does not support this property.</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<h3 id="Buttons">Buttons</h3> + +<p>See the <code>{{htmlelement("input/button", "button")}}</code>, <code>{{htmlelement("input/submit", "submit")}}</code>, and <code>{{htmlelement("input/reset", "reset")}}</code> input types and the <code>{{htmlelement("button")}}</code> element.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>This property is not applied on WebKit based browsers on Mac OSX or iOS.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>This property is not applied on WebKit based browsers on Mac OSX or iOS.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td>See the note about {{cssxref("line-height")}}.</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes<sup>[1]</sup></td> + <td> + <ol> + <li>On Opera the {{cssxref("border-radius")}} property is applied only if an explicit border is set.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 does not support this property.</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<h3 id="Number">Number</h3> + +<p>See the <code>{{htmlelement("input/number", "number")}}</code> input type. There is no standard way to change the style of spinners used to change the value of the field, with the spinners on Safari being outside the field.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>On Opera, the spinners are zoomed in, which can hide the content of the field.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>On Opera, the spinners are zoomed in, which can hide the content of the field.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td>See the note about {{cssxref("line-height")}}.</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td colspan="1" rowspan="3"> + <p>Supported but there is too much inconsistency between browsers to be reliable.</p> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + </tr> + </tbody> +</table> + +<h3 id="Check_boxes_and_radio_buttons">Check boxes and radio buttons</h3> + +<p>See the <code>{{htmlelement("input/checkbox", "checkbox")}}</code> and <code>{{htmlelement("input/radio", "radio")}}</code> input types.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>Some browsers add extra margins and others stretch the widget.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>Some browsers add extra margins and others stretch the widget.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Select_boxes_single_line">Select boxes (single line)</h3> + +<p>See the <code>{{htmlelement("select")}}</code>, <code>{{htmlelement("optgroup")}}</code> and <code>{{htmlelement("option")}}</code> elements.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>This property is okay on the <code>{{htmlelement("select")}}</code> element, but it cannot be the case on the <code>{{htmlelement("option")}}</code> or <code>{{htmlelement("optgroup")}}</code> elements.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[2]</sup></td> + <td> + <ol> + <li>The property is applied, but in an inconsistent way between browsers on Mac OSX.</li> + <li>The property is well applied on the <code>{{htmlelement("select")}}</code> element, but is inconsistently handled on <code>{{htmlelement("option")}}</code> and <code>{{htmlelement("optgroup")}}</code> elements.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>On Mac OSX, WebKit based browsers do not support this property on native widgets and they, along with Opera, do not support it at all on <code>{{htmlelement("option")}}</code> and <code>{{htmlelement("optgroup")}}</code> elements.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>On Mac OSX, WebKit based browsers do not support this property on native widgets and they, along with Opera, do not support it at all on <code>{{htmlelement("option")}}</code> and <code>{{htmlelement("optgroup")}}</code> elements.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 does not support this property on <code>{{htmlelement("select")}}</code>, <code>{{htmlelement("option")}}</code>, and <code>{{htmlelement("optgroup")}}</code> elements; WebKit based browsers on Mac OSX do not support this property on <code>{{htmlelement("option")}}</code> and <code>{{htmlelement("optgroup")}}</code> elements.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 on Windows 7 and WebKit based browsers on Mac OSX do not support this property on this widget.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>Only Firefox provides full support for this property. Opera does not support this property at all and other browsers only support it on the <code>{{htmlelement("select")}}</code> element.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td> + <ol> + <li>Most of the browsers only support this property on the <code>{{htmlelement("select")}}</code> element.</li> + <li>IE9 does not support this property.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td> + <ol> + <li>Most of the browsers only support this property on the <code>{{htmlelement("select")}}</code> element.</li> + <li>IE9 does not support this property.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>Most of the browsers only support this property on the <code>{{htmlelement("select")}}</code> element.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td colspan="1" rowspan="3"> + <ol> + <li>Most of the browsers only support this property on the <code>{{htmlelement("select")}}</code> element.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + </tr> + </tbody> +</table> + +<p>Note Firefox does not provide any way to change the down arrow on the <code>{{htmlelement("select")}}</code> element.</p> + +<h3 id="Select_boxes_multiline">Select boxes (multiline)</h3> + +<p>See the <code>{{htmlelement("select")}}</code>, <code>{{htmlelement("optgroup")}}</code> and <code>{{htmlelement("option")}}</code> elements and the <a href="/en-US/docs/Web/HTML/Attributes/size"><code>size</code> attribute</a>.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>Opera does not support {{cssxref("padding-top")}} and {{cssxref("padding-bottom")}} on the <code>{{htmlelement("select")}}</code> element.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td>See the note about {{cssxref("line-height")}}.</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 does not support this property on <code>{{htmlelement("select")}}</code>, <code>{{htmlelement("option")}}</code>, and <code>{{htmlelement("optgroup")}}</code> elements; WebKit based browsers on Mac OSX do not support this property on <code>{{htmlelement("option")}}</code> and <code>{{htmlelement("optgroup")}}</code> elements.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 on Windows 7 and WebKit based browser on Mac OSX do not support this property on this widget.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>Only supported by Firefox and IE9+.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>Most of the browsers only support this property on the <code>{{htmlelement("select")}}</code> element.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes<sup>[1]</sup></td> + <td> + <ol> + <li>On Opera the {{cssxref("border-radius")}} property is applied only if an explicit border is set.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 does not support this property.</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<h3 id="Datalist">Datalist</h3> + +<p>See the <code>{{htmlelement("datalist")}}</code> and <code>{{htmlelement("input")}}</code> elements and the <a href="/en-US/docs/Web/HTML/Attributes/list"><code>list</code> attribute</a>.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="File_picker">File picker</h3> + +<p>See the <code>{{htmlelement("input/file", "file")}}</code> input type.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>Supported, but there is too much inconsistency between browsers to be reliable.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>Many browsers apply this property to the select button.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>It acts more or less like an extra left margin outside the widget.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>Supported, but there is too much inconsistency between browsers to be reliable.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 does not support this property.</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<h3 id="Date_pickers">Date pickers</h3> + +<p>See the <code>{{htmlelement("input/date", "date")}}</code> and <code>{{htmlelement("input/time", "time")}}</code> input types. Many properties are supported, but there is too much inconstency between browsers to be reliable.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Color_pickers">Color pickers</h3> + +<p>See the <code>{{htmlelement("input/color", "color")}}</code> input type:</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>Opera handles this like a select widget with the same restriction.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>Opera handles this like a select widget with the same restriction.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td colspan="1" rowspan="3"> + <ol> + <li>Supported, but there is too much inconsistency between browsers to be reliable.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + </tbody> +</table> + +<h3 id="Meters_and_progress">Meters and progress</h3> + +<p>See the <code>{{htmlelement("meter")}}</code> and <code>{{htmlelement("progress")}}</code> elements:</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>Chrome hides the <code>{{htmlelement("progress")}}</code> and <code>{{htmlelement("meter")}}</code> element when the {{cssxref("padding")}} property is applied on a tweaked element.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td colspan="1" rowspan="3"> + <ol> + <li>Supported, but there is too much inconsistency between browsers to be reliable.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + </tbody> +</table> + +<h3 id="Range">Range</h3> + +<p>See the <code>{{htmlelement("input/range", "range")}}</code> input type. There is no standard way to change the style of the range grip and Opera has no way to tweak the default rendering of the range widget.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>Chrome and Opera add some extra space around the widget, whereas Opera on Windows 7 stretches the range grip.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>The {{cssxref("padding")}} is applied, but has no visual effect.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td colspan="1" rowspan="3"> + <ol> + <li>Supported, but there is too much inconsistency between browsers to be reliable.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + </tbody> +</table> + +<h3 id="Image_buttons">Image buttons</h3> + +<p>See the <code>{{htmlelement("input/image", "image")}}</code> input type:</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td colspan="1"></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td colspan="1"> + <ol> + <li>IE9 does not support this property.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td colspan="1"> + <ol> + <li>IE9 does not support this property.</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<h2 id="See_also">See also</h2> + +<h3 id="Learning_path">Learning path</h3> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Forms/Your_first_HTML_form">Your first HTML form</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">How to structure an HTML form</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/The_native_form_widgets">The native form widgets</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/HTML5_input_types">HTML5 input types</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Additional_form_controls">Additional form controls</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/UI_pseudo-classes">UI pseudo-classes</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Styling_HTML_forms">Styling HTML forms</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Form_validation">Form data validation</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Sending form data</a></li> +</ul> + +<h3 id="Advanced_Topics">Advanced Topics</h3> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript">Sending forms through JavaScript</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets">How to build custom form widgets</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/HTML_forms_in_legacy_browsers">HTML forms in legacy browsers</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Advanced_styling_for_HTML_forms">Advanced styling for HTML forms</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Property_compatibility_table_for_form_widgets">Property compatibility table for form widgets</a></li> +</ul> diff --git a/files/es/learn/forms/sending_and_retrieving_form_data/index.html b/files/es/learn/forms/sending_and_retrieving_form_data/index.html new file mode 100644 index 0000000000..d6ca2161a4 --- /dev/null +++ b/files/es/learn/forms/sending_and_retrieving_form_data/index.html @@ -0,0 +1,328 @@ +--- +title: Sending form data +slug: Learn/HTML/Forms/Sending_and_retrieving_form_data +translation_of: Learn/Forms/Sending_and_retrieving_form_data +--- +<div>{{LearnSidebar}} {{PreviousMenuNext("Aprende / HTML / Formularios / The_native_form_widgets", "Aprender / html / Formularios / Form_validation", "Aprender / html / Forms")}}</div> + +<p class="summary">En este artículo se analiza lo que sucede cuando un usuario envía un formulario - ¿A dónde van los datos y cómo los manejamos cuando llegan allí? - También tenemos en cuenta algunos de los problemas de seguridad asociados con el envío de los datos del formulario.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Requisitos previos:</th> + <td>Conocimientos básicos de informática, una <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">comprensión de HTML</a> , y conocimientos básicos de <a href="/en-US/docs/Web/HTTP/Basics_of_HTTP">HTTP</a> y <a href="/en-US/docs/Learn/Server-side/First_steps">programación del lado del servidor</a> .</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Para entender lo que sucede cuando se envía los datos del formulario, incluyendo la obtención de una idea básica de cómo se procesan los datos en el servidor</td> + </tr> + </tbody> +</table> + +<h2 id="¿A_dónde_van_los_datos">¿A dónde van los datos?</h2> + +<p>Aquí vamos a discutir lo que ocurre con los datos cuando se envía un formulario.</p> + +<h3 id="Sobre_la_arquitectura_cliente_servidor">Sobre la arquitectura cliente / servidor</h3> + +<p>La web se basa en una arquitectura cliente / servidor muy básica que se puede resumir de la siguiente manera: un cliente (normalmente un navegador Web) envía una petición a un servidor (la mayoría de las veces un servidor web como <a href="http://httpd.apache.org/" rel="external" title="http://www.apache.org/">Apache</a> , <a href="http://nginx.com/" rel="external" title="http://nginx.com/">Nginx</a> , <a href="http://www.iis.net/" rel="external" title="http://www.iis.net/">IIS</a> , <a href="http://tomcat.apache.org/" rel="external" title="http://tomcat.apache.org/">Tomcat</a> , etc.), utilizando el <a href="/en-US/docs/HTTP" title="/en-US/docs/HTTP">protocolo HTTP</a> . El servidor responde a la solicitud utilizando el mismo protocolo.</p> + +<p><img alt="Un esquema básico de la arquitectura cliente Web / servidor" src="/files/4291/client-server.png" style="display: block; height: 141px; margin: 0px auto; width: 400px;"></p> + +<p>En el lado del cliente, un formulario HTML no es más que una manera fácil de usar conveniente para configurar una petición HTTP para enviar datos a un servidor. Esto permite al usuario para proporcionar información a ser entregada en la petición HTTP.</p> + +<div class="note"> +<p><strong>Nota</strong> : Para tener una mejor idea de cómo funcionan las arquitecturas cliente-servidor, lea nuestra <a href="/en-US/docs/Learn/Server-side/First_steps">programación de páginas web del lado del servidor, módulo: primeros pasos</a>. En el lado del cliente: Debes definir como envías los datos.</p> +</div> + +<p>El elemento {{HTMLElement ( "form")}} define cómo se enviarán los datos. Todos sus atributos están diseñados para que pueda configurar la solicitud que se enviará cuando un usuario pulsa un botón de envío. Los dos atributos más importantes son {{htmlattrxref ( "acción", "forma")}} y {{htmlattrxref ( "método", "forma")}}.</p> + +<h4 id="El_atributo_htmlattrxref_acción_forma.">El atributo {{htmlattrxref ( "acción", "forma")}}.</h4> + +<p>Este atributo define el lugar donde los datos se envian. Su valor debe ser una dirección URL válida. Si no se proporciona este atributo, los datos serán enviados a la dirección URL de la página que contiene el formulario.</p> + +<p>En este ejemplo, los datos se envían a una dirección URL absoluta - <code>http://foo.com</code>:</p> + +<pre class="brush: html"><Acción del formulario = "http://foo.com"></pre> + +<p class="brush: html">Aquí, nosotros usamos una URL relativa - los datos se envían a una dirección URL diferente en el servidor:</p> + +<pre class="brush: html"><Acción del formulario = "/ somewhere_else"></pre> + +<p class="brush: html">Cuando se especifica sin atributos, como abajo, el {{HTMLElement ( "form")}} los datos se envían a la misma página en que la "forma" está presente :</p> + +<pre class="brush: html"><Form></pre> + +<p class="brush: html">Muchas páginas más antiguas utilizan la siguiente notación para indicar que los datos deben ser enviados a la misma página que contiene el formulario; Esto fue necesario porque hasta HTML5, el atributo {{htmlattrxref ( "acción", "form")}} fue requerido . Esto ya no es necesario.</p> + +<pre class="brush: html"><Form action = "#"></pre> + +<div class="note"> +<p><strong>Nota:</strong> Es posible especificar una dirección URL que utiliza el protocolo HTTPS (HTTP seguro). Al hacer esto, los datos se cifran junto con el resto de la solicitud, incluso si el propio formulario está alojado en una página insegura se accede a través de HTTPS. Por otro lado, si el formulario está alojado en una página segura, pero se especifica una dirección URL HTTP insegura con el atributo {{htmlattrxref ( "acción", "form")}} , todos los navegadores mostrarán una advertencia de seguridad para el usuario cada vez que intenten enviar datos, ya que estos no se pueden cifrar.</p> +</div> + +<h4 id="El_atributo_htmlattrxref_método_form">El atributo {{htmlattrxref ( "método", "form")}}</h4> + +<p>Este atributo define cómo se envían los datos. El <a href="/en-US/docs/HTTP" title="/en-US/docs/HTTP">protocolo HTTP</a> proporciona varias formas de realizar una solicitud; Los datos del formulario HTML se pueden transmitir a través de un número de diferentes queridos, los más comunes de los cuales son el método <code>GET</code> y el método <code>POST</code>.</p> + +<p>Para entender la diferencia entre estos dos métodos, vamos a dar un paso atrás y examinar cómo funciona HTTP. Cada vez que desee llegar a un recurso en la Web, el navegador envía una petición a una URL. Una petición HTTP consta de dos partes: un encabezado que contiene un conjunto de metadatos mundial sobre las capacidades del navegador, y un cuerpo que puede contener la información necesaria paraque el servidor pueda procesar la petición específica.</p> + +<h5 id="El_método_GET">El método GET</h5> + +<p>El método <code>GET</code> es utilizado por el navegador para pedir al servidor que se envíe de vuelta un recurso dado: "Hey servidor, quiero conseguir este recurso." En este caso, el navegador envía un cuerpo vacío. Debido a que el cuerpo está vacío, si un formulario se envía utilizando este método, los datos enviados al servidor se anexan a la URL.</p> + +<p>Considere la siguiente forma:</p> + +<pre class="brush: html"><form action="http://foo.com" method="get"> + <div> + <label for="decir"> ¿Qué saludo quiere decir? </label> + <input name="decir" id="decir" value="Hola"> + </div> + <div> + <label for="para"> ¿A quién se lo quiere decir? </label> + <input name="para" value="mamá"> + </div> + <div> + <button> Botón enviar mis saludos </ button> + </div> +</form></pre> + +<p>Dado que el método <code>GET</code>ha conseguido el recurso, verá en la URL lo siguiente en la barra de direcciones del navegador <code>www.foo.com/?say=Hi&to=Mom</code> cuando se envía el formulario.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14685/url-parameters.png" style="display: block; margin: 0 auto;">Los datos se añaden a la URL como una serie de pares de nombre / valor. Después que la dirección web URL ha terminado, se incluye un signo de interrogación ( <code>?</code>) seguido de los pares de nombre / valor, cada uno separado por un signo ( <code>&</code>). En este caso estamos pasando dos piezas de datos en el servidor:</p> + +<ul> + <li><code>say</code>, Que tiene un valor de <code>Hi</code></li> + <li><code>to</code>, Que tiene un valor de <code>Mom</code></li> +</ul> + +<p>La solicitud HTTP se ve así:</p> + +<pre>GET /? = Decir Hola & a = mamá HTTP / 1.1 +Anfitrión: foo.com</pre> + +<div class="note"> +<p><strong>Nota</strong> : Puede encontrar este ejemplo en GitHub - ver <a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/get-method.html">llegar-method.html</a> ( <a href="https://mdn.github.io/learning-area/html/forms/sending-form-data/get-method.html">verlo en directo también</a> ).</p> +</div> + +<h5 id="El_método_POST">El método POST</h5> + +<p>El <code>POST</code>método es un poco diferente. Es el método que el navegador utiliza para comunicarse con el servidor cuando se pide una respuesta que tenga en cuenta los datos proporcionados en el cuerpo de la petición HTTP: "Hey servidor, echa un vistazo a estos datos y envíame de vuelta un resultado apropiado." Si un formulario se envía utilizando este método, los datos se anexan al cuerpo de la petición HTTP.</p> + +<p>Veamos un ejemplo - se trata de algo similar a como se vió en el método <code>GET</code>del apartado anterior, pero con el {{htmlattrxref ( "método", "form")}} atributo establecido <code>post</code>.</p> + +<pre class="brush: html"><Form action = "http://foo.com" method = "post"> + <Div> + <Label for = "dice"> Lo saludo qué quiere decir? </ Label> + <Input name = "decir" id = "decir" value = "Hola"> + </ Div> + <Div> + <Label for = "para"> ¿Quién usted quiere decir que a? </ Label> + <Input name = "a" value = "mamá"> + </ Div> + <Div> + <> Botón enviar mis saludos </ botón> + </ Div> +</ Form></pre> + +<p>Cuando el formulario se envía mediante el método <code>POST</code>, no se obtienen los datos adjuntos en la dirección URL, y la solicitud HTTP se parece a esto y los datos son incluidos en el cuerpo de la petición en su lugar:</p> + +<pre>POST / HTTP/1.1 +Anfitrión: foo.com +Content-Type: application / x-www-form-urlencoded +Content-Length: 13 + +decir = Hi & a = mamá</pre> + +<p>La cabecera <code>Content-Length</code> indica el tamaño del cuerpo, y la cabecera <code>Content-Type</code> indica el tipo de recurso que se envía al servidor. Discutiremos estas cabeceras más adelante.</p> + +<div class="note"> +<p><strong>Nota</strong> : Puede encontrar este ejemplo en GitHub - ver <a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/post-method.html">post-method.html</a> ( <a href="https://mdn.github.io/learning-area/html/forms/sending-form-data/post-method.html">verlo en directo también</a> ).</p> +</div> + +<h4 id="Visualización_de_peticiones_HTTP">Visualización de peticiones HTTP</h4> + +<p>Las peticiones HTTP nunca se muestran al usuario (si quieres verlos, es necesario utilizar herramientas como el <a href="/en-US/docs/Tools/Network_Monitor">Monitor de red Firefox</a> o las <a href="https://developers.google.com/chrome-developer-tools/" title="https://developers.google.com/chrome-developer-tools/">herramientas de desarrollo de Chrome</a> ). A modo de ejemplo, los datos del formulario se muestran a continuación en la pestaña de Chrome red:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14691/network-monitor.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<p>Lo único que se muestra al usuario es la dirección URL llamada. Como mencionamos anteriormente, con una petición<code>GET</code> del usuario,se verán los datos en su barra de direcciones, pero con una petición <code>POST</code> no será de esta manera. Esto puede ser muy importante por dos razones:</p> + +<ol> + <li>Si necesita enviar una contraseña (o cualquier otra pieza sensible de los datos), nunca utilice el método<code>GET</code> o se arriesga a mostrar en la barra de direcciones, lo que sería muy inseguro.</li> + <li>Si necesita enviar una gran cantidad de datos, el método <code>POSt</code> es preferible debido a que algunos navegadores limitan los tamaños de las direcciones URL. Además, muchos servidores limitan la longitud de las URL que aceptan.</li> +</ol> + +<h3 id="En_el_lado_Servidor_la_recuperación_de_los_datos">En el lado Servidor: la recuperación de los datos</h3> + +<p>Sea cual sea el método HTTP que elija, el servidor recibe una cadena que será analizada con el fin de obtener los datos como una lista de pares clave / valor. La forma de acceder a esta lista depende de la plataforma de desarrollo que use y de las estructuras específicas que pueda estar usando con él. La tecnología se utiliza también determina cómo se manejan claves duplicadas; A menudo,se da prioridad al valor recibido más recientemente para una clave dada .</p> + +<h4 id="Ejemplo_PHP_Raw">Ejemplo: PHP Raw</h4> + +<p><a href="http://php.net/">PHP</a> ofrece algunos objetos globales para acceder a los datos. Suponiendo que usted ha utilizado el método<code>POST</code>, el siguiente ejemplo sólo toma los datos y lo muestra al usuario. Por supuesto, lo que se hace con los datos depende de usted. Es posible visualizarlos, almacenarlos en una base de datos, enviarlos por correo electrónico, o procesarlos de alguna otra manera.</p> + +<pre class="brush: php"><? Php + // La variable global $ _POST que permite acceder a los datos enviados con el método POST por su nombre + // Para acceder a los datos enviados con el método GET, puede usar $ _GET + $ = Decir htmlspecialchars ($ _POST [ 'decir']); + $ A = htmlspecialchars ($ _POST [ 'a']); + + echo $ digamos, '', $ a; +?></pre> + +<p>Este ejemplo muestra una página con los datos que enviamos. Esto se puede ver en acción en nuestro archivo ejemplo <a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/php-example.html">php-example.html</a> - que contiene un ejemplo similar en forma como el que hemos visto antes, con un <code>method</code>con parámetro <code>post</code>y un <code>action</code> con parámetro <code>php-example.php</code> Cuando se envía, envía los datos del formulario al script <a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/php-example.php">php-ejemplo.php</a> , que contiene el código de PHP que se ha visto en el bloque anterior. Cuando se ejecuta este código, la salida en el navegador es <code>Hi Mom</code>.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14693/php-result.png" style="display: block; margin: 0 auto;"></p> + +<div class="note"> +<p><strong>Nota</strong> : Este ejemplo no funcionará cuando se carga en un navegador localmente - los navegadores no pueden interpretar código PHP, por lo que cuando se envía el formulario en el navegador sólo se puede ofrecer la descarga del archivo PHP para usted. Para conseguir que funcione, es necesario ejecutar el ejemplo a través de un servidor PHP de algún tipo. Buenas opciones para probar PHP locales son <a href="https://www.mamp.info/en/downloads/">MAMP</a> (Mac y Windows) y <a href="http://ampps.com/download">AMPPS</a> (Mac, Windows, Linux).</p> +</div> + +<h4 id="Ejemplo_Python">Ejemplo: Python</h4> + +<p>Este ejemplo muestra como se puede utilizar Python para hacer la misma cosa - mostrar los datos presentados en una página web. Se utiliza el <a href="http://flask.pocoo.org/">framework Flask</a> para la prestación de las plantillas, el manejo de la presentación de datos de formulario, etc (ver <a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/python-example.py">python-example.py</a> ).</p> + +<pre class="line-numbers language-html"><code class="language-html">from flask import Flask, render_template, request +app = Flask(__name__) + +@app.route('/', methods=['GET', 'POST']) +def form(): + return render_template('form.html') + +@app.route('/hello', methods=['GET', 'POST']) +def hello(): + return render_template('greeting.html', say=request.form['say'], to=request.form['to']) + +if __name__ == "__main__": + app.run()</code></pre> + +<p>Las dos plantillas de referencia en el código anterior son los siguientes:</p> + +<ul> + <li><a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/templates/form.html">form.html</a> : La misma forma que hemos visto anteriormente en la {{anch ( "El método POST")}} sección, pero con el <code>action</code>conjunto a <code>\{{ url_for('hello') }}</code>. (Esta es una <a href="http://jinja.pocoo.org/docs/2.9/">Jinja2</a> plantilla, que es básicamente HTML, pero puede contener llamadas al código Python que ejecuta el servidor web que figura entre corchetes. <code>url_for('hello')</code>Básicamente está diciendo "redirigir a <code>/hello</code>cuando se envía el formulario").</li> + <li><a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/templates/greeting.html">greeting.html</a> :<span id="result_box" lang="es"><span>Esta plantilla solo contiene una línea que representa los dos bits de datos que se le pasan cuando se procesa</span></span>. Esto se hace a través de la función <code>hello()</code>que se ha visto anteriormente, y que se ejecuta cuando la URL<code>/hello</code> es accedida.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong> : Una vez más, este código no funcionará si sólo intenta cargarlo en un navegador directamente. Python funciona un poco diferente a PHP - Para ejecutar este código local que necesita para <a href="/en-US/docs/Learn/Server-side/Django/development_environment#Installing_Python_3">instalar Python / PIP</a> , a continuación, instalar el frasco utilizando <code>pip3 install flask</code>. En este punto, usted debe ser capaz de ejecutar el ejemplo utilizando <code>python3 python-example.py</code>, a continuación, deberá navegar a <code>localhost:5000</code>en su barra de direcciones.</p> +</div> + +<h4 id="Otros_lenguajes_y_frameworks">Otros lenguajes y frameworks</h4> + +<p>Hay muchas otras tecnologías del lado del servidor que puede utilizar para el manejo de formularios, incluyendo <a href="/en-US/docs/" title="/en-US/docs/">Perl</a> , <a href="/en-US/docs/" title="/en-US/docs/">Java</a> , <a href="http://www.microsoft.com/net" title="http://www.microsoft.com/net">.Net</a> , <a href="/en-US/docs/" title="/en-US/docs/">Rubí</a> , etc. Sólo tiene que elegir el que más le guste. Dicho esto, vale la pena señalar que es muy raro de usar estas tecnologías directamente porque esto puede ser complicado. Es más común el uso de uno de los muchos marcos de trabajo para un manejo más fácil del código, tales como:</p> + +<ul> + <li><a href="http://symfony.com/" rel="external" title="http://symfony.com/">Symfony</a> para PHP</li> + <li><a href="/en-US/docs/Learn/Server-side/Django" rel="external" title="https://www.djangoproject.com/">Django</a> para Python (un poco más pesado que el <a href="http://flask.pocoo.org/">frasco</a> , pero con más herramientas y opciones).</li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs">Express</a> de Node.js</li> + <li><a href="http://rubyonrails.org/" rel="external" title="http://rubyonrails.org/">Ruby on Rails</a> Ruby</li> + <li><a href="http://grails.org/" rel="external" title="http://grails.org/">Grails</a> para Java</li> + <li>etc.</li> +</ul> + +<p>Vale la pena señalar que incluso el uso de estos marcos, trabajar con formularios no es necesariamente <em>fácil</em> . Pero es mucho más fácil que tratar de escribir toda la funcionalidad a partir de cero, además, le ahorrará mucho tiempo.</p> + +<div class="note"> +<p><strong>Nota</strong> : Está más allá del alcance de este artículo para enseñarle cualquier lenguaje del lado del servidor o marcos de trabajo. Los enlaces de arriba le dará un poco de ayuda,en caso de que desee aprender.</p> +</div> + +<h2 id="Un_caso_especial_el_envío_de_archivos">Un caso especial: el envío de archivos</h2> + +<p>El envío de archivos con formularios HTML es un caso especial. Los archivos son datos binarios - o considerados como tal - mientras que todos los demás datos son datos de texto. Debido a que HTTP es un protocolo de texto, existen requisitos especiales para el manejo de datos binarios.</p> + +<h3 id="El_htmlattrxref_enctype_form_atributo">El {{htmlattrxref ( "enctype", "form")}} atributo</h3> + +<p>Este atributo le permite especificar el valor de la cabecera <code>Content-Type</code> HTTP incluido en la solicitud que se genera cuando se envía el formulario. Esta cabecera es muy importante porque le dice al servidor qué tipo de datos se está enviando. Por defecto, su valor es <code>application/x-www-form-urlencoded</code>. En términos humanos, esto significa: "<span class="short_text" id="result_box" lang="es"><span>Estos son datos de formulario que han sido codificados dentro de los parámetros de la URL</span></span>."</p> + +<p>Si desea enviar archivos, es necesario tomar tres pasos adicionales:</p> + +<ul> + <li>Ajuste el {{htmlattrxref ( "método", "form")}} atributo <code>POST</code>porque el contenido del archivo no se puede poner dentro de los parámetros de URL.</li> + <li>Establecer el valor de {{htmlattrxref ( "enctype", "form")}} que <code>multipart/form-data</code>debido a que los datos se dividen en múltiples partes, una para cada archivo más uno para los datos de texto incluidos en el cuerpo del formulario (si también se introduce el texto en la formulario).</li> + <li>Incluir uno o más widgets <a href="/en-US/docs/Learn/HTML/Forms/The_native_form_widgets#File_picker">selector de archivos</a> para permitir a los usuarios seleccionar el archivo (s) que será subido.</li> +</ul> + +<p>Por ejemplo:</p> + +<pre class="brush: html"><Form method = "post" enctype = "multipart / form-data"> + <Div> + <Label for = "archivo"> Elija un archivo </ label> + <Input type = "file" id = "file" name = "myFile"> + </ Div> + <Div> + <> Botón Enviar el archivo </ botón> + </ Div> +</ Form></pre> + +<div class="note"> +<p><strong>Nota:</strong> Algunos navegadores son compatibles con la {{htmlattrxref ( "múltiple", "input")}} atributo en el elemento {{HTMLElement ( "input")}}, lo que permite elegir más de un archivo para subir con un único elemento <code><input></code> . Cómo el servidor gestiona los archivos realmente depende de la tecnología utilizada en el servidor. Como se mencionó anteriormente, el uso de un marco le hará la vida mucho más fácil.</p> +</div> + +<div class="warning"> +<p><strong>Advertencia:</strong> Muchos servidores están configurados con un límite de tamaño para los archivos y las peticiones HTTP con el fin de prevenir el abuso. Es importante comprobar este límite con el administrador del servidor antes de enviar un archivo.</p> +</div> + +<h2 id="Precauciones_de_seguridad_comunes">Precauciones de seguridad comunes</h2> + +<p>Cada vez que envíe datos a un servidor, debe tener en cuenta la seguridad de sus formularios HTML que son con mucho, los vectores de ataque más comunes (en lugares donde ocurren los ataques contra servidores). Los problemas nunca vienen de los formulariosHTML mismos - sino que proceden de cómo el servidor maneja los datos.</p> + +<p><span id="result_box" lang="es"><span>Dependiendo de lo que estés haciendo, hay algunos problemas de seguridad muy conocidos con los que te enfrentarás</span></span>:</p> + +<h3 id="XSS_y_CSRF">XSS y CSRF</h3> + +<p>Cross-Site Scripting (XSS) y Cross-Site Request Falsification (CSRF) son tipos comunes de ataques que se producen cuando se muestran los datos enviados por un usuario y que son devueltos a otro usuario para otro uso.</p> + +<p>XSS permite a los atacantes inyectar secuencias de comandos del lado del cliente en páginas Web visitadas por otros usuarios. Una vulnerabilidad de secuencias de comandos entre sitios, puede ser utilizada por los atacantes para eludir los controles de acceso, como la <a href="/en-US/docs/JavaScript/Same_origin_policy_for_JavaScript" title="/ Es-ES / docs / JavaScript / Same_origin_policy_for_JavaScript">política del mismo origen</a> . El efecto de estos ataques pueden ir desde una pequeña molestia a un riesgo de seguridad.</p> + +<p>Los ataques CSRF son similares a los ataques XSS porque comienzan de la misma manera - mediante la inyección de comandos de cliente en páginas Web - pero su objetivo es diferente. Los atacantes CSRF tratan de escalar privilegios de un usuario de mayores privilegios (por ejemplo, un administrador de sitio) para realizar una acción que no deberían ser capaces de hacer (por ejemplo, el envío de datos a un usuario no fiable).</p> + +<p>Los ataques XSS explotan la confianza depositada a un usuario de un sitio web, mientras que los ataques CSRF abusan de la confianza que un sitio web ofrece para sus usuarios.</p> + +<p>Para evitar estos ataques, siempre se deben comprobar los datos que un usuario envía a su servidor y (si es necesario mostrarlos) <span id="result_box" lang="es"><span>trate de no mostrar el contenido HTML provisto por el usuario</span></span>. En su lugar, se deben procesar los datos proporcionados por el usuario para no mostrarlos al pie de la letra. <span style="line-height: 1.5;">Casi todos los marcos de trabajo (<strong>frameworks</strong>) en el mercado hoy implementan un filtro mínimo que eliminan el código HTML {{HTMLElement ( "script")}}, {{HTMLElement ( "iframe")}} y {{HTMLElement ( "objeto")}} si fuesen enviados por cualquier usuario. Esto ayuda a mitigar el riesgo, pero no necesariamente lo erradica.</span></p> + +<h3 id="Inyección_SQL">Inyección SQL</h3> + +<p>La inyección de SQL es un tipo de ataque que intenta realizar acciones en una base de datos utilizada por el sitio web de destino. Esto normalmente implica el envío de una petición SQL con la esperanza de que el servidor la ejecutará (por lo general cuando el servidor de aplicaciones intenta almacenar los datos enviados por un usuario). Esto es en realidad <a href="https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project" rel="external" title="https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project">uno de los principales vectores de ataque contra los sitios web </a> .</p> + +<p>Las consecuencias pueden ser terribles, que van desde la pérdida de datos o hasta que los ataques tomen el control de la infraestructura de todo el sitio web mediante el uso de una escalada de privilegios. Esta es una amenaza muy seria y nunca debe almacenar los datos enviados por un usuario sin realizar alguna sanitización (por ejemplo, mediante el uso <code><a href="http://www.php.net/manual/en/function.mysql-real-escape-string.php" rel="external" title="http://www.php.net/manual/en/function.mysql-real-escape-string.php">mysql_real_escape_string()</a></code>de una infraestructura de PHP / MySQL).</p> + +<h3 id="Inyección_de_cabecera_HTTP_y_la_inyección_de_correo_electrónico">Inyección de cabecera HTTP y la inyección de correo electrónico</h3> + +<p>Este tipo de ataques pueden ocurrir cuando su aplicación se basa cabeceras HTTP o mensajes de correo electrónico basado en la entrada de datos por un usuario en un formulario. Estos no dañan directamente su servidor o afectan a sus usuarios, pero son una puerta abierta a problemas más profundos tales como el secuestro de sesión o ataques de phishing.</p> + +<p>Estos ataques son en su mayoría en silencio, y pueden volver a su servidor en un <a href="http://en.wikipedia.org/wiki/Zombie_(computer_science)" rel="exernal" title="http://en.wikipedia.org/wiki/Zombie_(computer_science)">zombi</a> .</p> + +<h3 id="Sea_paranoico_Nunca_confíe_en_sus_usuarios">Sea paranoico: Nunca confíe en sus usuarios</h3> + +<p>Entonces, ¿cómo se lucha contra estas amenazas? Este es un tema mucho más allá de esta guía, pero hay algunas reglas a tener en cuenta. La regla más importante es: nunca vuelva a confiar en sus usuarios, incluyáse a sí mismo; incluso un usuario de confianza podría haber sido secuestrado.</p> + +<p>Todos los datos que vienen a su servidor deben comprobarse y ser desinfectados. Siempre. Sin excepción.</p> + +<ul> + <li>Escapar caracteres potencialmente peligrosos. Los caracteres específicos con los que debe tener cuidado variarán dependiendo del contexto en el que se utilizan los datos y la plataforma de servidores que emplean, pero todos los lenguajes del lado del servidor tienen funciones de este.</li> + <li>Limite la cantidad de entrada de datos para permitir sólo lo necesario.</li> + <li>Sandbox subido archivos (almacenarlos en un servidor diferente y permitir el acceso al archivo sólo a través de un subdominio diferente o incluso mejor a través de un nombre de dominio totalmente diferente).</li> +</ul> + +<p>Debería evitar muchos o la mayoría de estos problemas, si sigue estas tres reglas, pero siempre es una buena idea obtener una revisión de seguridad realizada por una tercera parte competente. No asuma que usted ha visto todos los posibles problemas.</p> + +<div class="note"> +<p><strong>Nota</strong> : La <a href="/en-US/docs/Learn/Server-side/First_steps/Website_security">seguridad del sitio web</a> el artículo de nuestro <a href="/en-US/docs/Learn/Server-side">lado del servidor</a> tema de aprendizaje analiza las amenazas anteriores y las posibles soluciones con más detalle.</p> +</div> + +<h2 id="Conclusión">Conclusión</h2> + +<p>Como se puede ver, el envío de los datos del formulario es fácil, pero asegurar una aplicación puede ser complicado. Sólo recuerde que un desarrollador de aplicaciones para usuario no es el que debe definir el modelo de seguridad de los datos. Sí, como veremos, es posible <a href="/en-US/docs/HTML/Forms/Data_form_validation" title="/ es-ES / docs / HTML / Formularios / Data_form_validation">realizar la validación de los datos del lado del cliente</a> , pero el servidor no puede confiar en esta validación porque no tiene manera de saber realmente lo que sucede en el lado del cliente.</p> + +<h2 id="Ver_también">Ver también</h2> + +<p>Si desea obtener más información sobre la seguridad de una aplicación web, se puede excavar en estos recursos:</p> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/First_steps">programación web del lado del servidor primeros pasos</a></li> + <li><a href="https://www.owasp.org/index.php/Main_Page" rel="external" title="https://www.owasp.org/index.php/Main_Page">El Proyecto Open Web Application Security (OWASP)</a></li> + <li><a href="http://shiflett.org/" rel="external" title="http://shiflett.org/">el blog de Chris Shiflett sobre Seguridad en PHP</a></li> +</ul> + +<p>{{PreviousMenuNext ( "Aprende / html / Formularios / The_native_form_widgets", "Saber / html / Formularios / Form_validation", "Aprender / html / Forms")}}</p> diff --git a/files/es/learn/forms/styling_web_forms/index.html b/files/es/learn/forms/styling_web_forms/index.html new file mode 100644 index 0000000000..26b4173ee8 --- /dev/null +++ b/files/es/learn/forms/styling_web_forms/index.html @@ -0,0 +1,345 @@ +--- +title: Estilizando formularios HTML +slug: Learn/HTML/Forms/Styling_HTML_forms +translation_of: Learn/Forms/Styling_web_forms +--- +<p>En este artículo aprenderemos como utilizar <a href="/es/docs/Web/CSS">CSS</a> con formularios <a href="/es/docs/Web/HTML">HTML</a> para hacerlos más atractivos. Aunque parezca extraño, esto es algo que puede llegar a ser complicado. Por razones históricas y técnicas, los widgets de formulario no suelen llevarse bien con CSS. Por este motivo, muchos desarrolladores prefieren <a href="https://developer.mozilla.org/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets">construir sus propios widgets</a> para tener el control de su aspecto en vez de utilizar los nativos. De todas formas, con los modernos navegadores, los diseñadores web <span style="line-height: 23.3333339691162px;">cada vez</span><span style="line-height: 1.5;"> tienen más control sobre el diseño de los elementos de formulario. Vamos a profundizar en esto.</span></p> + +<h2 id="¿Porqué_es_tan_difícil_aplicar_estilos_a_formularios_con_CSS">¿Porqué es tan difícil aplicar estilos a formularios con CSS?</h2> + +<p>En los principios de la Web —allá por1995—se añadieron los controles de formulario en la <a href="http://www.ietf.org/rfc/rfc1866.txt">2ª especificación HTML.</a> Debido a la complejidad de los widgets de formulario, los implementadores prefirieron dejar que el sistema operativo subyacente se encargara de su manejo y presentación.</p> + +<p>Pocos años después, se creó<span style="line-height: 23.3333339691162px;"> </span><span style="line-height: 1.5;">CSS y lo que era una necesidad técnica</span>— es decir, el uso de widgets nativos para implementar controles de formulario—empezó a requerir estilizado. Y en los primeros días de CSS, el estilizado de formularios no fué una prioridad.</p> + +<p>Por otra parte, como los usuarios estaban acostumbrados a la apariencia visual de sus plataformas respectivas, los fabricantes de navegadores fueron reacios a hacer que los controles de formularios pudieran recibir estilos.</p> + +<p>Hoy en día, ni siquiera uno solo de los navegadores actuales implementa <span style="line-height: 23.3333339691162px;">completamente</span><span style="line-height: 1.5;"> a CSS 2.1. Afortunadamente, con el tiempo, los fabricantes de navegadores han ido mejorado su soporte a CSS para los elementos de formulario e, incluso considerando que su usabilidad tiene mala reputación, actualmente, ya se puede usar CSS para estilizar </span><a href="https://developer.mozilla.org/en-US/docs/HTML/Forms" style="line-height: 1.5;">formularios HTML.</a></p> + +<h3 id="No_todos_los_widgets_se_crean_igual_con_CSS">No todos los widgets se crean igual con CSS</h3> + +<p>Actualmente aun se encuentran dificultades cuando se utiliza CSS con formularios; estos problemas se pueden dividir en tres categorías.</p> + +<h4 id="El_bueno">El bueno</h4> + +<p>A algunos elementos se les puede dar estilo con pocos o ningún problema independientemente de la plataforma. Entre estos se incluyen los siguientes elementos estructurales:</p> + +<ol> + <li>{{HTMLElement("form")}}</li> + <li>{{HTMLElement("fieldset")}}</li> + <li>{{HTMLElement("label")}}</li> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/output"><output></a></li> +</ol> + +<p style="line-height: 23.3333339691162px;">Esto también incluye todos los campos de texto (tanto los de línea simple como los de línea múltiple) y los botones.</p> + +<ol style="line-height: 23.3333339691162px;"> +</ol> + +<p style="line-height: 18px; font-size: 1.28571428571429rem;">El malo</p> + +<p>Hay otros elementos a los que raramente se les puede aplicar estilos y pueden llegar a requerir <span style="line-height: 23.3333339691162px;">técnicas</span><span style="line-height: 1.5;"> complejas y </span><span style="line-height: 1.5;">ocasionalmente necesitan conocimientos avanzados de CSS3.</span></p> + +<p>Entre estos se incluyen el elemento {{HTMLElement("legend")}} ; que no puede posicionarse adecuadamente en todas las plataformas. Los elementos checkbox y los botones de radio no permiten que se le apliquen estilos directamente; de todas formas, gracias a CSS3 esto puede soslayarse. Al contenido de <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-placeholder">placeholder </a>no se le puede aplicar estilo de ninguna forma convencional; sin embargo, todos los navegadores que lo implementan también implementan pseudo-elementos<span style="line-height: 23.3333339691162px;"> o </span><span style="line-height: 1.5;">pseud</span><span style="line-height: 1.5;">o-clases propi</span>etarias que permiten darles estilo<span style="line-height: 1.5;">.</span></p> + +<p><span style="line-height: 1.5;">Veremos como trabajar con estos casos específicos en el artículo </span><a href="/en-US/docs/Advanced_styling_for_HTML_forms" style="line-height: 23.3333339691162px;" title="/en-US/docs/Advanced_styling_for_HTML_forms">Advanced styling for HTML forms</a><span style="line-height: 23.3333339691162px;">.</span></p> + +<h4 id="El_feo">El feo</h4> + +<p>En algunos elementos, simplemente no se puede utilizar CSS. Estos son todos los elementos avanzados de interface de usuario tales como los controles range, color, o date, e igualmente pasa con los widgets desplegables como <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select">select</a>, <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option">option</a>, <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup">optgropup </a>y <a href="/es/docs/HTML/Elemento/datalist">datalist</a>. Respecto al selector de archivos, es bien sabido que no puede aplicarse estilo en absoluto. Los nuevos elementos <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress">progress </a>y <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meter">meter </a>también caen dentro de esta categoría.</p> + +<p>El principal problema con todos estos widgets viene de que todos ellos tienen una estructura muy compleja y CSS no es lo suficientemente expresivo para estilizar cada una de sus sutiles partes. Si lo que se quiere es personalizar estos widgets se deberá recurrir a javaScript para construir un árbol DOM que te permita acceder a ellos. Para aprender como conseguirlo mirar en el artículo <a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets" style="line-height: 23.3333339691162px; text-decoration: underline;" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets"><span style="line-height: 23.3333339691162px;"><u>How to </u></span>build<span style="line-height: 23.3333339691162px;"><u> </u></span>custom<span style="line-height: 23.3333339691162px;"><u> </u></span>form<span style="line-height: 23.3333339691162px;"><u> </u></span>widgets</a>.</p> + +<h2 id="Estilizado_básico">Estilizado básico</h2> + +<p>Aplicar estilos a <a href="https://developer.mozilla.org/es/docs/Web/Guide/HTML/Forms/Styling_HTML_forms#El_bueno">elementos que son fáciles de estilizar</a> con CSS, no debería suponer ninguna dificultad ya que básicamente se comportan como cualquier otro elemento HTML. De todas formas, el agente de usuario de estilos para cada navegador puede mostrar pequeñas inconsistencias por lo que a continuación daremos algunos trucos para ayudar a aplicar estilos más cómodamente.</p> + +<h3 id="Campos_de_búsqueda">Campos de búsqueda</h3> + +<p>Las cajas de búsqueda son el único tipo de campo de texto que pueden ofrecer más dificultad al aplicar estilos. En los navegadores basados en webkit (Chrome, Safari, etc.) se debe lidiar con la propiedad -webkit-. Discutiremos esta propiedad más tarde en el artículo: <a href="/en-US/docs/Advanced_styling_for_HTML_forms" style="line-height: 23.3333339691162px; text-decoration: underline;" title="/en-US/docs/Advanced_styling_for_HTML_forms">Advanced styling for HTML forms</a><span style="line-height: 23.3333339691162px;">.</span></p> + +<h4 id="Ejemplo">Ejemplo</h4> + +<pre class="brush: html"><form> + <input type="search"> +</form> +</pre> + +<pre class="brush: css">input[type=search] { + border: 1px dotted #999; + border-radius: 0; + + -webkit-appearance: none; +}</pre> + +<p><img alt="This is a screenshot of a search filed on Chrome, with and without the use of -webkit-appearance" src="/files/4153/search-chrome-macos.png" style="border-style: solid; border-width: 1px; height: 107px; width: 179px;"></p> + +<p>En esta captura de pantalla pueden verse dos campos de búsqueda en Chrome, ambos campos tienen definido el borde como en nuestro ejemplo, pero el primero no utiliza -webkit- mientras que el segundo si lo hace con -webkit-appearance:none. Las diferencias son evidentes.</p> + +<h3 id="Fuentes_y_texto">Fuentes y texto</h3> + +<p>Las fuentes y capacidades de texto de CSS se pueden utilizar sin problemas en cualquier widget (y sí, se puede utilizar <a href="/es/docs/Web/CSS/@font-face">@font-face</a> en formularios). De todas formas, el comportamiento de los navegadores no es siempre consistente. Por defecto, algunos widgets no heredan <a href="/es/docs/Web/CSS/font-family">font-family</a> ni <a href="/es/docs/Web/CSS/font-size">font-size</a> de sus antecesores. Y muchos navegadores utilizan la apariencia por defecto. Para mantener la coherencia de los formularios con el resto de elementos se deben añadir las siguientes reglas a la hoja de estilos:</p> + +<pre class="brush: css">button, input, select, textarea { + font-family : inherit; + font-size : 100%; +}</pre> + +<p>La siguiente captura de pantalla muestra estas incosistencias; a la izquierda la apariencia por defecto en Firefox sobre Mac OS X, usando las fuentes por defecto de la plataforma. A la derecha los mismos elementos aplicando nuestras reglas de armonización de fuentes.</p> + +<p><img alt="This is a screenshot of the main form widgets on Firefox on Mac OSX, with and without font harmonization" src="/files/4157/font-firefox-macos.png" style="border-style: solid; border-width: 1px; height: 234px; width: 420px;"></p> + +<p>Hay muchas controversia sobre si los formularios tienen mejor aspecto usando los estilos por defecto del sistema o usando estilos personalizados que coincidan con el resto del contenido. Como diseñador del sitio o aplicación Web esta decisión es suya.</p> + +<h3 id="Modelo_de_cajas">Modelo de cajas</h3> + +<p>Todos los campos de texto tienen soporte completo para las propiedades relacionadas con el modelo de cajas de CSS (<a href="/es/docs/Web/CSS/width">width</a>, <a href="/es/docs/Web/CSS/height">height</a>, <a href="/es/docs/Web/CSS/padding_paspartu">padding</a>, margin y <a href="/es/docs/CSS/border">border</a>). Igual que antes, los navegadores se remiten a los estilos por defecto del sistema cuando muestran estos widgets. A cada cual te corresponde el como combinarlos dentro del resto de contenido. Si se quieres mantener el aspecto nativo de los widgets, entonces hay que afrontar pequeñas inconsistencias de tamaño.</p> + +<p>Esto es porque cada widget tiene sus propias reglas para el orden, margen y padding. Por lo que si quieres darle el mismo tamaño a varios widgets diferentes se debe usar la propiedad box-sizing: </p> + +<pre class="brush: css">input, textarea, select, button { + width : 150px; + margin: 0; + + -webkit-box-sizing: border-box; /* For legacy WebKit based browsers */ + -moz-box-sizing: border-box; /* For legacy (Firefox <29) Gecko based browsers */ + box-sizing: border-box; +}</pre> + +<p><img alt="This is a screenshot of the main form widgets on Chrome on Windows 7, with and without the use of box-sizing." src="/files/4161/size-chrome-win7.png" style="border-style: solid; border-width: 1px; height: 213px; width: 358px;"></p> + +<p>En la captura de pantalla de arriba, la columna la izquierda es sin utilizar box-sizing, mientras que la de la derecha usa esta propiedad con el valor border-box. Obsérvese cómo esto permite asegurar que todos los elementos ocupan la misma cantidad de espacio, independientemente de las reglas por defecto de la plataforma.</p> + +<h3 id="Posicionado">Posicionado</h3> + +<p>El posicionado de formularios HTML <span style="line-height: 23.3333339691162px;">no es </span><span style="line-height: 1.5;">generalmente un problema; sin embargo, hay dos elementos a los que prestar una especial atención:</span></p> + +<h4 id="legend">legend</h4> + +<p>El elemento <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/legend">legend </a>no tiene problemas de estilizado a excepción de las reglas de posición. En los navegadores el elemento <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/legend">legend </a>se posiciona encima del borde superior de su antecesor <a href="/es/docs/HTML/Elemento/fieldset">fieldset</a>. No existe ninguna posibilidad de colocarlo dentro del flujo HTML más allá del borde superior. Sin embargo se puede posicionar de forma relativa o absoluta mediante la propiedad position. En cualquier caso sigue siendo parte del borde de fieldset.</p> + +<p>Debido a que el elemento legend es muy importante por razones de accesibilidad (esto es lo que leen las tecnologías de asistencia como parte de las etiquetas de cada elemento de formulario dentro del fieldset), bastante menudo se empareja con un título que se oculta pero siendo aun accesible, de la forma siguiente:</p> + +<h5 id="HTML">HTML</h5> + +<pre class="brush: html"><fieldset> + <legend>Hi!</legend> + <h1>Hello</h1> +</fieldset></pre> + +<h5 id="CSS">CSS</h5> + +<pre class="brush: css">legend { + width: 1px; + height: 1px; + overflow: hidden; +}</pre> + +<h4 id="textarea">textarea</h4> + +<p>Por defecto, todos los navegadores consideran el elemento <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea">textarea </a>como un inline block alineado con la línea base del texto. Esto es algo que raramente es lo que en realidad se quiere. Para convertir este elemento de un inline-block a uno tipo block, se realiza bastante fácilmente utilizando la propiedad <a href="/es/docs/CSS/display">display</a>. Si lo que quieres es utilizarlo inline, es corriente cambiar la alineación vertical: </p> + +<pre class="brush: css">textarea { + vertical-align: top; +}</pre> + +<h2 id="Ejemplo_2">Ejemplo</h2> + +<p>Vamos a ver un ejemplo de como aplicar estilo a un formulario HTML. Esto nos ayudará a tener las ideas más claras. A continuación construiremos el siguiente formulario de contacto de esta postal:</p> + +<p><img alt="This is what we want to achieve with HTML and CSS" src="/files/4149/screenshot.png" style="border-style: solid; border-width: 1px; height: 249px; width: 370px;"></p> + +<h3 id="HTML_2">HTML</h3> + +<p>El HTML incluye poco más de lo que se utiliza en el primer artículo de <a href="/en-US/docs/HTML/Forms/My_first_HTML_form">esta guía</a>; apenas el título y algún ID más.</p> + +<pre class="brush: html"><form> + <h1>to: Mozilla</h1> + + <div id="from"> + <label for="name">from:</label> + <input type="text" id="name" name="user_name"> + </div> + + <div id="reply"> + <label for="mail">reply:</label> + <input type="email" id="mail" name="user_email"> + </div> + + <div id="message"> + <label for="msg">Your message:</label> + <textarea id="msg" name="user_message"></textarea> + </div> + + <div class="button"> + <button type="submit">Send your message</button> + </div> +</form></pre> + +<h3 id="CSS_2">CSS</h3> + +<p>¿Aqui es donde empieza la diversión! Antes de empezar a codificar, necesitamos tres elementos adicionales:</p> + +<ol> + <li>El <a href="https://developer.mozilla.org/files/4151/background.jpg">fondo </a>de la postal</li> + <li>Una fuente tipográfica: <a href="http://www.fontsquirrel.com/fonts/Secret-Typewriter" rel="external" title="http://www.fontsquirrel.com/fonts/Secret-Typewriter">la "Secret Typewriter" de fontsquirrel.com</a></li> + <li>Una fuente manuscrita: <a href="http://www.fontsquirrel.com/fonts/Journal" rel="external" title="http://www.fontsquirrel.com/fonts/Journal">la "Journal" fde fontsquirrel.com</a></li> +</ol> + +<p>Ahora podemos repasar el código. Primero preparamos las bases definiendo las reglas <span style="line-height: 23.3333339691162px;"> </span><a href="https://developer.mozilla.org/es/docs/Web/CSS/@font-face" style="line-height: 23.3333339691162px;" title="@font-face permite al autor especificar fuentes online para visualizar en sus páginas web. Al permitir a los autores proporcionar sus propias fuentes, @font-face elimina la necesidad de depender del numero limitado de fuentes de usuarios instaladas en sus computadoras."><code>@font-face</code></a> y los elementos básicos de <a href="https://developer.mozilla.org/es/docs/Web/HTML/Elemento/body" style="line-height: 23.3333339691162px;" title="This article hasn't been written yet. Please consider contributing!"><code><body></code></a> y <a href="https://developer.mozilla.org/es/docs/Web/HTML/Elemento/form" style="line-height: 23.3333339691162px;" title="This article hasn't been written yet. Please consider contributing!"><code><form></code></a><span style="line-height: 23.3333339691162px;"> </span></p> + +<pre class="brush: css">@font-face{ + font-family : "handwriting"; + + src : url('journal.eot'); + src : url('journal.eot?') format('eot'), + url('journal.woff') format('woff'), + url('journal.ttf') format('truetype'); +} + +@font-face{ + font-family : "typewriter"; + + src : url('veteran_typewriter.eot'); + src : url('veteran_typewriter.eot?') format('eot'), + url('veteran_typewriter.woff') format('woff'), + url('veteran_typewriter.ttf') format('truetype'); +} + +body { + font : 21px sans-serif; + + padding : 2em; + margin : 0; + + background : #222; +} + +form { + position: relative; + + width : 740px; + height : 498px; + margin : 0 auto; + + background: #FFF url(background.jpg); +}</pre> + +<p>Ahora podemos posicionar los elementos, incluidos el título y los elementos del formulario.</p> + +<pre class="brush: css">h1 { + position : absolute; + left : 415px; + top : 185px; + + font : 1em "typewriter", sans-serif; +} + +#from { + position: absolute; + left : 398px; + top : 235px; +} + +#reply { + position: absolute; + left : 390px; + top : 285px; +} + +#message { + position: absolute; + left : 20px; + top : 70px; +}</pre> + +<p>Aquí es donde empezamos a trabajar los propios elementos. Primero, nos aseguramos que los elementos <span style="line-height: 23.3333339691162px;"> </span><a href="https://developer.mozilla.org/es/docs/Web/HTML/Elemento/label" style="line-height: 23.3333339691162px;" title="This article hasn't been written yet. Please consider contributing!"><code><label></code></a> reciben la fuente correcta.</p> + +<pre class="brush: css">label { + font : .8em "typewriter", sans-serif; +}</pre> + +<p>Los campos de texto necesitan algunas reglas comunes. Dicho simplemente, le quitamos bordes y fondos y redefinimos el padding y margin.</p> + +<pre class="brush: css">input, textarea { + font : .9em/1.5em "handwriting", sans-serif; + + border : none; + padding : 0 10px; + margin : 0; + width : 240px; + + background: none; +}</pre> + +<p>Cuando uno de estos campos recibe el foco, vamos a resaltarlo con un fondo transparente gris claro. Tome nota de que es importante añadir la propiedad <span style="line-height: 23.3333339691162px;"> </span><a class="new" href="https://developer.mozilla.org/es/docs/Web/CSS/outline" style="color: rgb(153, 0, 0); line-height: 23.3333339691162px;" title="The documentation about this has not yet been written; please consider contributing!"><code>outline</code></a><span style="line-height: 23.3333339691162px;"> </span> para quitar el resaltado de enfoque añadido por defecto por algunos navegadores.</p> + +<pre class="brush: css">input:focus, textarea:focus { + background : rgba(0,0,0,.1); + border-radius: 5px; + outline : none; +}</pre> + +<p>Ahora que nuestros campos de texto están terminados, necesitamos ajustar como se muestran los campos de simple y múltiple línea para que coincidan, ya que lo normal es que por defecto no se vean igual.</p> + +<p>El campo de línea simple requiere de algunos trucos para que se vean bien en Internet Explorer. Internet Explorer no define la altura de los campos basándose en la altura natural de la fuente (lo cual es el comportamiento normal del resto de navegadores). Para corregir esto necesitamos añadir explícitamente la altura a los campos de la siguiente forma:</p> + +<pre class="brush: css">input { + height: 2.5em; /* for IE */ + vertical-align: middle; /* This is optional but it makes legacy IEs look better */ +}</pre> + +<p>Los elementos <code style="color: rgb(153, 0, 0); line-height: 23.3333339691162px;"><a class="new" href="https://developer.mozilla.org/es/docs/Web/HTML/Elemento/textarea" style="color: rgb(153, 0, 0); line-height: 23.3333339691162px;" title="This article hasn't been written yet. Please consider contributing!"><textarea></a> </code>se muestran por defecto como bloques, Las dos cosas importantes aquí son las propiedades <a class="new" href="https://developer.mozilla.org/es/docs/Web/CSS/resize" style="color: rgb(153, 0, 0); line-height: 19.0909080505371px;" title="The documentation about this has not yet been written; please consider contributing!"><code>resize</code></a><span style="line-height: 19.0909080505371px;"> y </span><code style="line-height: 19.0909080505371px;"><a href="https://developer.mozilla.org/es/docs/Web/CSS/overflow" style="line-height: 19.0909080505371px;" title="La propiedad CSS overflow especifica: si recortar contenido, dibujar barras de desplazamiento o mostrar el contenido excedente en un elemento a nivel de bloque.">overflow</a>. </code>Ya que nuestro <code style="line-height: 19.0909080505371px;">diseño </code>es de tamaño fijo, utilizaremos la propiedad <code>resize</code> para impedir que el usuario pueda cambiar el tamaño de los campos multilínea. La propiedad <span style="line-height: 19.0909080505371px;"> </span><a href="https://developer.mozilla.org/es/docs/Web/CSS/overflow" style="line-height: 19.0909080505371px;" title="La propiedad CSS overflow especifica: si recortar contenido, dibujar barras de desplazamiento o mostrar el contenido excedente en un elemento a nivel de bloque."><code>overflow</code></a><span style="line-height: 19.0909080505371px;"> </span> se utiliza para que el campo se muestre de forma más consistente a través de diversos navegadores; algunos de ellos ponen por defecto esta propiedad en <code>auto</code>, pero en nuestro caso, es mejor asegurarse de que todos estén en <code>auto.</code></p> + +<pre class="brush: css">textarea { + display : block; + + padding : 10px; + margin : 10px 0 0 -10px; + width : 340px; + height : 360px; + + resize : none; + overflow: auto; +}</pre> + +<p>El elemento <code style="line-height: 19.0909080505371px;"><a href="https://developer.mozilla.org/es/docs/Web/HTML/Elemento/button" style="line-height: 19.0909080505371px;" title="This article hasn't been written yet. Please consider contributing!"><button></a> </code>se acomoda muy bien a CSS; se puede hacer lo que se quiera con el, ¡incluso utilizando<code style="line-height: 19.0909080505371px;"> <a href="https://developer.mozilla.org/en-US/docs/CSS/Pseudo-elements">pseudo-elementos</a>!</code></p> + +<pre class="brush: css">button { + position : absolute; + left : 440px; + top : 360px; + + padding : 5px; + + font : bold .6em sans-serif; + border : 2px solid #333; + border-radius: 5px; + background : none; + + cursor : pointer; + +-webkit-transform: rotate(-1.5deg); + -moz-transform: rotate(-1.5deg); + -ms-transform: rotate(-1.5deg); + -o-transform: rotate(-1.5deg); + transform: rotate(-1.5deg); +} + +button:after { + content: " >>>"; +} + +button:hover, +button:focus { + outline : none; + background: #000; + color : #FFF; +}</pre> + +<p>Y ¡listo! Sientase libre de probarlo usted mismo; como comprobará ¡esto funciona!</p> + +<h2 id="Conclusión">Conclusión</h2> + +<p>Como puede verse, mientras que queramos construir formularios solo con campos de texto y botones, es sencillo aplicarles estilos con CSS. Si desea saber más pequeños trucos de CSS que le hagan más fácil la vida al trabajar con formularios, echele un vistazo a la parte de formularios de <a href="http://necolas.github.com/normalize.css" rel="external" style="line-height: 19.0909080505371px;" title="http://necolas.github.com/normalize.css">the normalize.css project</a><span style="line-height: 19.0909080505371px;">.</span></p> + +<p><span style="line-height: 19.0909080505371px;">En el próximo artículo, veremos como manejar widgets de formulario de la categoría de "el malo" y "el feo".</span></p> diff --git a/files/es/learn/forms/test_your_skills_colon__html5_controls/index.html b/files/es/learn/forms/test_your_skills_colon__html5_controls/index.html new file mode 100644 index 0000000000..b73c8d4442 --- /dev/null +++ b/files/es/learn/forms/test_your_skills_colon__html5_controls/index.html @@ -0,0 +1,75 @@ +--- +title: 'Prueba tus habilidades: controles HTML5' +slug: 'Learn/HTML/Forms/Prueba_tus_habilidades:_controles_HTML5' +tags: + - Aprendizaje + - Evaluación + - Formulário + - HTML5 + - Principiante +translation_of: 'Learn/Forms/Test_your_skills:_HTML5_controls' +--- +<div>{{learnsidebar}}</div> + +<p>El objetivo de esta prueba es evaluar si has comprendido nuestro artículo <a href="/en-US/docs/Learn/Forms/HTML5_input_types">The HTML5 input types</a>.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes intentar resolver esta prueba en los editores interactivos más abajo, sin embargo, puede ser útil descargar el código y usar una herramienta en línea como <a href="https://codepen.io/" rel="noopener">CodePen</a>, <a href="https://jsfiddle.net/" rel="noopener">jsFiddle</a>, o <a href="https://glitch.com/" rel="noopener">Glitch</a> para trabajar en las tareas.<br> + <br> + Si te atascas, pide ayuda — mira la sección <a href="https://wiki.developer.mozilla.org/es/docs/Learn/HTML/Introduccion_a_HTML/Prueba_tus_habilidades:_Enlaces#Evaluaci%C3%B3n_o_ayuda_adicional">Evaluación o ayuda adicional</a> al final de esta página.</p> +</div> + +<h2 id="Controles_HTML5_1">Controles HTML5 1</h2> + +<p>Primero exploraremos algunos de los tipos nuevos de <code>input</code> en HTML5. Crea las etiquetas <code>input</code> apropiadas para que un usuario actualice sus detalles para:</p> + +<ol> + <li>Email</li> + <li>Website</li> + <li>Número de teléfono</li> + <li>Color favorito</li> +</ol> + +<p>Intenta actualizar el código en vivo más abajo para retrear el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/forms/tasks/html5-controls/html5-controls1.html", '100%', 700)}}</p> + +<div class="blockIndicator note"> +<p><a href="/en-US/docshttps://github.com/mdn/learning-area/blob/master/html/forms/tasks/html5-controls/html5-controls1-download.html">Descarga el código inicial de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Controles_HTML5_2">Controles HTML5 2</h2> + +<p>A continuación, queremos que implementes un control deslizante para permitir al usuario escoger el número máximo de personas para invitar a su fiesta.</p> + +<ol> + <li>Implemente un control deslizante básico que acompañe a la etiqueta provista.</li> + <li>Establezca un valor minimo de 1, uno máximo de 30 y un valor inicial de 10.</li> + <li>Crea un elemento de salida correspondiente para poner el valor actual del deslizador. Asígnale la clase invite-output, y asocialo semanticamente con le entrada. Si haces esto correctamente, el JavaScript incluido en la página automáticamente actualizará el valor cuando se deslice el control.</li> +</ol> + +<p>Intenta actualizar el código en vivo más abajo para retrear el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/forms/tasks/html5-controls/html5-controls2.html", '100%', 700)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/html/forms/tasks/html5-controls/html5-controls2-download.html">Descarga el código inicial de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Evaluación_o_ayuda_adicional">Evaluación o ayuda adicional</h2> + +<p>Puedes practicar estos ejemplos en los editores interactivos que se encuentran más arriba.</p> + +<p>Si deseas que tu trabajo sea evaluado, o estás atorado y quieres solicitar ayuda:</p> + +<ol> + <li>Pon tu trabajo en un editor en línea con capacidad de compartir como <a href="https://codepen.io/" rel="noopener">CodePen</a>, <a href="https://jsfiddle.net/" rel="noopener">jsFiddle</a>, o <a href="https://glitch.com/" rel="noopener">Glitch</a>. Puedes escribir el código por ti mismo, o usar los archivos de punto de inicio enlazados en las secciones superiores.</li> + <li>Escribe una publicación solicitando evaluacion y/o ayuda en el <a href="https://discourse.mozilla.org/c/mdn/learn" rel="noopener">MDN Discourse forum Learning category</a>. Tu publicación debería incluir: + <ul> + <li>Un título descriptivo como "Solicito evaluacion para la prueba de habilidad de controles HTML5 1".</li> + <li>Detalles de lo que ya has intentado, y que te gustaría que hiciéramos, por ejemplo, si estas atascado y necesitas ayuda, o quieres una evaluación.</li> + <li>Un enlace al ejemplo que quieres que sea evaluado o por el que necesitas ayuda en un editor en linea con capacidad de compartir (como se mencionó en el paso 1 más arriba). Esta es una buena práctica - Es muy dificil ayudar a alguien con un problema de codificación si no puedes ver su código.</li> + <li>Un enlace a la tarea o página de evaluacion actual, para que podamos encontrar la pregunta con la cual necesitas ayuda.</li> + </ul> + </li> +</ol> diff --git a/files/es/learn/forms/test_your_skills_colon__other_controls/index.html b/files/es/learn/forms/test_your_skills_colon__other_controls/index.html new file mode 100644 index 0000000000..1496025a8d --- /dev/null +++ b/files/es/learn/forms/test_your_skills_colon__other_controls/index.html @@ -0,0 +1,87 @@ +--- +title: 'Prueba tus habilidades: Otros controles' +slug: 'Learn/HTML/Forms/Prueba_tus_habilidades:_Otros_controles' +translation_of: 'Learn/Forms/Test_your_skills:_Other_controls' +--- +<div>{{learnsidebar}}</div> + +<p>El objetivo de esta pueba de habilidad es evaluar si has comprendido nuestro artículo <a href="/en-US/docs/Learn/Forms/Other_form_controls">Otros controles de formulario</a>.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes intentar resolver esta prueba en los editores interactivos más abajo, sin embargo, puede ser útil descargar el código y usar una herramienta en línea como <a href="https://codepen.io/" rel="noopener">CodePen</a>, <a href="https://jsfiddle.net/" rel="noopener">jsFiddle</a>, o <a href="https://glitch.com/" rel="noopener">Glitch</a> para trabajar en las tareas.<br> + <br> + Si te atascas, pide ayuda — mira la sección <a href="https://wiki.developer.mozilla.org/es/docs/Learn/HTML/Introduccion_a_HTML/Prueba_tus_habilidades:_Enlaces#Evaluaci%C3%B3n_o_ayuda_adicional">Evaluación o ayuda adicional</a> al final de esta página.</p> +</div> + +<h2 id="Otros_controles_1">Otros controles 1</h2> + +<p>En nuestra primera evaluación de "Otros controles", te pediremos crear una entrada de texto de líneas múltiples.</p> + +<ol> + <li>Crea una entrada básica de texto de múltiples líneas.</li> + <li>Asócialo semánticamente con la etiqueta de "Comentario" asociado.</li> + <li>Define la entrada con 35 columnas y 10 filas de espacio en cual agregar comentarios.</li> + <li>Define para los comentatios una longitud máxima de 100 caracteres.</li> +</ol> + +<p>Intenta actualizar el código en vivo más abajo para mostrar el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/forms/tasks/other-controls/other-controls1.html", '100%', 700)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/html/forms/tasks/other-controls/other-controls1-download.html" rel="noopener">Descarga el inicio de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Otros_controles_2">Otros controles 2</h2> + +<p>Ahora es tiempo de implementar un menú desplegable, para permitir al usuario escoger su comida favorita de las opciones entregadas.</p> + +<ol> + <li>Crea tu estructura de caja básica.</li> + <li>Asóciala semánticamente con la etiqueta de "comentarios" entregada.</li> + <li>Dentro de la lista, divide las opciones en 2 subgrupos - "principales" y "meriendas".</li> +</ol> + +<p>Intenta actualizar el código en vivo más abajo para mostrar el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/forms/tasks/other-controls/other-controls2.html", '100%', 700)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/html/forms/tasks/other-controls/other-controls2-download.html" rel="noopener">Descarga el inicio de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Otros_controles_3">Otros controles 3</h2> + +<p>En la tarea final de esta evaluación, comenzaremos con la misma lista de opciones de comida. Sin embargo, esta vez queremos hacer las cosas de otra forma:</p> + +<ol> + <li>Crea una entrada de texto básica, que esté asociada semánticamente con la etiqueta entregada.</li> + <li>Coloca las opciones de comida en una lista que pueda ser asociada con una entrada de formulario.</li> + <li>Asocia la lista con tu entrada de texto, de forma que cuando escribas caracteres, cualquier opción de la lista que coincida con la secuencia de caracteres ingresada, aparezca en un listado desplegable como sugerencia de autocompletado.</li> +</ol> + +<p>Intenta actualizar el código en vivo más abajo para mostrar el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/forms/tasks/other-controls/other-controls3.html", '100%', 700)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/html/forms/tasks/other-controls/other-controls3-download.html" rel="noopener">Descarga el inicio de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Evaluación_o_ayuda_adicional">Evaluación o ayuda adicional</h2> + +<p>Puedes practicar estos ejemplos en los editores interactivos que se encuentran más arriba.</p> + +<p>Si deseas que tu trabajo sea evaluado, o estás atorado y quieres solicitar ayuda:</p> + +<ol> + <li>Pon tu trabajo en un editor en línea con capacidad de compartir como <a href="https://codepen.io/" rel="noopener">CodePen</a>, <a href="https://jsfiddle.net/" rel="noopener">jsFiddle</a>, o <a href="https://glitch.com/" rel="noopener">Glitch</a>. Puedes escribir el código por ti mismo, o usar los archivos de punto de inicio enlazados en las secciones superiores.</li> + <li>Escribe una publicación solicitando evaluacion y/o ayuda en el <a href="https://discourse.mozilla.org/c/mdn/learn" rel="noopener">MDN Discourse forum Learning category</a>. Tu publicación debería incluir: + <ul> + <li>Un título descriptivo como "Solicito evaluacion para la prueba de habilidad de Otros controles 1".</li> + <li>Detalles de lo que ya has intentado, y que te gustaría que hiciéramos, por ejemplo, si estas atascado y necesitas ayuda, o quieres una evaluación.</li> + <li>Un enlace al ejemplo que quieres que sea evaluado o por el que necesitas ayuda en un editor en linea con capacidad de compartir (como se mencionó en el paso 1 más arriba). Esta es una buena práctica - Es muy dificil ayudar a alguien con un problema de codificación si no puedes ver su código.</li> + <li>Un enlace a la tarea o página de evaluacion actual, para que podamos encontrar la pregunta con la cual necesitas ayuda.</li> + </ul> + </li> +</ol> diff --git a/files/es/learn/forms/your_first_form/index.html b/files/es/learn/forms/your_first_form/index.html new file mode 100644 index 0000000000..df9d73bc60 --- /dev/null +++ b/files/es/learn/forms/your_first_form/index.html @@ -0,0 +1,305 @@ +--- +title: Mi primer formulario HTML +slug: Learn/HTML/Forms/Your_first_HTML_form +tags: + - Ejemplo + - Guía + - HTML + - Principiante + - Web + - formulários +translation_of: Learn/Forms/Your_first_form +--- +<div>{{LearnSidebar}}{{NextMenu("Learn/Forms/How_to_structure_a_web_form", "Learn/Forms")}}</div> + +<p class="summary">El primer artículo de nuestra serie te proporciona una primera experiencia de creación de un formulario web, que incluye diseñar un formulario sencillo con controles de formulario adecuados y otros elementos HTML, añadir un poco de estilo muy simple con CSS y describir cómo se envían los datos a un servidor. Ampliaremos cada uno de estos subtemas más adelante.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática y de <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">lenguaje HTML</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Familiarizarse con los formularios web, para qué se usan, cómo diseñarlos y qué elementos HTML básicos vas a necesitar para casos sencillos.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_son_los_formularios_web">¿Qué son los formularios web?</h2> + +<p>Los <strong>formularios web</strong> son uno de los principales puntos de interacción entre un usuario y un sitio web o aplicación. Los formularios permiten a los usuarios la introducción de datos, que generalmente se envían a un servidor web para su procesamiento y almacenamiento (consulta <a href="/es/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Enviar los datos de un formulario</a> más adelante en el módulo), o se usan en el lado del cliente para provocar de alguna manera una actualización inmediata de la interfaz (por ejemplo, se añade otro elemento a una lista, o se muestra u oculta una función de interfaz de usuario).</p> + +<p>El HTML de un <strong>formulario web</strong> está compuesto por uno o más <strong>controles de formulario</strong> (a veces llamados <strong>widgets</strong>), además de algunos elementos adicionales que ayudan a estructurar el formulario general; a menudo se los conoce como <strong>formularios HTML</strong>. Los controles pueden ser campos de texto de una o varias líneas, cajas desplegables, botones, casillas de verificación o botones de opción, y se crean principalmente con el elemento {{htmlelement("input")}}, aunque hay algunos otros elementos que también hay que conocer.</p> + +<p>Los controles de formulario también se pueden programar para forzar la introducción de formatos o valores específicos (<strong>validación de formulario</strong>), y se combinan con etiquetas de texto que describen su propósito para los usuarios con y sin discapacidad visual.</p> + +<h2 id="Diseñar_tu_formulario">Diseñar tu formulario</h2> + +<p>Antes de comenzar a escribir código, siempre es mejor dar un paso atrás y tomarte el tiempo necesario para pensar en tu formulario. Diseñar una maqueta rápida te ayudará a definir el conjunto de datos adecuado que deseas pedirle al usuario que introduzca. Desde el punto de vista de la experiencia del usuario (UX), es importante recordar que cuanto más grande es tu formulario, más te arriesgas a frustrar a las personas y perder usuarios. Tiene que ser simple y conciso: solicita solo los datos que necesitas.</p> + +<p>Diseñar formularios es un paso importante cuando creas un sitio web o una aplicación. Va más allá del alcance de este artículo exponer la experiencia de usuario de los formularios, pero si deseas profundizar en ese tema, puedes leer los artículos siguientes:</p> + +<ul> + <li>Smashing Magazine tiene algunos <a href="https://www.smashingmagazine.com/2018/08/ux-html5-mobile-form-part-1/" rel="external" title="http://uxdesign.smashingmagazine.com/tag/forms/">artículos muy buenos sobre formularios UX</a>, incluido el artículo —antiguo pero relevante— <a href="https://www.smashingmagazine.com/2011/11/extensive-guide-web-form-usability/" rel="external" title="http://uxdesign.smashingmagazine.com/2011/11/08/extensive-guide-web-form-usability/">An Extensive Guide To Web Form Usability</a> [Amplia guía de usabilidad para formularios web].</li> + <li>UXMatters también es un recurso que da buenos consejos, desde <a href="http://www.uxmatters.com/mt/archives/2012/05/7-basic-best-practices-for-buttons.php" rel="external" title="http://www.uxmatters.com/mt/archives/2012/05/7-basic-best-practices-for-buttons.php"> buenas prácticas básicas</a> hasta cuestiones complejas como los <a href="http://www.uxmatters.com/mt/archives/2010/03/pagination-in-web-forms-evaluating-the-effectiveness-of-web-forms.php" title="http://www.uxmatters.com/mt/archives/2010/03/pagination-in-web-forms-evaluating-the-effectiveness-of-web-forms.php"> formularios de varias páginas</a>.</li> +</ul> + +<p>En este artículo, vamos a crear un formulario de contacto sencillo. Hagamos un esbozo.</p> + +<p><img alt="Esbozo aproximado del formulario que vamos a construir" src="/files/4579/form-sketch-low.jpg" style="border-style: solid; border-width: 1px; display: block; height: 352px; margin: 0px auto; width: 400px;"></p> + +<p>Nuestro formulario va a tener tres campos de texto y un botón. Le pedimos al usuario su nombre, su correo electrónico y el mensaje que desea enviar. Al pulsar el botón sus datos se enviarán a un servidor web.</p> + +<h2 id="Aprendizaje_activo_La_implementación_de_nuestro_formulario_HTML">Aprendizaje activo: La implementación de nuestro formulario HTML</h2> + +<p>De acuerdo, intentemos crear el HTML para nuestro formulario. Vamos a utilizar los elementos HTML siguientes: {{HTMLelement("form")}}, {{HTMLelement("label")}}, {{HTMLelement("input")}}, {{HTMLelement("textarea")}} y {{HTMLelement("button")}}.</p> + +<p>Antes de continuar, haz una copia local de nuestra <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">plantilla HTML simple</a>: introduce aquí tu formulario HTML.</p> + +<h3 id="El_elemento_HTMLelementform">El elemento {{HTMLelement("form")}}</h3> + +<p>Todos los formularios comienzan con un elemento {{HTMLelement("form")}}, como este:</p> + +<pre class="brush:html; notranslate"><form action="/my-handling-form-page" method="post"> + +</form></pre> + +<p>Este elemento define formalmente un formulario. Es un elemento contenedor, como un elemento {{HTMLelement("section")}} o {{HTMLelement("footer")}}, pero específico para contener formularios; también admite algunos atributos específicos para la configuración de la forma en que se comporta el formulario. Todos sus atributos son opcionales, pero es una práctica estándar establecer siempre al menos los atributos <a href="/en-US/docs/Web/HTML/Attributes/action"><code>action</code></a> y <a href="/en-US/docs/Web/HTML/Attributes/method"><code>method</code></a>:</p> + +<ul> + <li>El atributo <code>action</code> define la ubicación (URL) donde se envían los datos que el formulario ha recopilado cuando se validan.</li> + <li>El atributo <code>method</code> define con qué método HTTP se envían los datos (generalmente <code>get</code> o <code>post</code>).</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Veremos cómo funcionan esos atributos en nuestro artículo <a href="/es/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data" title="/en-US/docs/HTML/Forms/Sending_and_retrieving_form_data">Enviar los datos de un formulario</a> que encontrarás más adelante.</p> +</div> + +<p>Por ahora, añade el elemento {{htmlelement("form")}} anterior a tu elemento HTML {{htmlelement("body")}}.</p> + +<h3 id="Los_elementos_HTMLelementlabel_HTMLelementinput_y_HTMLelementtextarea">Los elementos {{HTMLelement("label")}}, {{HTMLelement("input")}} y {{HTMLelement("textarea")}}</h3> + +<p>Nuestro formulario de contacto no es complejo: la parte para la entrada de datos contiene tres campos de texto, cada uno con su elemento {{HTMLelement("label")}} correspondiente:</p> + +<ul> + <li>El campo de entrada para el nombre es un {{HTMLelement("input/text", "campo de texto de una sola línea")}}.</li> + <li>El campo de entrada para el correo electrónico es una {{HTMLelement ("input/email", "entrada de datos de tipo correo electrónico")}}: un campo de texto de una sola línea que acepta solo direcciones de correo electrónico.</li> + <li>El campo de entrada para el mensaje es {{HTMLelement("textarea")}}; un campo de texto multilínea.</li> +</ul> + +<p>En términos de código HTML, para implementar estos controles de formulario necesitamos algo como lo siguiente:</p> + +<pre class="brush:html; notranslate" dir="rtl"><form action="/my-handling-form-page" method="post"> + <ul> + <li> + <label for="name">Nombre:</label> + <input type="text" id="name" name="user_name"> + </li> + <li> + <label for="mail">Correo electrónico:</label> + <input type="email" id="mail" name="user_mail"> + </li> + <li> + <label for="msg">Mensaje:</label> + <textarea id="msg" name="user_message"></textarea> + </li> + </ul> +</form></pre> + +<p>Actualiza el código de tu formulario para que se vea como el anterior.</p> + +<p>Los elementos {{HTMLelement("li")}} están ahí para estructurar nuestro código convenientemente y facilitar la aplicación de estilo (ver más adelante en el artículo). Por motivos de usabilidad y accesibilidad incluimos una etiqueta explícita para cada control de formulario. Ten en cuenta el uso del atributo <a href="/en-US/docs/Web/HTML/Attributes/for"> <code>for</code> </a> en todos los elementos {{HTMLelement("label")}}, que toma como valor el <a href="/en-US/docs/Web/HTML/Attributes/id"><code>id</code></a> del control de formulario con el que está asociado; así es como asocias un formulario con su etiqueta.</p> + +<p>Hacer esto presenta muchas ventajas porque la etiqueta está asociada al control del formulario y permite que los usuarios con ratón, panel táctil y dispositivos táctiles hagan clic en la etiqueta para activar el control correspondiente, y también proporciona accesibilidad con un nombre que los lectores de pantalla leen a sus usuarios. Encontrarás más detalles sobre las etiquetas de los formularios en <a href="/es/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">Cómo estructurar un formulario web</a>.</p> + +<p>En el elemento {{HTMLelement("input")}}, el atributo más importante es <code>type</code>. Este atributo es muy importante porque define la forma en que el elemento {{HTMLelement("input")}} aparece y se comporta. Encontrarás más información sobre esto en el artículo sobre <a href="/es/docs/Learn/HTML/Forms/The_native_form_widgets">Controles de formularios nativos básicos</a> más adelante.</p> + +<ul> + <li>En nuestro ejemplo sencillo, usamos el valor {{HTMLelement("input/text")}} para la primera entrada, el valor predeterminado para este atributo. Representa un campo de texto básico de una sola línea que acepta cualquier tipo de entrada de texto.</li> + <li>Para la segunda entrada, usamos el valor {{HTMLelement("input/email")}}, que define un campo de texto de una sola línea que solo acepta una dirección de correo electrónico. Esto convierte un campo de texto básico en una especie de campo «inteligente» que efectúa algunas comprobaciones de validación de los datos que el usuario escribe. También hace que aparezca un diseño de teclado más apropiado para introducir direcciones de correo electrónico (por ejemplo, con un símbolo @ por defecto) en dispositivos con teclados dinámicos, como teléfonos inteligentes. Encontrarás más información sobre la validación de formularios en el artículo de <a href="/es/docs/Learn/HTML/Forms/Validacion_formulario_datos">Validación de formularios por parte del cliente</a> más adelante.</li> +</ul> + +<p>Por último, pero no por ello menos importante, ten en cuenta la sintaxis de <code><input></code> en contraposición con la de <code><textarea></textarea></code>. Esta es una de las rarezas del HTML. La etiqueta <code><input></code> es un elemento vacío, lo que significa que no necesita una etiqueta de cierre. El elemento {{HTMLElement("textarea")}} no es un elemento vacío, lo que significa que debe cerrarse con la etiqueta de cierre adecuada. Esto tiene un impacto en una característica específica de los formularios: el modo en que defines el valor predeterminado. Para definir el valor predeterminado de un elemento {{HTMLElement("input")}}, debes usar el atributo <a href="/en-US/docs/Web/HTML/Attributes/value"><code>value</code></a> de esta manera:</p> + +<pre class="brush:html; notranslate"><input type="text" value="por defecto este elemento se llena con este texto"></pre> + +<p>Por otro lado, si deseas definir un valor predeterminado para un elemento {{HTMLElement("textarea")}}, lo colocas entre las etiquetas de apertura y cierre del elemento {{HTMLElement("textarea")}}, así:</p> + +<pre class="brush:html; notranslate"><textarea> +Por defecto, este elemento contiene este texto +</textarea></pre> + +<h3 id="El_elemento_HTMLelementbutton">El elemento {{HTMLelement("button")}}</h3> + +<p>El marcado de nuestro formulario está casi completo; solo necesitamos añadir un botón para permitir que el usuario envíe sus datos una vez que haya completado el formulario. Esto se hace con el elemento {{HTMLelement("button")}}; añade lo siguiente justo encima de la etiqueta de cierre <code></form></code>:</p> + +<pre class="brush:html; notranslate"><li class="button"> + <button type="submit">Envíe su mensaje</button> +</li></pre> + +<p>El elemento {{htmlelement("button")}} también acepta un atributo de <code>type</code>, que a su vez acepta uno de estos tres valores: <code>submit</code>, <code>reset</code> o <code>button</code>.</p> + +<ul> + <li>Un clic en un botón <code>submit</code> (el valor predeterminado) envía los datos del formulario a la página web definida por el atributo <code>action</code> del elemento {{HTMLelement("form")}}.</li> + <li>Un clic en un botón <code>reset</code> restablece de inmediato todos los controles de formulario a su valor predeterminado. Desde el punto de vista de UX, esto se considera una mala práctica, por lo que debes evitar usar este tipo de botones a menos que realmente tengas una buena razón para incluirlos.</li> + <li>Un clic en un botón <code>button</code> no hace... ¡nada! Eso suena tonto, pero es muy útil para crear botones personalizados: puedes definir su función con JavaScript.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: También puedes usar el elemento {{HTMLElement("input")}} con el atributo <code>type</code> correspondiente para generar un botón, por ejemplo <code><input type="submit"></code>. La ventaja principal del elemento {{HTMLelement("button")}} es que el elemento {{HTMLelement("input")}} solo permite texto sin formato en su etiqueta, mientras que el elemento {{HTMLelement("button")}} permite contenido HTML completo, lo que permite generar botones creativos más complejos.</p> +</div> + +<h2 id="Aplicar_estilo_básico_a_un_formulario">Aplicar estilo básico a un formulario</h2> + +<p>Ahora que has terminado de escribir el código HTML de tu formulario, guárdalo y observa lo que ocurre en un navegador. Por ahora, se verá bastante feo.</p> + +<div class="note"> +<p><strong>Nota</strong>: Si crees que no has escrito bien el código HTML, compáralo con nuestro ejemplo final: véase <a href="https://github.com/mdn/learning-area/blob/master/html/forms/your-first-HTML-form/first-form.html">first-form.html</a> (<a href="https://mdn.github.io/learning-area/html/forms/your-first-HTML-form/first-form.html">ver en vivo</a>).</p> +</div> + +<p>Resulta notablemente difícil aplicar estilo a los formularios. Está más allá del alcance de este artículo enseñarte cómo aplicar estilo a los formularios en detalle, por lo que por el momento solo vamos a exponer cómo añadir un poco de CSS para que se vea un poco bien.</p> + +<p>En primer lugar, añade un elemento {{htmlelement("style")}} a tu página, dentro de la cabecera del HTML. Debe quedar así:</p> + +<pre class="brush: html notranslate"><style> + +</style></pre> + +<p>Dentro de las etiquetas <code>style</code>, añade el código CSS siguiente:</p> + +<pre class="brush:css; notranslate">form { + /* Centrar el formulario en la página */ + margin: 0 auto; + width: 400px; + /* Esquema del formulario */ + padding: 1em; + border: 1px solid #CCC; + border-radius: 1em; +} + +ul { + list-style: none; + padding: 0; + margin: 0; +} + +form li + li { + margin-top: 1em; +} + +label { + /* Tamaño y alineación uniforme */ + display: inline-block; + width: 90px; + text-align: right; +} + +input, +textarea { + /* Para asegurarse de que todos los campos de texto tienen la misma configuración de letra + Por defecto, las áreas de texto tienen un tipo de letra monoespaciada */ + font: 1em sans-serif; + + /* Tamaño uniforme del campo de texto */ + width: 300px; + box-sizing: border-box; + + /* Hacer coincidir los bordes del campo del formulario */ + border: 1px solid #999; +} + +input:focus, +textarea:focus { + /* Destacado adicional para elementos que tienen el cursor */ + border-color: #000; +} + +textarea { + /* Alinear los campos de texto multilínea con sus etiquetas */ + vertical-align: top; + + /* Proporcionar espacio para escribir texto */ + height: 5em; +} + +.button { + /* Alinear los botones con los campos de texto */ + padding-left: 90px; /* mismo tamaño que los elementos de la etiqueta */ +} + +button { + /* Este margen adicional representa aproximadamente el mismo espacio que el espacio + entre las etiquetas y sus campos de texto */ + margin-left: .5em; +}</pre> + +<p>Guarda y vuelve a cargar, y observa que tu formulario presenta un aspecto mucho menos feo.</p> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar nuestra versión en GitHub en <a href="https://github.com/mdn/learning-area/blob/master/html/forms/your-first-HTML-form/first-form-styled.html">first-form-styled.html</a> (<a href="https://mdn.github.io/learning-area/html/forms/your-first-HTML-form/first-form-styled.html">ver en vivo</a>).</p> +</div> + +<h2 id="Enviar_los_datos_del_formulario_a_un_servidor_web">Enviar los datos del formulario a un servidor web</h2> + +<p>La última parte, y quizás la más complicada, es manejar los datos del formulario en el lado del servidor. El elemento {{HTMLelement("form")}} define dónde y cómo enviar los datos gracias a los atributos <a href="/en-US/docs/Web/HTML/Attributes/action"><code>action</code></a> y <a href="/en-US/docs/Web/HTML/Attributes/method"><code>method</code></a>.</p> + +<p>Proporcionamos un nombre (<a href="/en-US/docs/Web/HTML/Attributes/name"><code>name</code></a>) a cada control de formulario. Los nombres son importantes tanto en el lado del cliente como del servidor; le dicen al navegador qué nombre debe dar a cada dato y, en el lado del servidor, dejan que el servidor maneje cada dato por su nombre. Los datos del formulario se envían al servidor como pares de nombre/valor.</p> + +<p>Para poner nombre a los diversos datos que se introducen en un formulario, debes usar el atributo <code>name</code> en cada control de formulario que recopila un dato específico. Veamos de nuevo algunos de nuestros códigos de formulario:</p> + +<pre class="brush:html; notranslate"><form action="/my-handling-form-page" method="post"> + <ul> + <li> + <label for="name">Nombre:</label> + <input type="text" id="name" name="user_name" /> + </li> + <li> + <label for="mail">Correo electrónico:</label> + <input type="email" id="mail" name="user_email" /> + </li> + <li> + <label for="msg">Mensaje:</label> + <textarea id="msg" name="user_message"></textarea> + </li> + + ... +</pre> + +<p>En nuestro ejemplo, el formulario envía tres datos denominados «<code>user_name</code>», «<code>user_email</code>» y «<code>user_message</code>». Esos datos se envían a la URL «<code>/my-handling-form-page</code>» utilizando el método <a href="/en-US/docs/Web/HTTP/Methods/POST"><code>post</code> de HTTP</a>.</p> + +<p>En el lado del servidor, la secuencia de comandos de la URL «<code>/my-handling-form-page</code>» recibe los datos como una lista de tres elementos clave/valor contenidos en la solicitud HTTP. La forma en que este script maneja esos datos depende de ti. Cada lenguaje de servidor (PHP, Python, Ruby, Java, C#, etc.) tiene su propio mecanismo de manipulación de datos de formulario. No profundizaremos sobre el tema en esta guía, pero si deseas obtener más información, proporcionamos algunos ejemplos en nuestro artículo <a href="/es/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data" title="/en-US/docs/HTML/Forms/Sending_and_retrieving_form_data"><span>Enviar los datos de un formulario</span></a> que encontrarás más adelante.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>¡Enhorabuena!, has creado tu primer formulario web. Debería verse así:</p> + +<p>{{ EmbedLiveSample('A_simple_form', '100%', '240', '', 'Learn/Forms/Your_first_form/Example') }}</p> + +<p>Pero esto es solo el comienzo: ahora ha llegado el momento de profundizar en el tema. Los formularios tienen mucho más potencial de lo que hemos visto aquí y los artículos siguientes de este módulo te ayudarán a dominarlo.</p> + +<p>{{NextMenu("Learn/Forms/How_to_structure_a_web_form", "Learn/Forms")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Forms/Your_first_form">Tu primer formulario</a></li> + <li><a href="/en-US/docs/Learn/Forms/How_to_structure_a_web_form">Cómo estructurar un formulario web</a></li> + <li><a href="/en-US/docs/Learn/Forms/Basic_native_form_controls">Los controles de formulario básicos originales</a></li> + <li><a href="/en-US/docs/Learn/Forms/HTML5_input_types">Los tipos de entrada en HTML5</a></li> + <li><a href="/en-US/docs/Learn/Forms/Other_form_controls">Otros controles de formulario</a></li> + <li><a href="/en-US/docs/Learn/Forms/Styling_web_forms">Aplicación de estilo a formularios web</a></li> + <li><a href="/en-US/docs/Learn/Forms/Advanced_form_styling">Aplicación de estilo a formularios avanzada</a></li> + <li><a href="/en-US/docs/Learn/Forms/UI_pseudo-classes">Pseudoclases UI</a></li> + <li><a href="/en-US/docs/Learn/Forms/Form_validation">Validación del formulario del lado del cliente</a></li> + <li><a href="/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data">Enviar los datos de un formulario</a></li> +</ul> + +<h3 id="Temas_avanzados">Temas avanzados</h3> + +<ul> + <li><a href="/en-US/docs/Learn/Forms/How_to_build_custom_form_controls">Cómo construir controles de formulario personalizados</a></li> + <li><a href="/en-US/docs/Learn/Forms/Sending_forms_through_JavaScript">Enviar formularios a través de JavaScript</a></li> + <li><a href="/en-US/docs/Learn/Forms/Property_compatibility_table_for_form_widgets">Tabla de compatibilidad para las propiedades de los controles de formulario</a></li> +</ul> |