aboutsummaryrefslogtreecommitdiff
path: root/files/es/web/guide/html/html5/constraint_validation/index.html
blob: 04182a8fecdbbc7af3f66158f0adeb62d6b3aff3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
---
title: Validación de restricciones
slug: HTML/HTML5/Validacion_de_restricciones
tags:
  - CSS
  - Guía
  - HTML5
  - NecesitaContenido
  - Selectores
translation_of: Web/Guide/HTML/HTML5/Constraint_validation
---
<p>La creación de formularios web siempre ha sido una tarea compleja. Mientras armar el formulario en sí es fácil, verificar si cada campo tiene un valor que es válido y coherente es aun más difícil, e informar al usuario acerca del problema puede convertirse en un dolor de cabeza.<a href="/es/docs/HTML/HTML5" title="en/HTML/HTML5"> HTML5</a> introdujo nuevos mecanismos para formularios: añadió nuevos tipos semánticos para el elemento {{ HTMLElement("input") }} y <em>validación de restricciones</em> para facilitar el trabajo de revisar el contenido del formulario de lado del cliente. Se pueden usar restricciones básicas y comunes, sin la necesidad de JavaScript, estableciendo nuevos atributos; para restricciones más complejas se puede usar la <a href="/es/docs/HTML/HTML5/Formularios_en_HTML5#Validaci.C3.B3n_restringida" title="en/HTML/HTML5/Forms in HTML5#Constraint Validation API">API de Validación de Restricciones</a> de HTML.</p>

<div class="note"><strong>Nota:</strong> La validación de restricciones de HTML5 no elimina la necesidad de hacer validaciones <em>de lado del servidor</em>. Aunque se esperen menos envíos con formularios inválidos, sí se pueden seguir recibiendo datos inválidos, en navegadores sin soporte (por ejemplo, navegadores sin HTML y sin JavaScript) o por chicos malos que traten de burlar las restricciones de la aplicación. Por lo tanto, como en HTML4, también tendrás que validar las restricciones de captura del lado del servidor, de modo que sea consistente con las que se hacen del lado del cliente.</div>

<h2 id="Restricciones_intrínsecas_y_básicas">Restricciones intrínsecas y básicas</h2>

<p>En HTML5, las restricciones básicas son declaradas de dos formas:</p>

<ul>
 <li>Eligiendo el valor semánticamente más apropiado para el atributo {{ htmlattrxref("type", "input") }} del elemento {{ HTMLElement("input") }}, por ejemplo, elegir el tipo <span style="font-family: courier new;">email</span> creará automáticamente la restricción para verificar que el valor sea una dirección de correo electrónico válida.</li>
 <li>Estableciendo valores a los atributos de validación, permitiendo que se describan restricciones básicas de manera simple, sin la necesidad de JavaScript.</li>
</ul>

<h3 id="Tipos_de_captura_semánticos">Tipos de captura semánticos</h3>

<p>Las restricciones intrínsecas para el atributo {{ htmlattrxref("type", "input") }} son:</p>

<table class="standard-table">
 <thead>
  <tr>
   <th scope="col">Tipo de input</th>
   <th scope="col">Descripción</th>
   <th scope="col">Incumplimiento asociado</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td><span style="font-family: courier new;">&lt;input type="URL"&gt;</span></td>
   <td>El valor debe ser una URL absoluta, es decir, una de las siguientes:
    <ul>
     <li>una URI válida (como se define en <a class="external" href="http://www.ietf.org/rfc/rfc3986.txt" title="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>)</li>
     <li>una IRI válida, sin un componente de query (como se define en <a class="external" href="http://www.ietf.org/rfc/rfc3987.txt" title="http://www.ietf.org/rfc/rfc3987.txt">RFC 3987</a>)</li>
     <li>una IRI válida, con componente de query sin caracteres no ASCII sin escapar (como se define en <a class="external" href="http://www.ietf.org/rfc/rfc3987.txt" title="http://www.ietf.org/rfc/rfc3987.txt">RFC 3987</a>)</li>
     <li>una IRI válida, y que el conjunto de caracteres para el documento sea UTF-8 o UTF-16 (como se define en <a class="external" href="http://www.ietf.org/rfc/rfc3987.txt" title="http://www.ietf.org/rfc/rfc3987.txt">RFC 3987</a>)</li>
    </ul>
   </td>
   <td>Incumplimiento de restricción por <strong>tipo no coincidente (Type mismatch)</strong></td>
  </tr>
  <tr>
   <td> <span style="font-family: courier new;">&lt;input type="email"&gt;</span></td>
   <td>El valor debe obedecer a la producción <a class="external" href="http://www.ietf.org/rfc/std/std68.txt" title="http://www.ietf.org/rfc/std/std68.txt">ABNF</a>: <code>1*( atext / "." ) "@" ldh-str 1*( "." ldh-str )</code> donde:
    <ul>
     <li><code>atext</code> está definido en  <a class="external" href="http://tools.ietf.org/html/rfc5322" title="http://tools.ietf.org/html/rfc5322">RFC 5322</a>, y representa una letra US-ASCII (<span style="font-family: courier new;">A</span>-<span style="font-family: courier new;">Z</span> y <span style="font-family: courier new;">a</span>-<span style="font-family: courier new;">z</span>), un dígito (<span style="font-family: courier new;">0</span>-<span style="font-family: courier new;">9</span>) o uno de los siguientes caracteres especiales: <span style="font-family: courier new;">! # $ % &amp; ' * + - / = ? ` { } | ~</span>,</li>
     <li><code>ldh-str</code> está definido en <a class="external" href="http://www.apps.ietf.org/rfc/rfc1034.html#sec-3.5" title="http://www.apps.ietf.org/rfc/rfc1034.html#sec-3.5">RFC 1034</a>, y representa letras US-ASCII, combinadas con dígitos y el símbolo <span style="font-family: courier new;">-</span> agrupados en palabras separadas por un punto (<span style="font-family: courier new;">.</span>).</li>
    </ul>

    <div class="note"><strong>Nota:</strong> si se estableció el atributo {{ htmlattrxref("multiple", "input") }}, se pueden definir distintas direcciones de correo, separadas por coma, para este control. Si cualquiera de ellas no satisface la condición descrita aquí, se ejecuta el incumplimiento de restricción por <strong>tipo no coincidente</strong>.</div>
   </td>
   <td>Incumplimiento de restricción por <strong>tipo no coincidente (Type mismatch)</strong></td>
  </tr>
 </tbody>
</table>

<p>Nótese que la mayoría de los tipos de input no tienen restricciones intrínsecas, puesto que algunos simplemente son excluidos de la validación de restricciones, o tienen un algoritmo de sanitización que transforma los valores incorrectos a uno valor correcto predeterminado. </p>

<h3 id="Atributos_relacionados_con_validaciones">Atributos relacionados con validaciones</h3>

<p>Los siguientes atributos son usados para describir restricciones básicas:</p>

<table class="standard-table">
 <thead>
  <tr>
   <th scope="col">Atributo</th>
   <th scope="col">Tipos de input que soportan el atributo</th>
   <th scope="col">Valores posibles</th>
   <th scope="col">Descripción</th>
   <th scope="col">Incumplimiento asociado</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td>{{ htmlattrxref("pattern", "input") }}</td>
   <td>text, search, url, tel, email, password</td>
   <td>Una expresión regular de JavaScript (compilada con las banderas <code title="">global</code>, <code title="">ignoreCase</code>, y <code title="">multiline</code> de ECMAScript 5 <em>desabilitadas</em>)</td>
   <td>El valor debe coincidir con el patrón.</td>
   <td>Incumplimiento de restricción por <strong>incompatibilidad de patrones (Pattern mismatch)</strong></td>
  </tr>
  <tr>
   <td rowspan="3">{{ htmlattrxref("min", "input") }}</td>
   <td>range, number</td>
   <td>Un número válido</td>
   <td rowspan="3">El valor debe ser mayor o igual al de este atributo.</td>
   <td rowspan="3">Incumplimiento de restricción por <strong>flujo insuficiente (Underflow)</strong></td>
  </tr>
  <tr>
   <td>date, month, week</td>
   <td>Una fecha válida</td>
  </tr>
  <tr>
   <td>datetime, datetime-local, time</td>
   <td>Una fecha y hora válidos</td>
  </tr>
  <tr>
   <td rowspan="3">{{ htmlattrxref("max", "input") }}</td>
   <td>range, number</td>
   <td>Un número válido</td>
   <td rowspan="3">El valor debe ser menor o igual al de este atributo</td>
   <td rowspan="3">Incumplimiento de restricción por <strong>desborde (Overflow)</strong></td>
  </tr>
  <tr>
   <td>date, month, week</td>
   <td>Una fecha válida</td>
  </tr>
  <tr>
   <td>datetime, datetime-local, time</td>
   <td>Una fecha y hora válidos</td>
  </tr>
  <tr>
   <td>{{ htmlattrxref("required", "input") }}</td>
   <td>text, search, url, tel, email, password, date, datetime, datetime-local, month, week, time, number, checkbox, radio, file; también en los elementos {{ HTMLElement("select") }} y {{ HTMLElement("textarea") }}</td>
   <td><em>ninguno</em>, pues éste es un atributo de tipo Boolean: su presencia representa <em>true</em>, y su ausencia representa <em>false</em></td>
   <td>Debe tener un valor (si se establece).</td>
   <td>Incumplimiento de restricción por<strong> ausencia (Missing)</strong></td>
  </tr>
  <tr>
   <td rowspan="5">{{ htmlattrxref("step", "input") }}</td>
   <td>date</td>
   <td>Un número entero de días</td>
   <td rowspan="5">A menos que se establezca el atributo con la literal <span style="font-family: courier new;">any</span>, el valor debe ser <strong>min</strong> + un enter múltiplo del valor de este atributo.</td>
   <td rowspan="5">Incumplimiento de restricción por<strong> inconsistencia de paso (Step mismatch)</strong></td>
  </tr>
  <tr>
   <td>month</td>
   <td>Un número entero de meses</td>
  </tr>
  <tr>
   <td>week</td>
   <td>Un número entero de semanas</td>
  </tr>
  <tr>
   <td>datetime, datetime-local, time</td>
   <td>Un número entero de segundos</td>
  </tr>
  <tr>
   <td>range, number</td>
   <td>Un entero</td>
  </tr>
  <tr>
   <td>{{ htmlattrxref("maxlength", "input") }}</td>
   <td>text, search, url, tel, email, password; también en el elemento {{ HTMLElement("textarea") }}</td>
   <td>Una longitud en enteros</td>
   <td>El número de caracteres (puntos de código) no debe exceder el valor del atributo.</td>
   <td>Incumplimiento de restricción por ser<strong> muy largo (Too long)</strong></td>
  </tr>
 </tbody>
</table>

<h2 id="Proceso_de_validación_de_restricciones"><span class="author-g-by4vjwmiwjiydpj7">Proceso de validación de restricciones</span></h2>

<p>La validación de restricciones se hace a través de la API de Validación de Restricciones, ya sea en un elemento de formulario individual o a nivel de formulario, en el elemento {{ HTMLElement("form") }} mismo. La validación de restricciones se hace de las siguientes maneras:</p>

<ul>
 <li>Invocando a la función <code>checkValidity()</code> de una interfaz <a href="/es/docs/DOM" title="en/DOM">DOM</a> relacionada con formas (<code><a href="/es/docs/Web/API/HTMLInputElement" title="en/DOM/HTMLInputElement">HTMLInputElement</a></code>, <code><a href="/es/docs/Web/API/HTMLSelectElement" title="en/DOM/HTMLSelectElement">HTMLSelectElement</a></code>, <code><a href="/es/docs/Web/API/HTMLButtonElement" title="en/DOM/HTMLButtonElement">HTMLButtonElement</a></code><code><a href="/es/docs/Web/API/HTMLTextAreaElement" title="en/DOM/HTMLTextAreaElement">HTMLTextAreaElement</a></code>), la cual evalúa las restricciones para este elemento únicamente, permitiendo que un script obtenga esta información. (Esto lo hace comúnmente el agente usuario cuando determina cuál de las pseudo-clases <a href="/es/docs/Web/CSS" title="en/CSS">CSS</a>{{ Cssxref(":valid") }}{{ Cssxref(":invalid") }}, se aplicará.)</li>
 <li>Invocando a la función <code>checkValidity()</code> en la interfaz <code><a href="/es/docs/Web/API/HTMLFormElement" title="en/DOM/HTMLFormElement">HTMLFormElement</a></code>, llamada <em>validación estática de restricciones</em>.</li>
 <li>Enviando el formulario en sí, llamado <em>validación interactiva de restricciones</em>.</li>
</ul>

<div class="note"><strong>Nota: </strong>

<ul>
 <li>Si se establece el atributo {{ htmlattrxref("novalidate", "form") }} en el elemento {{ HTMLElement("form") }}, la validación interactiva de las restricciones no se aplica.</li>
 <li>Invocando al método <code>send()</code> en la interfaz <a href="/es/docs/Web/API/HTMLFormElement" title="en/DOM/HTMLFormElement">HTMLFormElement</a> no invoca a la validación de restricciones. en otras palabras, este método envía los datos del formulario al servidor aunque no se satisfagan las restricciones.</li>
</ul>
</div>

<h2 id="Restricciones_complejas_usando_la_API_de_Restricciones_de_HTML5"><span class="author-g-by4vjwmiwjiydpj7">Restricciones complejas usando la API de Restricciones de HTML5</span></h2>

<p><span class="author-g-by4vjwmiwjiydpj7">Usando JavaScript y la API de Restricciones, es posible implementar restricciones más complejas, por ejemplo, restricciones que combinen varios campos, o que involucren cálculos complejos.</span></p>

<p><span class="author-g-by4vjwmiwjiydpj7">Básicamente, la idea es ejecutar JavaScript en un evento de algún campo del formulario (como <strong>onchange</strong>) para calcular si la restricción no se cumple, y entonces usar el método <code><em>field</em>.setCustomValidity()</code> para establecer el resultado de la validación: una cadena vacía significa que la restricción se satisfizo, y cualquier otro texto significa que hay un error, siendo el texto el mensaje que se mostrará al usuario.</span></p>

<h3 id="Restricciones_que_combinan_varios_campos_Validación_de_código_postal">Restricciones que combinan varios campos: Validación de código postal</h3>

<p>El formato de código postal varía de un país a otro. No sólo la mayoría de los países permiten un prefijo opcional con el código del país (como <code>D-</code> en Alemania, <code>F-</code> en Francia o Suiza), sino que algunos países tienen códigos postales con solamente un número fijo de dígitos; otros, como el Reino Unido, tienen estructuras más complejas, permitiendo letras en posiciones específicas.</p>

<div class="note">
<p><strong>Nota:</strong> Esto no es una guía completa para una biblioteca de validación de código postal, sino más bien una demostración de conceptos clave.</p>
</div>

<p><span style="line-height: 1.5;">Como un ejemplo, añadiremos un script que verificará la validación de restricciones en este formulario simple:</span></p>

<pre class="brush: html notranslate">&lt;form&gt;
    &lt;label for="ZIP"&gt;Código postal : &lt;/label&gt;
    &lt;input type="text" id="ZIP"&gt;
    &lt;label for="Country"&gt;País : &lt;/label&gt;
    &lt;select id="Country"&gt;
      &lt;option value="ch"&gt;Suiza&lt;/option&gt;
      &lt;option value="fr"&gt;Francia&lt;/option&gt;
      &lt;option value="de"&gt;Alemania&lt;/option&gt;
      &lt;option value="nl"&gt;Países Bajos&lt;/option&gt;
    &lt;/select&gt;
    &lt;input type="submit" value="Validar"&gt;
&lt;/form&gt;</pre>

<p>Esto mostrará el siguiente formulario: </p>

<p><label>Código Postal : </label><input> <label>Country: </label><select><option value="ch">Suiza</option><option value="fr">Francia</option><option value="de">Alemania</option><option value="nl">Países Bajos</option></select></p>

<p>Primero, escribimos una función que revisará las restricciones en sí:</p>

<pre class="brush: js notranslate">function checkZIP() {
  // Para cada país, se define el patrón para el código postal
  var constraints = {
    ch : [ '^(CH-)?\\d{4}$', "El código postal de Suiza debe tener cuatro dígitos: p.ej. CH-1950 o 1950" ],
    fr : [ '^(F-)?\\d{5}$' , "El código postal de Francia debe tener cinco dígitos: p.ej. F-75012 o 75012" ],
    de : [ '^(D-)?\\d{5}$' , "El código postal de Alemania debe tener cinco dígitos: p-ej. D-12345 o 12345" ],
    nl : [ '^(NL-)?\\d{4}\\s*([A-RT-Z][A-Z]|S[BCE-RT-Z])$',
                    "El código postal de Países Bajos debe tener cuatro dígitos, seguidos de dos letras excepto SA, SD y SS" ]
  };

  // Se lee el ID del país
  var country = document.getElementById("Country").value;

  // Se obtiene el campo del código postal
  var ZIPField = document.getElementById("ZIP");

  // Se crea el validador de la restricción
  var constraint = new RegExp(constraints[country][0], "");
    console.log(constraint);


  // ¡Se hace la revisión!
  if (constraint.test(ZIPField.value)) {
    // El código postal cumple la restricción, usamos la API de Restricciones para indicarlo
    ZIPField.setCustomValidity("");
  }
  else {
    // El código postal no cumple la restricción, usamos la API de Restricciones para
    // dar un mensaje sobre el formato requerido para este país
    ZIPField.setCustomValidity(constraints[country][1]);
  }
}
</pre>

<p>Entonces, enlazamos este código al evento <strong>onchange</strong> del elemento {{ HTMLElement("select") }} y al evento <strong>oninput</strong> del elemento {{ HTMLElement("input") }}:</p>

<pre class="brush: js notranslate">window.onload = function () {
    document.getElementById("Country").onchange = checkZIP;
    document.getElementById("ZIP").oninput = checkZIP;
}</pre>

<p>Puedes ver <a href="/@api/deki/files/4744/=constraint.html" title="https://developer.mozilla.org/@api/deki/files/4744/=constraint.html">aquí un ejemplo en vivo</a> de la validación de código postal.</p>

<h3 id="Limitando_el_tamaño_de_un_archivo_antes_de_ser_subido">Limitando el tamaño de un archivo antes de ser subido</h3>

<p>Otra restricción común es limitar el tamaño de un archivo que será subido. Verificar esto de lado del cliente antes de que el archivo sea transmitido al servidor requiere combinar la API de Validación de Restricciones, y especialmente la función field.setCustomValidity(), con otra API de JavaScript, la File API.</p>

<p>Aquí está la parte de HTML:</p>

<pre class="brush: html notranslate">&lt;label for="FS"&gt;Selecciona un archivo menor a 75KB : &lt;/label&gt;
&lt;input type="file" id="FS"&gt;</pre>

<p>Esto muestra lo siguiente:</p>

<p><label>Seleciona un archivo menor a 75KB : </label> <input></p>



<p>Con JavaScript, leemos el archivo seleccionado, usamos el método File.size() para obtener su tamaño, lo comparamos con el límite fijo (hard coded), y llamamos a la API de Validación de Restricciones para informar al navegador si no se cumple la restricción:</p>

<pre class="brush: js notranslate">function checkFileSize() {
  var FS = document.getElementById("FS");
  var files = FS.files;

  // Si hay (por lo menos) un archivo seleccionado
  if (files.length &gt; 0) {
     if (files[0].size &gt; 75 * 1024) { // Validar la restricción
       FS.setCustomValidity("El archivo seleccionado no debe ser mayor a 75KB");
       return;
     }
  }
  // No hay incumplimiento de la restricción
  FS.setCustomValidity("");
}</pre>



<p>Finalmente, anclamos el método al evento requerido:</p>

<pre class="brush: js notranslate">window.onload = function () {
  document.getElementById("FS").onchange = checkFileSize;
}</pre>

<p>Puedes ver <a href="/@api/deki/files/4745/=fileconstraint.html" title="https://developer.mozilla.org/@api/deki/files/4745/=fileconstraint.html">aquí un ejemplo en vivo</a> de la validación de tamaño de archivos.</p>

<h2 id="Estilos_visuales_de_validación_de_restricciones"><span class="author-g-by4vjwmiwjiydpj7">Estilos visuales de validación de restricciones</span></h2>

<p>Aparte de establecer las restricciones, los desarrolladores web querrán controlar los mensajes que son desplegados al usuario y los estilos de los mismos.</p>

<h3 id="Controlando_el_aspecto_de_los_elementos">Controlando el aspecto de los elementos</h3>

<p>El aspecto de los elementos puede ser controlado por medio de pseudo-clases de CSS.</p>

<h4 id="Pseudo-clases_required_y_optional">Pseudo-clases :required y :optional</h4>

<p>Las <a href="/es/docs/Web/CSS/Pseudo-classes" title="Pseudo-classes">pseudo-clases</a> <a href="/en-US/docs/Web/CSS/:required" title=":required"><code>:required</code></a> y <a href="/en-US/docs/Web/CSS/:optional" title=":optional"><code>:optional</code></a> permitene escribir selectores que coincidan con elementos de formulario que tengan el atributo {{ htmlattrxref("required") }} y los que no lo tengan, respectivamente.</p>

<h4 id="Pseudo-clase_-moz-placeholder">Pseudo-clase :-moz-placeholder</h4>

<p>Véase <a href="/es/docs/Web/CSS/::placeholder" title="/en-US/docs/Web/CSS/:-moz-placeholder">::placeholder</a> (experimental).</p>

<h4 id="Pseudo-clases_valid_invalid">Pseudo-clases :valid :invalid</h4>

<p>Las <a href="/es/docs/Web/CSS/Pseudo-classes" title="/en-US/docs/Web/CSS/Pseudo-classes?redirectlocale=en-US&amp;redirectslug=CSS%2FPseudo-classes">pseudo-clases</a> <a href="/en-US/docs/Web/CSS/:valid" title="/en-US/docs/Web/CSS/:valid">:valid</a> e <a href="/en-US/docs/Web/CSS/:invalid" title="/en-US/docs/Web/CSS/:invalid?redirectlocale=en-US&amp;redirectslug=CSS%2F%3Ainvalid">:invalid</a> son usadas para representar elementos &lt;input&gt; cuyo contenido es válido o inválido, respectivamente, acorde a las configuraciones de captura. Estas clases permiten al usuario estilizar elementos de formulario válidos e inválidos, para hacer más fácil el identificar elementos que tienen valores correctos o incorrectos.</p>

<h4 id="Estilos_predeterminados">Estilos predeterminados</h4>

<h3 id="Controlando_el_texto_de_incumplimiento_de_restricciones">Controlando el texto de incumplimiento de restricciones</h3>

<h4 id="El_atributo_x-moz-errormessage">El atributo x-moz-errormessage</h4>

<p>El atributo x-moz-errormessage es una extensión de Mozilla que te permite especificar el mensaje de error que se mostrará cuando un campo no es validado exitosamente.</p>

<div class="note">
<p style="margin-left: 40px;">Nota: Esta extensión no es estándar.</p>
</div>

<h4 id="element.setCustomValidity_de_la_API_de_Validación_de_Restricciones">element.setCustomValidity() de la API de Validación de Restricciones</h4>

<p>El método element.setCustomValidity(error) es usado para establecer un mensaje de error personalizado para mostrar cuando el formulario es enviado. El método toma una cadena de texto como parámetro con el error. Si el error es una cadena no vacía, el método asume que la validación no fue exitosa, y despliega el mensaje con el error indicado. Si el error es una cadena vacía, el elemento es considerado válido, y restablece el mensaje de error.</p>

<h4 id="Objeto_ValidityState_de_la_API_de_Validación_de_Restricciones"><span class="author-g-by4vjwmiwjiydpj7">Objeto ValidityState</span> de la API de Validación de Restricciones</h4>

<p>La interfaz de DOM <code><a href="/es/docs/Web/API/ValidityState">ValidityState</a></code><a href="/es/docs/Web/API/ValidityState"> </a>representa los <em>estados de validez</em> en los que puede estar un elemento, respecto a la validación de restricciones. En conjunto, ayudan a explicar por qué el valor de un elemento falló en la validación, si no es válido.</p>

<h3 id="Examples_of_personalized_styling"><span class="author-g-by4vjwmiwjiydpj7">Examples of personalized styling</span></h3>

<h3 id="HTML4_fallback"><span class="author-g-by4vjwmiwjiydpj7">HTML4 fallback</span></h3>

<h4 id="Trivial_fallback"><span class="author-g-by4vjwmiwjiydpj7">Trivial fallback</span></h4>

<h4 id="JS_fallback"><span class="author-g-by4vjwmiwjiydpj7">JS fallback</span></h4>

<h2 id="Conclusión"><span class="author-g-by4vjwmiwjiydpj7">Conclusión</span></h2>