Formulare web 2 - Stilizarea formularelor web
Am analizat toate elementele HTML de care avem nevoie, pentru a crea și structura formularele web. Acum, deși nu ați studiat încă CSS, vom trece la analizarea modului de utilizare a codului CSS pentru a stiliza controalele de formular. Vă recomand să vizitați din nou aceste articole, mai târziu, după ce veți fi studiat CSS, pentru a înțelege cât mai bine informațiile prezentate. Stilizarea controalelor de formular nu a fost un lucru foarte simplu, dar este din ce în ce mai ușor de realizat, pe măsură ce browserele vechi sunt retrase și browserele moderne ne oferă mai multe funcții de utilizat.
Nu toate widget-urile sunt egale în ceea ce privește stilizarea lor cu CSS.
În prezent, există încă unele probleme și, în funcție de aceste probleme, pot fi identificate trei categorii:
Relativ ușor de stilizat.
Aceste elemente pot fi stilizate fără dificultăți foarte mari. Acestea includ următoarele elemente:
- <form>,
- <fieldset> și <legend>
- tot ce înseamnă o singură linie de text creată cu <input> (type text, url, email, etc.), inclusiv <input type="search">,
- <textarea>
- Butoanele create cu <input> și <button>,
- <label>
- <output>
Relativ greu de stilizat.
Unele elemente sunt mai greu de stilizat, necesitând cod CSS mai complex sau câteva trucuri specifice:
- casetele de selectare și butoanele radio,
- elemente implicite precum <select>, care necesită soluții personalizate pentru un control complet al stilului,
Foarte greu de stilizat.
Aceste elemente nu pot fi stilizate în totalitate folosind CSS:
- <input type="color">,
- controale legate de data, precum <input type="datetime-local">,
- <input type="range">,
- <input type="file">,
- Elemente implicate în crearea de widget-uri derulante, inclusiv <select>, <option>, <optgroup> și <datalist>
- <progress> și <meter>
Vom discuta despre ce se poate face în ceea ce privește stilizarea acestor elemente în "Metode avansate de stilizare a formularelor web".
Adevărata problemă cu toate aceste controale este că au o structură foarte complexă și, dincolo de unele stiluri de bază (cum ar fi schimbarea lățimii sau marginii controlului), în general, nu avem cum să stilizăm componentele interne ale controalelor care alcătuiesc aceste widget-uri.
Dacă totuși doriți să personalizați mai mult aceste widget-uri, trebuie să vă creați propriile widget-uri de la zero cu ajutorul HTML, CSS și JavaScript.
☞ Există unele pseudo-elemente CSS disponibile, care vă permit să modelați componentele interne ale acestor controale de formular, cum ar fi ::-moz-range-track sau ::-webkit-slider-thumb, dar acestea nu sunt suportate de toate browserele, deci nu pot fi utilizate în mod fiabil.
Elemente relativ ușor de stilizat
Câteva informații despre aspecte specifice ale stilizării formularelor, care merită menționate.
Fontul și textul
Proprietățile de font și text CSS pot fi utilizate cu ușurință pe orice widget (puteți utiliza chiar și @font-face). Cu toate acestea, comportamentul în browsere este adesea inconsistent. În mod implicit, unele widget-uri nu moștenesc (inherit) familia de fonturi și dimensiunea fontului de la părinții lor. Multe browsere folosesc în schimb aspectul implicit al sistemului. Pentru ca aspectul formularelor să fie în concordanță cu restul conținutului, putem adăuga următoarele reguli în foaia de stil:
button, input, select, textarea {
font-family: inherit;
font-size: 100%;
}
Există multe dezbateri cu privire la faptul că formularele arată mai bine folosind stilurile implicite ale sistemului sau folosind stiluri personalizate concepute pentru a se potrivi cu conținutul. Această decizie trebuie să o luați personal, în calitate de designer al site-ului.
Box sizing-Dimensionarea cutiei
Toate câmpurile de text au suport complet pentru fiecare proprietate legată de modelul cutiei CSS, cum ar fi lățimea, înălțimea, umplutura, marginea și chenarul (width, height, padding, margin, și border). La fel ca înainte, browserele se bazează pe stilurile implicite ale sistemului atunci când afișează aceste widget-uri. Depinde de dvs. să definiți cum doriți să le combinați în conținutul dvs. Dacă doriți să păstrați aspectul nativ al widget-urilor, veți întâmpina o mică dificultate dacă doriți să le oferiți o dimensiune consistentă.
Acest lucru se datorează faptului că fiecare widget are propriile reguli pentru chenar, umplutură și margine. Pentru a da aceeași dimensiune mai multor widget-uri diferite, puteți utiliza proprietatea de dimensionare a cutiilor împreună cu unele valori consistente pentru alte proprietăți:
button, input, select, textarea {
width: 150px;
padding: 0;
margin: 0;
box-sizing: border-box;
}
Plasament legenda
Elementul legend este usor de stilizat, dar poate fi un pic complicat să controlezi plasarea acestuia. În mod implicit, acesta este întotdeauna poziționat peste chenarul superior a parintelui sau fieldset, lângă colțul din stânga sus. Pentru a o poziționa în altă parte, de exemplu în interiorul câmpului undeva sau în colțul din stânga jos, trebuie să vă bazați pe poziționare.
Sa ne uitam la următoarele exemple:
Pentru a poziționa legenda în acest mod, am folosit următoarele linii de cod CSS:
fieldset {
position: relative;
}
legend {
position: absolute;
bottom: 0;
right: 0;
}
De asemenea, fieldset trebuie să fie poziționat, astfel încât legend să fie poziționat în raport cu acesta (altfel legend ar fi poziționat în raport cu elementul body).
Elementul legend este foarte important pentru accesibilitate - este vocalizat de tehnologiile de asistență ca parte a etichetei fiecărui element de formular din cadrul fieldset - dar utilizarea unei tehnici ca cea de mai sus este în regulă. Conținutul legendei va fi vocalizat în același mod, schimbarea produsa este doar vizuala.
Metode avansate de stilizare a formularelor web
În acest articol, vom vedea ce se poate face cu CSS pentru a stiliza controalele de formular care sunt mai greu de stilizat.
Să vorbim mai întâi despre proprietatea CSS appearance, care este destul de utilă, pentru a face elementele greu de stilizat, ceva mai stilizabile.
Controlul stilului la nivel de sistem de operare
Proprietatea appearance a fost creată ca o modalitate de a controla modul in care sistemele de operare influenteaza stilizarea controalelor de formulare web. Din păcate, comportamentul implementărilor inițiale ale acestei proprietăți a fost foarte diferit în cadrul browserelor, ceea ce nu era foarte folositor. Implementările mai noi sunt mai consistente în comportament - browserele bazate pe Chromium (Chrome, Opera, Edge), Safari și Firefox acceptă toate versiunea prefixată -webkit-. Firefox a rezolvat acest lucru, deoarece dezvoltatorii web păreau în mare parte să folosească versiunea prefixată -webkit-, deci era mai bine pentru compatibilitate.
Dacă te uiți la pagina de referință, de pe MDN web docs, vei vedea listate, o mulțime de valori posibile pentru aspectul -webkit-ului, însă, de departe, cea mai utilă valoare, și probabil singura pe care o vei folosi, este none. Acest lucru oprește orice control pe care îl folosiți de la utilizarea stilizarii la nivel de sistem de operare, pe cât posibil, și vă permite să creați singuri stiluri personalizate folosind CSS.
De exemplu, să luăm următoarele controale:
<form>
<p>
<label for="search">search: </label>
<input id="search" name="search" type="search">
</p>
<p>
<label for="text">text: </label>
<input id="text" name="text" type="text">
</p>
<p>
<label for="date">date: </label>
<input id="date" name="date" type="datetime-local">
</p>
<p>
<label for="radio">radio: </label>
<input id="radio" name="radio" type="radio">
</p>
<p>
<label for="checkbox">checkbox: </label>
<input id="checkbox" name="checkbox" type="checkbox">
</p>
<p><input type="submit" value="submit"></p>
<p><input type="button" value="button"></p>
</form>
Aplicarea următoarelor linii de cod CSS elimină stilul la nivel de sistem de operare:
input {
-webkit-appearance: none;
appearance: none;
}
☞ Este o idee bună să includeți întotdeauna ambele declarații - prefixate și neprefixate - atunci când utilizați o proprietate prefixată. Prefixat înseamnă, de obicei, „lucru în desfășurare”, astfel că, în viitor, furnizorii de browsere pot ajunge la un consens pentru a renunța la prefix.
Următorul exemplu vă arată cum sunt redate controalele de sistemul dvs. - implicit în stânga și cu regula CSS de mai sus aplicata, în dreapta:
În cele mai multe cazuri, efectul este de a elimina chenarul stilizat, ceea ce face ca stilizarea cu CSS să fie ceva mai ușor de aplicat, dar nu este esențial. În câteva cazuri - pentru search, radio button și checkbox, devine mult mai util.
Modificarea casetelor de căutare
<input type = "search"> este practic doar un input de text, deci de ce este appearance: none; util in acest caz? Răspunsul este că în browserele bazate pe Chromium, casetele de căutare au anumite restricții de stil - nu putem ajusta înălțimea lor, de exemplu.
Aceasta problema poate fi rezolvată folosind appearance: none;:
input[type="search"] {
-webkit-appearance: none;
appearance: none;
}
În exemplul de mai jos, puteți vedea două căsuțe de căutare cu stil identic. Cel din dreapta are aplicat appearance: none;, iar cel din stânga nu. Dacă vizualizati pagina în Chrome, veți vedea că cel din stânga nu este dimensionat corespunzător.
Interesant este că setarea border/background pe câmpul de căutare pare să rezolve și această problemă. Următoarea intrare de căutare nu are aplicat appearance: none;, dar nu suferă de aceeași problemă în Chrome ca și exemplul precedent.
Stilizarea casetelor de selectare și a butoanelor radio
Stilizarea unei căsuțe de selectare sau a unui buton radio este complicată în mod implicit. Dimensiunile casetelor de selectare și ale butoanelor radio nu sunt menite să fie modificate cu stilurile lor implicite, iar browserele reacționează foarte diferit atunci când încercați.
Sa ne uitam la urmatorul exemplu simplu:
<span><input type="checkbox"></span>
span {
display: inline-block;
background: red;
}
input[type="checkbox"] {
width: 100px;
height: 100px;
}
Diferite browsere afiseaza în mod diferit:
appearence: none pentru casete de selectare și butoane radio
Sa incepem cu un exemplu:
<form>
<fieldset>
<legend>Fructe preferate</legend>
<p>
<label>
<input type="checkbox" name="fruit-1" value="cherry">
Imi plac ciresele
</label>
</p>
<p>
<label>
<input type="checkbox" name="fruit-2" value="banana" disabled>
Nu-mi plac bananele
</label>
</p>
<p>
<label>
<input type="checkbox" name="fruit-3" value="strawberry">
Imi plac capsunile
</label>
</p>
</fieldset>
</form>
Acum, haideți să utilizam un design personalizat pentru caseta de selectare. Să începem cu o destilizare:
input[type="checkbox"] {
-webkit-appearance: none;
appearance: none;
}
Putem folosi pseudo-clasele :checked și :disabled pentru a schimba aspectul casetei, deoarece starea acesteia se schimbă:
input[type="checkbox"] {
position: relative;
width: 1em;
height: 1em;
border: 1px solid gray;
/* Ajustam pozitia casetei in raport cu textul */
vertical-align: -2px;
color: green;
}
input[type="checkbox"]::before {
content: "✔";
position: absolute;
font-size: 1.2em;
right: -1px;
top: -0.3em;
visibility: hidden;
}
input[type="checkbox"]:checked::before {
/* Utilizam "visibility" in loc de "display" pentru a evita recalcularea layout-ului */
visibility: visible;
}
input[type="checkbox"]:disabled {
border-color: black;
background: #ddd;
color: gray;
}
Pseudo-clasele din exemplul de mai sus au rolul:
- :checked (bifat) - caseta de selectare (sau butonul radio) este într-o stare verificată - utilizatorul a făcut clic pe / a activat-o.
- :disabled (dezactivat) - caseta de selectare (sau butonul radio) este într-o stare dezactivată - nu se poate interacționa cu acestea.
De asemenea, am creat câteva exemple pentru a vă oferi mai multe idei:
Dacă vedeți aceste casete de selectare într-un browser care nu acceptă appearance, designul personalizat va fi pierdut, dar acestea vor arăta în continuare ca niște casete de selectare și vor putea fi utilizate.
Ce putem face cu elementele greu de stilizat?
Acum, să ne îndreptăm atenția asupra controalelor "urâte" - cele care sunt cu adevărat greu de stilizat. Pe scurt, acestea sunt casetele derulante, tipuri de control complexe, cum ar fi color, datetime-local, și controale orientate către feedback, cum ar fi progress și meter.
Problema este că aceste elemente au aspecte implicite foarte diferite în browsere și pot fi stilizate intr-o anumita masura, insa unele părți componente sunt literalmente imposibile de stilizat.
Următorul exemplu, arată o serie de caracteristici ale controalelor neaspectuoase în acțiune:
Puteti deschide pagina de mai sus in diferite browsere pentru a observa diferentele de redare si de asemenea puteti vizualiza codul sursa al paginii, pentru a analiza codul CSS utilizat.
După cum ați putut observa, controalele din exemplul de mai sus, arata destul de bine si se comporta destul de uniform în browserele moderne. Am aplicat unele proprietati CSS de normalizare globală la toate controalele și etichetele lor, pentru a le aduce la dimensiuni similare și pentru a adopta fontul părintelui.
button, label, input, select, progress, meter {
display: block;
font-family: inherit;
font-size: 100%;
padding: 0;
margin: 0;
box-sizing: border-box;
width: 100%;
padding: 5px;
height: 30px;
}
De asemenea, am adăugat câteva umbre și am rotunjit colțurile, la controalele la care avea sens sa facem acest lucru:
input[type="text"], input[type="datetime-local"], input[type="color"], select {
box-shadow: inset 1px 1px 3px #ccc;
border-radius: 5px;
}
Să vorbim acum despre unele specificitati ale fiecăruia dintre aceste tipuri de control, evidențiind dificultățile care pot sa apara.
Select și datalist
Două lucruri sunt ceva mai problematice. În primul rând, pictograma "săgeată" care indică faptul că este un dropdown diferă între browsere. De asemenea, tinde să se schimbe dacă creșteți dimensiunea casetei selectate sau o redimensionați. Pentru a remedia acest lucru în exemplul nostru, am folosit mai întâi vechiul nostru prieten appearance: none pentru a scăpa de pictograma cu totul:
select {
-webkit-appearance: none;
appearance: none;
}
Am creat apoi propria noastră pictogramă folosind conținut generat. Am pus un strat suplimentar în jurul controlului, deoarece :: before / :: after nu funcționează pe elementele select (deoarece conținutul generat este plasat în raport cu caseta de formatare a unui element):
<div class="select-wrapper">
<select id="select" name="select">
<option>Banana</option>
<option>Cherry</option>
<option>Lemon</option>
</select>
</div>
Apoi folosim conținut generat pentru a genera o săgeată în jos și o așezăm la locul potrivit folosind poziționarea:
.select-wrapper {
position: relative;
}
.select-wrapper::after {
content: "▼";
font-size: 1rem;
top: 6px;
right: 10px;
position: absolute;
}
A doua problemă, ceva mai importantă, este aceea că nu aveți control asupra căsuței care apare și conține opțiunile atunci când faceți clic pe caseta select pentru a o deschide. Veți observa că opțiunile nu moștenesc fontul setat pe părinte. De asemenea, nu puteți seta în mod constant lucruri precum distanțarea și culorile. De exemplu, Firefox va aplica culoarea și culoarea de fundal atunci când este setat pe elementele option, dar Chrome nu va face acest lucru. Niciunul dintre browsere nu va aplica nici un fel de spațiere (de exemplu, padding). Același lucru este valabil și pentru autocomplete list care apare pentru datatalist.
Dacă aveți nevoie într-adevăr de control complet asupra stilului, va trebui să utilizați fie un fel de bibliotecă pentru a genera un control personalizat, fie să vă construiți propriul control personalizat, fie în cazul select, utilizați atribute multiplu, ceea ce face ca toate opțiunile sa apara in pagină, evitând această problemă:
<select id="select" name="select" multiple>
...
</select>
Tipuri de introducere a datei
Tipurile de intrare dată / oră (datetime-local, ora, săptămâna, luna) au aceeași problemă principală asociată. Caseta este la fel de ușor de stilizat ca orice introducere de text (text input), iar ceea ce avem în exemplul de mai sus arată bine.
Cu toate acestea, componentele interne ale controlului (de exemplu, calendarul pop-up pe care îl utilizați alege o dată, spinner-ul pe care îl puteți utiliza pentru a creste / descrește valorile) nu sunt deloc stilizabile și nu puteți scăpa de ele folosind appearence: none;. Dacă aveți nevoie într-adevăr de control complet asupra stilului, va trebui să utilizați fie un fel de bibliotecă pentru a genera un control personalizat, fie să vă construiți propriul widget.
Tipul de intrare range
<input type = "range"> este enervant de greu de stilizat. Puteți utiliza ceva de genul următor pentru a elimina complet traseul glisorului implicit și a-l înlocui cu un stil personalizat (un marcaj roșu subțire, în acest caz):
input[type="range"] {
appearance: none;
-webkit-appearance: none;
background: red;
height: 2px;
padding: 0;
outline: 1px solid transparent;
}
Tipul de introducere color
Controalele de intrare pentru culoare nu stau prea rau. În sprijinul browserelor, acestea tind să vă ofere doar un bloc de culoare solidă cu un chenar mic. Puteți elimina chenarul, lăsând doar blocul de culoare, folosind așa ceva:
input[type="color"] {
border: 0;
padding: 0;
}
Tipul de introducere file
Singura problemă cu controlul de selectare a fișierelor este că butonul pe care apăsați pentru a deschide selectorul de fișiere este complet nestilizabil - nu poate fi dimensionat sau colorat și nici nu va accepta un font diferit.
O modalitate este să profitați de faptul că dacă aveți o etichetă asociată unui control de formular, faceți clic pe etichetă pentru a activa controlul. Așadar, puteți ascunde cu totul intrarea folosind așa ceva:
input[type="file"] {
height: 0;
padding: 0;
opacity: 0;
}
Și apoi stilizam eticheta să acționeze ca un buton, care atunci când este apăsat, va deschide selectorul de fișiere așa cum este de așteptat:
label[for="file"] {
box-shadow: 1px 1px 3px #ccc;
background: linear-gradient(to bottom, #eee, #ccc);
border: 1px solid rgb(169, 169, 169);
border-radius: 5px;
text-align: center;
line-height: 1.5;
}
label[for="file"]:hover {
background: linear-gradient(to bottom, #fff, #ddd);
}
label[for="file"]:active {
box-shadow: inset 1px 1px 3px #ccc;
}
Contoare și bare de progres
<meter> și <progress> sunt probabil cele mai cele mai enervante. După cum ați văzut în exemplul anterior, le putem seta pe o lățime dorită relativ exact. Dar, dincolo de asta, sunt cu adevărat dificile de stilizat în orice fel. Nu suportă setările de înălțime, în mod consistent în browsere, puteți colora fundalul, dar nu bara de prim plan și prietenul nostru appearance: none înrăutățește lucrurile.
Este mai ușor să creezi propria ta soluție personalizată pentru aceste funcții, dacă vrei să poți controla stilul sau să folosești un script javascript, cum ar fi progressbar.js
Librarii utile si polyfills
Un polyfill, sau polyfiller, este o bucată de cod (sau plugin) care furnizează tehnologia pe care tu, dezvoltatorul, te aștepți ca browserul să o ofere nativ.
După cum am menționat mai sus, dacă doriți să obțineți un control complet asupra tipurilor de control "urâte", nu aveți de ales decât să vă bazați pe JavaScript.
Există câteva biblioteci foarte utile care vă pot ajuta:
- Uni-form - este un framework care standardizează marcarea formularului, stilizându-l cu CSS. De asemenea, oferă câteva funcții suplimentare atunci când este utilizat cu jQuery, dar este opțional.
- Formalize - este o extensie la framework-urile JavaScript comune (cum ar fi jQuery, Dojo, YUI etc.) care ajută la normalizarea și personalizarea formularelor.
- jQuery UI - oferă widget-uri personalizabile, cum ar fi selectoarele de date (cu o atenție deosebită acordată accesibilității).
- Twitter Bootstrap - vă poate ajuta să vă normalizați formularele.
- WebShim - este un instrument uriaș, care vă poate ajuta in ceea ce priveste suportul pentru HTML5 al browserelor. Partea care tine de formulare poate fi foarte utilă.
Pseudo-clase UI
Cum am precizat si mai sus, nu este neaparata nevoie sa parcurgeti acest articol in acest moment. Puteti reveni aici dupa ce ati studiat și ati dobindit o buna intelegere a CSS.
În acest articol, vom explora în detaliu diferitele pseudo-clase UI disponibile pentru noi în browserele moderne pentru stilizarea formularelor aflate în diferite stari.
Ce pseudo-clase avem la dispozitie?
Pseudo-clasele disponibile pentru noi și care sunt relevante pentru formulare sunt:
- :hover - selectează un element numai atunci când se trece cu indicatorul de mouse pe deasupra acestuia.
- :focus - selectează un element numai atunci când este focalizat (atunci cind este selectat folosind tasta TAB a tastaturii).
- :active - selectează un element doar atunci când acesta este activat (adică în timp ce se face clic pe sau când se apasă tasta ENTER în cazul unei activări prin intermediul tastaturii).
- :required și :optional - targheteaza controale de formular necesare sau opționale.
- :valid / :invalid și :in-range / :out-of-range - targheteaza controale de formular care sunt valide / invalide în funcție de constrângerile de validare setate pe acestea sau care sunt în raza de acțiune / în afara razei.
- :enabled / :disabled și :read-only / :read-write - targheteaza controale de formular activate sau dezactivate (de exemplu, cu setul de atribute HTML dezactivat) și controale de formulare de citire-scriere sau numai de citire (de exemplu, cu setul de atribute HTML readonly).
- :checked, :indeterminate și :default - targheteaza casetele de selectare și butoanele radio care sunt bifate (checked), sunt într-o stare nedeterminată (nici bifată sau nici verificată) și opțiunea implicită selectată atunci când pagina se încarcă (de ex. Un <input type = "checkbox"> cu setul de atribute bifat sau un element option cu setul de atribute selectat).
Există și multe altele, dar cele enumerate mai sus sunt, evident, cele mai utile și au un suport de browser destul de bun, dar, bineînțeles, ar trebui să testați cu atenție implementările de formular pentru a vă asigura că funcționează pentru publicul țintă.
Stilizarea input în funcție de obligativitatea introducerii datelor
Unul dintre cele mai de bază concepte, în ceea ce privește validarea formularului pe partea de client, se refera la necesitatea introducerii datelor înainte de a putea trimite formularul.
Elementele <input>, <select> și <textarea> au la dispoziție un atribut required care, atunci când este setat, înseamnă că trebuie să completați controlul respectiv înainte ca formularul să poata fi trimis cu succes. De exemplu:
<form>
<fieldset>
<legend>Contact</legend>
<div>
<label for="fname">Nume: </label>
<input id="fname" name="fname" type="text" required>
</div>
<div>
<label for="lname">Prenume: </label>
<input id="lname" name="lname" type="text" required>
</div>
<div>
<label for="email">Adresa e-mail (include adresa daca doresti un raspuns): </label>
<input id="email" name="email" type="email">
</div>
<div><button>Trimite</button></div>
</fieldset>
</form>
Numele și prenumele sunt obligatorii (:required), dar adresa de e-mail este opțională (:optional).
Puteți targheta cele două stări folosind pseudo-clasele :required și :optional. De exemplu, dacă aplicăm următoarele linii CSS la HTML-ul de mai sus:
input:required {
border: 2px solid red;
}
input:optional {
border: 2px solid green;
}
obtinem urmatorul rezultat:
Puteți încerca, să trimiteți formularul fără să îl completați, pentru a vedea mesajul de eroare implicit, pe care browserul îl afiseaza, atunci cind valideaza datele pe partea de client.
Formularul de mai sus nu este rau, dar nici nu este prea grozav. Pentru început, semnalăm ce este obligatoriu si ce este opțional folosind doar culoarea, ceea ce nu este folositor pentru persoanele nevăzătoare. În al doilea rând, convenția standard de pe web pentru cimpurile obligatorii este un asterisc (*), sau cuvântul "necesar" asociate cu controalele în cauză. În următoarea secțiune, vom analiza un exemplu mai bun de semnalare a câmpurilor obligatorii folosind :required si vom face acest lucru prin utilizarea conținutului generat.
☞ Probabil că nu vei folosi pseudo-clasa :optional foarte des.
Controalele de formulare sunt opționale implicit, astfel încât puteți adăuga stiluri doar pentru controalele
necesare.
Dacă un buton radio dintr-un grup de butoane cu acelasi nume, are atributul required,
toate butoanele radio vor fi invalide până cind unul este selectat, dar numai cel cu atributul setat se va
potrivi de fapt cu :required.
Utilizarea conținutului generat cu ajutorul pseudo-claselor
În articolele anterioare am văzut utilizarea conținutului generat, dar acum ar fi un moment bun pentru a vorbi despre asta un pic mai detaliat.
Ideea este că putem folosi pseudo-elementele ::before și ::after împreună cu proprietatea conținutului pentru a face ca un fragment de conținut să apară înainte sau după elementul afectat. Partea de conținut nu este adăugată la DOM, deci este invizibilă pentru screenreaders - este parte din stilul aplicat documentului. Deoarece este un pseudo element, poate fi stilizat în același mod in care targhetam orice nod real din DOM.
Acest lucru este cu adevărat util când doriți să adăugați un indicator vizual la un element, cum ar fi o etichetă sau o pictogramă, dar nu doriți ca acesta să fie observat de tehnologiile de asistență. In exemplul nostru de butoane radio personalizate, folosim conținut generat pentru a gestiona plasarea și animarea cercului interior atunci când este selectat un buton radio:
input[type="radio"]::before {
display: block;
content: " ";
width: 10px;
height: 10px;
border-radius: 6px;
background-color: red;
font-size: 1.2em;
transform: translate(3px, 3px) scale(0);
transform-origin: center;
transition: all 0.3s ease-in;
}
input[type="radio"]:checked::before {
transform: translate(3px, 3px) scale(1);
transition: all 0.3s cubic-bezier(0.25, 0.25, 0.56, 2);
}
Acest lucru este cu adevărat util - tehnologiile de asistență anunță deja utilizatorii lor, atunci când un buton radio sau o caseta de selectare, este selectat/bifata, pentru ca nu dorim să citească un alt element DOM care indică selecția, pentru a evita confuzia. Existenta unui indicator pur vizual rezolvă această problemă.
☞ Acest lucru arată, de asemenea, cum puteți combina o pseudo-clasă și un pseudo-element, dacă este necesar.
Înapoi la exemplul nostru required/optional de mai înainte, de data aceasta nu vom modifica aspectul intrării în sine - vom folosi conținutul generat pentru a adăuga o etichetă indicatoare.
În primul rând, vom adăuga un paragraf în partea de sus a formularului:
<p>Cimpurile obligatorii au eticheta "obligatoriu".</p>
Utilizatorii de screenreader vor auzi "obligatoriu" ca un bit suplimentar de informație, atunci când ajung la fiecare intrare necesară, iar utilizatorii fara probleme de vedere vor putea vedea eticheta.
Întrucât intrările de formular nu acceptă în mod direct conținut generat setat pe ele (aceasta se datorează faptului că, conținutul este plasat în raport cu caseta de formatare a unui element, dar intrările de formular funcționează similar cu elementele înlocuite, deci nu au o caseta proprie), vom adăuga un element gol <span> pentru a seta conținutul generat pe acesta:
<div>
<label for="fname">Nume: </label>
<input id="fname" name="fname" type="text" required>
<span></span>
</div>
Problema imediată care apare, este ca elementul span cade pe o nouă linie sub input, deoarece intrarea și eticheta sunt ambele setate cu lățimea: 100%. Pentru a remedia acest lucru, transformam elementul părinte div intr-un container flex, caruia îi spunem să extinda conținutul pe o linie noua, dacă acesta devine prea lung:
fieldset > div {
margin-bottom: 20px;
display: flex;
flex-flow: row wrap;
}
Rezultatul este că eticheta și intrarea sunt așezate pe linii separate, deoarece ambele au o lățime de: 100%, dar span are o lățime de 0, astfel încât să poată sta pe aceeași linie cu input.
Acum creăm conținutul generat folosind urmatoarele linii de cod CSS:
input + span {
position: relative;
}
input:required + span::after {
font-size: 0.7rem;
position: absolute;
content: "obligatoriu";
color: white;
background-color: black;
padding: 5px 10px;
top: -26px;
left: -70px;
}
Setăm span pe position: relative;, doar pentru a putea seta conținutul generat pe position: absolute;, pentru a fi poziționat în raport cu span și nu cu body (conținutul generat acționează ca și cum ar fi un nod copil a elementului pe care este generat, în scopul poziționării).
Apoi, oferim conținutului generat, textul "obligatoriu", apoi stilizam și poziționam așa cum dorim. Rezultatul se vede mai jos:
Stilizarea controalelor pe baza validitatii datelor introduse
Un concept important, fundamental, în validarea formularelor, se refera la validitatea datelor introduse intr-un control de formular. Controalele de formulare cu limitări de constrângere pot fi targhetate pe baza acestor stări:
:valid sau :invalid
Sunt câteva lucruri ce trebuie avute în vedere:
- Controalele fără constrângeri de validare vor fi întotdeauna valide.
- Controalele care au setat atributul required și nu au nicio valoare sunt considerate nevalide.
- Controalele cu validare implicita încorporată, precum <input type = "email"> sau <input type = "url">, sunt nevalide atunci când datele introduse nu se potrivesc cu modelul asteptat (dar sunt valide când sunt goale).
- Controalele a căror valoare curentă se află în afara limitelor de interval (:in-range) specificate de atributele min și max sunt considerate nevalide, dar sunt valide pentru :out-of-range, așa cum veți vedea mai târziu.
- Există câteva alte modalități de potrivi starea unui element cu :valid /:invalid, așa cum veți vedea în articolul de validare a formularului pe partea de client, dar vom păstra lucrurile simple deocamdată.
Haideți să ne uităm la un exemplu simplu de utilizare :valid /:invalid (consultați codul sursă):
La fel ca în exemplul precedent, avem un extra element span pentru a genera conținut pe care îl vom folosi pentru a oferi indicatori (pictograme) de date valide / nevalide:
<div>
<label for="fname">Nume : </label>
<input id="fname" name="fname" type="text" required>
<span></span>
</div>
Pentru a furniza acești indicatori, utilizăm următoarele linii de cod CSS:
input + span {
position: relative;
}
input + span::before {
position: absolute;
right: -20px;
top: 5px;
}
input:invalid {
border: 2px solid red;
}
input:invalid + span::before {
content: '✖';
color: red;
}
input:valid + span::before {
content: '✓';
color: green;
}
Ca și înainte, setăm span la position: relative, astfel încât să putem poziționa conținutul generat în raport cu intrarile. Apoi poziționăm absolut conținutul generat, în funcție de validitatea datelor - o bifa verde pentru date valide, respectiv, un x de culoare roșie, pentru date nevalide. Pentru a evidentia si mai mult datele nevalide, am adaugat pentru intrări, un chenar roșu gros atunci când datele sunt nevalide.
Observați cum intrările de text obligatorii sunt nevalide când sunt goale, dar valide atunci când au ceva text completat. Intrarea de e-mail, pe de altă parte, este valida când este goală, deoarece nu are setat atributul required, dar este nevalidă atunci când conține ceva text care nu este formatat corect, ca o adresa de e-mail valida.
Date in-range și out-of-range
După cum am arătat mai sus, există alte două pseudo-clase înrudite de luat în considerare: :in-range și :out-of-range. Acestea se utilizeaza cu intrările numerice în care limitele intervalului sunt specificate de min și max, atunci când datele lor se află în interiorul sau în afara intervalului specificat.
☞ Tipurile de intrari numerice sunt: date, month, week, time, datetime-local, number, și range.
Merită remarcat faptul că intrările ale căror date sunt in-range (în intervalul de acțiune) vor fi, de asemenea, corelate cu pseudo-clasa :valid, iar intrările ale căror date sunt out-of-range (în afara intervalului), vor fi corelate cu pseudo-clasa :invalid. Atunci de ce le avem pe amândouă? Problema este una de semantică - out-of-range este un tip mai specific de mesaj nevalid, așa că este posibil să doriți să oferiți utilizatorilor un mesaj diferit pentru intrările din afara intervalului, lucru ce va fi mai util pentru utilizatori decât mesajul "nevalid". De asemenea, s-ar putea să doriți să le utilizati pe amindoua.
Să ne uităm la un exemplu care face exact acest lucru. Demonstrația noastră se bazează pe exemplul precedent și furnizeaza mesaje pentru intrările numerice, în afara intervalului, și de asemenea precizeaza dacă sunt obligatorii.
Intrarea numerică arată astfel:
<div>
<label for="age">Virsta (minim 12 ani): </label>
<input id="age" name="age" type="number" min="12" max="120" required>
<span></span>
</div>
Și codul CSS arată așa:
input + span {
position: relative;
}
input + span::after {
font-size: 0.7rem;
position: absolute;
padding: 5px 10px;
top: -26px;
}
input:required + span::after {
color: white;
background-color: black;
content: "obligatoriu";
left: -70px;
}
input:out-of-range + span::after {
color: white;
background-color: red;
width: 155px;
content: "In afara intervalului acceptat";
left: -182px;
}
Aceasta poveste este similară cu cea pe care am avut-o anterior în exemplul required, cu excepția faptului că aici am împărțit declarațiile care se aplică conținutului ::after în reguli separate, una pentru :required și alta pentru :out-of-range. Puteți încerca versiunea live aici:
Ce se intimpla daca, pentru o intrare numerica, utilizam required și out-of-range in acelasi timp? Deoarece regula out-of-range apare mai târziu în codul sursă decât required, regulile de cascadă CSS intră în joc, iar mesajul afișat este cel generat de out-of-range.
Acest lucru funcționează destul de bine - atunci când pagină se încarcă prima data, este afișat "obligatoriu", împreună cu un X și un chenar ambele de culoare roșie. Când ați tastat o vârstă valabilă (de exemplu, în intervalul 12-120), intrarea devine valida. Dacă, schimbați intrarea de vârstă cu una nevalida, mesajul "In afara intervalului acceptat" apare în locul mesajului "obligatoriu".
Stilizarea intrarilor enabled / disabled și read-only / read-write
Un element enabled este un element care poate fi activat, poate fi selectat, se poate face clic pe el, se pot introduce date, etc.. Pe de altă parte, cu un element disabled nu se poate interacționa în niciun fel, iar datele sale nu sunt nici măcar trimise serverului.
Aceste două stari pot fi targhetate folosind: :enabled și :disabled. De ce sunt utile intrările dezactivate? Ei bine, uneori, dacă unele date nu se aplică unui anumit utilizator, este posibil să nu doriți nici măcar să le trimiteți atunci când utilizatorul trimite formularul. Un exemplu clasic este un formular de expediere - în mod obișnuit veți fi întrebați dacă doriți să utilizați aceeași adresă pentru facturare și transport, dacă da, puteți trimite doar o adresă către server și astfel, câmpurile pentru adresa de facturare pot fi dezactivate.
Să vedem un exemplu care face exact acest lucru. Marcajul HTML este simplu, conține intrări de text, plus o casetă de selectare pentru a activa/dezactiva adrese de facturare. Câmpurile pentru adresa de facturare sunt dezactivate în mod implicit.
<form>
<fieldset id="shipping">
<legend>Adresa expediere</legend>
<div>
<label for="name1">Nume: </label>
<input id="name1" name="name1" type="text" required>
</div>
<div>
<label for="address1">Adresa: </label>
<input id="address1" name="address1" type="text" required>
</div>
<div>
<label for="pcode1">Cod postal: </label>
<input id="pcode1" name="pcode1" type="text" required>
</div>
</fieldset>
<fieldset id="billing">
<legend>Adresa facturare</legend>
<div>
<label for="billing-checkbox">Aceeasi ca adresa de expediere:</label>
<input type="checkbox" id="billing-checkbox" checked>
</div>
<div>
<label for="name" class="billing-label disabled-label">Nume: </label>
<input id="name" name="name" type="text" disabled required>
</div>
<div>
<label for="address2" class="billing-label disabled-label">Adresa: </label>
<input id="address2" name="address2" type="text" disabled required>
</div>
<div>
<label for="pcode2" class="billing-label disabled-label">Cod postal: </label>
<input id="pcode2" name="pcode2" type="text" disabled required>
</div>
</fieldset>
<div><button>Trimite</button></div>
</form>
Cele mai relevante părți ale codului CSS sunt următoarele:
input[type="text"]:disabled {
background: #eee;
border: 1px solid #ccc;
}
.disabled-label {
color: #aaa;
}
Am selectat direct intrările pe care dorim să le dezactivăm folosind input[type="text"]: disabled, dar am dorit să elimin și etichetele de text corespunzătoare. Acestea nu au fost la fel de ușor de selectat, așa că am folosit o clasă pentru a le oferi acel stil.
În sfârșit, am folosit ceva JavaScript pentru a dezactiva câmpurile adresei de facturare:
// Asteptam ca pagina sa se incarce complet
document.addEventListener('DOMContentLoaded', function () {
// Atasam evenimentul 'change' la checkbox
document.getElementById('billing-checkbox').addEventListener('change', toggleBilling);
}, false);
function toggleBilling() {
// Selectam cimpurile de facturare
let billingItems = document.querySelectorAll('#billing input[type="text"]');
// Selectam etichetele cimpurilor de facturare
let billingLabels = document.querySelectorAll('.billing-label');
// Activam / dezactivam cimpurile de facturare si etichetele corespunzatoare
for (let i = 0; i < billingItems.length; i++) {
billingItems[i].disabled = !billingItems[i].disabled;
if(billingLabels[i].getAttribute('class') === 'billing-label disabled-label') {
billingLabels[i].setAttribute('class', 'billing-label');
} else {
billingLabels[i].setAttribute('class', 'billing-label disabled-label');
}
}
}
Stilizarea intrarilor read-only și read-write
Într-un mod similar cu :enabled și :disabled, pseudo-clasele read-only și read-write vizează două stări in care intrările comuta între ele. Intrările read-only au valorile transmise serverului, dar utilizatorul nu le poate edita, în timp ce read-write înseamnă că pot fi editate - aceasta fiind starea lor implicită.
O intrare este setată la read-only folosind atributul readonly. Ca exemplu, imaginați-vă o pagină de confirmare, în care dezvoltatorul a trimis detaliile completate pe paginile anterioare, cu scopul de a-l determina pe utilizator să le verifice pe toate într-un singur loc, eventual să adauge orice date finale necesare și sa confirme comanda prin trimitere. În acest moment, toate datele finale ale formularului pot fi trimise serverului simultan.
Unul din fragmentele HTML care ne intereseaza este cel de mai jos - rețineți atributul readonly:
<div>
<label for="name">Nume: </label>
<input id="name" name="name" type="text" value="Mr Soft" readonly>
</div>
Dacă încercați exemplul live, de mai sus, veți vedea că setul superior de elemente de formular nu este focalizat, cu toate acestea valorile sunt transmise atunci când este trimis formularul. De asemenea, am stilizat controalele de formular read-only folosind pseudo-clasa :read-only (cu prefixul -moz pentru Firefox), asa cum se poate vedea mai jos:
input:-moz-read-only,
textarea:-moz-read-only {
border: 0;
box-shadow: none;
resize: none;
background-color: white;
}
input:read-only,
textarea:read-only {
border: 0;
box-shadow: none;
resize: none;
background-color: white;
}
☞ :enabled și :read-write, sunt încă două pseudo-clase, pe care probabil le veți folosi foarte rar, având în vedere că acestea sunt stări implicite ale elementelor de intrare.
Stilizarea starilor butoanelor radio si casetelor de selectare
Așa cum am văzut mai devreme, butoanele radio și casetele de selectare pot fi checked sau unchecked. Există însă și alte câteva stari care trebuie luate în considerare:
- :default - corespunde butoanelor radio si casetelor de selectare care sunt bifate în mod implicit, la încărcarea paginii (adică prin setarea atributului bifat pe acestea). Acestea corespund cu pseudo-clasa :default, chiar dacă utilizatorul le debifeaza.
- :indeterminate - butoanele radio și casetele de selectare care nu sunt nici bifate și nici debifate, sunt considerate nedeterminate și se vor potrivi cu pseudo-clasa :indeterminate.
:checked
Cea mai obișnuită utilizare este să adăugați un stil diferit pentru caseta / butonul radio atunci când este bifată, în cazurile în care ați eliminat stilul implicit al sistemului cu appearance: none; și construiți o stilizare personalizata. Am văzut asemenea exemple în acest articol și articolul precedent.
Puteti revedea exemplul anterior aici:
input[type="radio"]::before {
display: block;
content: " ";
width: 10px;
height: 10px;
border-radius: 6px;
background-color: red;
font-size: 1.2em;
transform: translate(3px, 3px) scale(0);
transform-origin: center;
transition: all 0.3s ease-in;
}
input[type="radio"]:checked::before {
transform: translate(3px, 3px) scale(1);
transition: all 0.3s cubic-bezier(0.25, 0.25, 0.56, 2);
}
Practic, construim stilul pentru cercul interior al butonului radio, folosind pseudo elementul ::before și setăm o transformare la scară (0) pe el. Vom folosi apoi o tranziție pentru a face o animație frumoasă atunci când butonul radio este selectat / bifat. Avantajul folosirii unei transformări, mai degrabă decât a tranziției lățimii / înălțimii este că, putem utiliza transform-origin pentru a face ca cercul sa crească din centrul sau, decât din colțul cercului.
:default și :indeterminate
Așa cum am menționat mai sus, pseudo-clasa :default se coreleaza cu butoanele radio / casetele de selectare, care sunt bifate implicit, la încărcarea paginii, chiar și atunci când nu sunt bifate. Acest lucru ar putea fi util pentru adăugarea unui indicator la o listă de opțiuni pentru a aminti utilizatorului care au fost valorile implicite (sau opțiunile de pornire), în cazul în care doresc să își reseteze alegerile.
De asemenea, am mentionat mai sus ca, butoanele radio / casetele de selectare vor fi corelate cu pseudo-clasa :indeterminate, atunci când se află într-o stare în care nu sunt nici bifate și nici debifate. Dar ce înseamnă asta? Elementele care sunt :indeterminate includ:
- <input/radio> - când toate butoanele radio dintr-un grup cu același nume sunt debifate,
- <input/checkbox> - intrări a căror proprietate :indeterminate este setată la valoarea true prin JavaScript,
- <progress> - elemente care nu au nicio valoare.
Nu este un lucru pe care îl vei folosi foarte des. Un caz de utilizare ar putea fi, un indicator care să le spună utilizatorilor, că trebuie să selecteze într-adevăr un buton radio înainte de a merge mai departe.
Să ne uităm la câteva versiuni modificate ale exemplului precedent, care să-i amintească utilizatorului care a fost opțiunea implicită și să stilizam butoanele radio atunci când sunt :indeterminate. Ambele au următoarea structură HTML pentru intrări:
<p>
<input type="radio" name="fruit" value="cherry" id="cherry">
<label for="cherry">Cirese</label>
<span></span>
</p>
Pentru exemplul :default, am adăugat atributul bifat (checked) la intrarea butonului radio din mijloc, astfel încât acesta va fi selectat implicit la încărcare. Stilizam acest lucru cu următorul cod CSS:
input ~ span {
position: relative;
}
input:default ~ span::after {
font-size: 0.7rem;
position: absolute;
content: "Implicit";
color: white;
background-color: black;
padding: 5px 10px;
right: -65px;
top: -3px;
}
Aceasta oferă o mică etichetă "Implicit", pentru butonul selectat inițial la încărcarea paginii. Rețineți că aici folosim combinatorul general de frați (~) și nu combinatorul de frați adiacenti (+) - trebuie să facem acest lucru deoarece span nu vine imediat după input în ordinea sursă.
Pentru exemplul :indeterminate, nu avem niciun buton radio selectat implicit - acest lucru este important - dacă există, atunci nu ar exista nici o stare nedeterminată de stilizat. Stilizam butoanele radio :indeterminate cu următorul cod CSS:
input[type="radio"]:indeterminate {
border: 2px solid red;
animation: 0.4s linear infinite alternate border-pulse;
}
@keyframes border-pulse {
from {
border: 2px solid red;
}
to {
border: 6px solid red;
}
}
Acest lucru creează o mică animație pe butoanele radio, ceea ce arată, că trebuie să selectați unul dintre butoane.
Vedeți rezultatul mai jos:
Mai multe pseudo-clase
Există o serie de alte pseudo-clase de interes, pe care doar le amintim aici, dar le vom utiliza in alte exemple viitoare:
- :focus-within - se potrivește cu un element care a primit focus sau conține un element care a primit focus. Acest lucru este util, dacă doriți ca un formular întreg, să fie evidențiat într-un fel, atunci când o intrare din interiorul acestuia este focalizată.
- :focus-visible - se potrivește cu elementele focalizate care au fost focalizate prin interacțiunea tastaturii (mai degrabă decât prin atingere sau clic cu mouse-ul) - utilă dacă doriți să afișați un stil diferit pentru focalizarea cu ajutorul tastaturii, în comparație cu focalizarea prin intermediul mouse-ului sau alt tip de focalizare.
- :placeholder-shown - se potrivește cu elementele input și textarea, care au afișat placeholderul lor (adică conținutul atributului placeholder), deoarece valoarea elementului este goală.
Validarea formularului pe partea de client
Înainte de a trimite date către server, este important să vă asigurați că, toate controalele de formular necesare, sunt completate în formatul corect. Acest proces, se numește, validarea formularului pe partea de client și ajută la verificarea datelor transmise, astfel incit acestea sa corespunda, cerințelor stabilite în diferitele controale de formular. In acest articol discutam despre concepte de bază utilizate in validarea formularului pe partea de client.
Validarea pe partea de client este o verificare inițială și o caracteristică importantă, in ceea ce priveste o buna experiența a utilizatorului. Captarea datelor nevalide introduse de utilizator, ofera acestuia posibilitatea de a remedia lucrurile imediat. Dacă datele ajung pe server și sunt respinse, apare o întârziere cauzată de o călătoria dus-întors către server și înapoi la client, care este anuntat ca datele introduse nu sunt conforme si trebuie sa le corecteze.
Cu toate acestea, validarea pe partea de client nu trebuie considerată o măsură de securitate completa! Aplicațiile dvs. ar trebui să efectueze întotdeauna verificări de securitate, pentru orice date trimise de formular atât pe partea serverului, cât și pe partea clientului, deoarece validarea din partea clientului este prea ușor de dezactivat, astfel încât utilizatorii rău intenționați pot trimite cu ușurință date malitioase către server.
Ce este validarea formularului?
Accesați orice site, care are un formular de înregistrare și veți observa că acesta oferă feedback, atunci când nu introduceți datele în formatul cerut.
Vei primi mesaje precum:
- "Acest câmp este obligatoriu", (Nu puteți lăsa acest câmp necompletat);
- "Vă rugăm să introduceți numărul dvs. de telefon în formatul xxx-xxx-xxx", (este necesar un format de date specific pentru ca acesta să fie considerat valid);
- "Vă rugăm să introduceți o adresă de e-mail validă", (datele introduse nu sunt în formatul potrivit);
- "Parola dvs. trebuie să aibă între 8 și 30 de caractere și să conțină o literă mare, un simbol și un număr".
Aceasta se numește validarea formularului. Când introduceți date, browserul și / sau serverul web vor verifica dacă datele sunt în formatul corect și în limitele stabilite de aplicație. Validarea făcută în browser se numește validare din partea clientului, în timp ce validarea făcută pe server se numește validare din partea serverului. În continuare ne concentrăm pe validarea din partea clientului.
Dacă informațiile sunt formatate corect, aplicația permite trimiterea datelor pe server și de obicei le salveaza într-o bază de date, iar dacă informațiile nu sunt formatate corect, îi oferă utilizatorului un mesaj de eroare care explică ce trebuie corectat și îi permite să încerce din nou.
Trebuie sa facem in asa fel incit completarea formularelor web sa fie cit mai facila. Deci, de ce insistăm să ne validăm formularele? Există trei motive principale:
- Vrem să obținem datele corecte, în formatul potrivit. Aplicațiile noastre nu vor funcționa corect dacă datele utilizatorilor noștri sunt stocate într-un format greșit, sunt incorecte sau sunt omise cu totul.
- Vrem să protejăm datele utilizatorilor noștri. Forțarea utilizatorilor noștri să introducă parole sigure, facilitează protejarea informațiilor despre conturile acestora.
- Vrem să ne protejăm propriile aplicatii Există multe modalități prin care utilizatorii rău intenționati pot folosi în mod incorect formularele neprotejate pentru a deteriora aplicația.
☞ Avertisment. Nu aveți încredere niciodata în datele transmise catre server de utilizatori. Chiar dacă formularul dvs. este validat corect și împiedică introducerea de date malformate de catre client, un utilizator rău intenționat poate totusi modifica cererea de rețea.
Diferite tipuri de validare din partea clientului
Există două tipuri diferite de validare din partea clientului pe care le veți întâlni pe web:
- Validarea încorporată utilizează caracteristici de validare a formularelor HTML5, despre care am discutat pîna acum în multe locuri din acest modul. Această validare nu necesită în general mult JavaScript. Validarea încorporată are performanțe mai bune decât JavaScript, dar nu este la fel de personalizabilă ca validarea JavaScript.
- Validarea JavaScript este realizată folosind limbajul JavaScript. Această validare este complet personalizabilă, dar trebuie creata in totalitate sau puteti să folosiți o bibliotecă.
Utilizarea validării încorporate
Una dintre cele mai semnificative caracteristici ale controalelor de formulare HTML5 este posibilitatea de a valida majoritatea datelor utilizatorului fără a utiliza JavaScript. Acest lucru se realizează prin utilizarea atributelor de validare a elementelor de formular. Am văzut multe dintre acestea mai devreme în acest curs, dar să recapitulăm:
- required - specifică dacă trebuie completat un câmp de formular, înainte de a putea fi trimis formularul.
- minlength și maxlength - specifică lungimea minimă și maximă a datelor textuale (șiruri-strings).
- min și max - specifică valorile minime și maxime ale tipurilor de intrari numerice
- type - specifică dacă datele trebuie să fie un număr, o adresă de e-mail sau un alt tip specific.
- pattern - specifică o expresie uzuala, care definește un model, pe care datele introduse trebuie să-l urmeze.
Dacă datele introduse într-un câmp de formular, respectă toate regulile specificate de atributele de mai sus, acestea sunt considerate valide. Dacă nu, sunt considerate nevalide.
Când un element este valid, următoarele lucruri sunt adevărate:
- Elementul se potrivește cu pseudo-clasa CSS :valid, care vă permite să aplicați un stil specific elementelor valide.
- Dacă utilizatorul încearcă să trimită datele, browserul va trimite formularul, cu condiția să nu existe altceva, care sa oprească acest lucru (de exemplu, JavaScript).
Când un element este invalid, următoarele lucruri sunt adevărate:
- Elementul se potrivește cu pseudo-clasa CSS :invalid și uneori cu alte pseudo-clase UI (de exemplu, :out-of-range) în funcție de eroare, ceea ce vă permite să aplicați un stil specific elementelor invalide.
- Dacă utilizatorul încearcă să trimită datele, browserul va bloca formularul și va afișa un mesaj de eroare.
Exemplu de utilizare a validării încorporate
Să începem cu un exemplu simplu: o intrare care vă permite să alegeți dacă preferați o pară sau o prună. Acest exemplu implică un text simplu input cu o eticheta label asociată și un buton, button pentru trimitere.
<form>
<label for="choose">Preferi o pară sau o cireașă?</label>
<input id="choose" name="i_like" pattern="(pară|cireașă)">
<button>Trimite</button>
</form>
input:invalid {
border: 2px dashed red;
}
input:valid {
border: 2px solid black;
}
Atributul required
Cea mai simplă caracteristică de validare HTML5 este atributul required (necesar, obligatoriu). Pentru a face o intrare obligatorie, adăugați acest atribut la element. Când acest atribut este setat, elementul se potrivește pseudoclasa UI :required și formularul nu se va trimite, afișând un mesaj de eroare la trimitere atunci când intrarea este goală. Deși este goală, intrarea va fi considerată de asemenea nevalidă, potrivindu-se cu pseudo-clasa UI :invalid.
Adăugam un atribut :required așa cum se poate vedea mai jos:
<form>
<label for="choose">Preferi o para sau o cireasa?</label>
<input id="choose" name="i_like" required>
<button>Trimite</button>
</form>
Rețineți codul CSS inclus în exemplu:
input:invalid {
border: 2px dashed red;
}
input:invalid:required {
background-image: linear-gradient(to bottom, tomato, lightgray);
}
input:valid {
border: 2px solid black;
}
Codul CSS de mai sus, face ca intrarea să aibă un chenar de culoare roșie atunci când este nevalidă și un chenar negru solid atunci când este valid. De asemenea, am adăugat un gradient de fundal atunci când intrarea este necesară și nevalidă.
Încercați să trimiteți formularul fără să introduceți o valoare. Va fi afisat un mesaj de eroare implicit ("Please fill out this field"), iar formularul nu va fi trimis.
Prezența atributului required pe orice element care acceptă acest atribut, înseamnă că elementul se potrivește cu pseudo-clasa :required, indiferent dacă are o valoare sau nu. Dacă input nu are nicio valoare, intrarea se va potrivi cu pseudo-clasa :invalid.
☞ Pentru o experiență bună, indicați utilizatorului când exista câmpuri de formulare necesare a fi completate. Nu este doar o experiență bună a utilizatorului, ci este cerut de ghidurile de accesibilitate WCAG. De asemenea, solicitați utilizatorilor să introducă datele de care aveți nevoie absoluta. De exemplu, de ce trebuie să știți cu adevărat genul sau titlul cuiva?
Validarea împotriva unei expresii obișnuite
O altă caracteristică utilă de validare este reprezentata de atributul pattern, care așteaptă o expresie regulată, ca valoare. O expresie obișnuită (regex) este un model care poate fi utilizat pentru a potrivi combinațiile de caractere din șirurile de text, asadar regex-urile sunt ideale pentru validarea formularelor și servesc o varietate de alte utilizări în JavaScript.
Regex-urile sunt destul de complexe și nu vom epuiza acest subiect aici, dar cel putin vom exemplifica modul de utilizare, pentru a vă oferi o idee de bază despre modul în care funcționează.
- a - se potrivește cu un caracter care este a (nu b, nu aa și așa mai departe).
- abc - se potrivește cu a, urmat de b, urmat de c.
- ab?c - se potrivește cu a, urmat opțional de un singur b, urmat de c, (ac sau abc).
- ab*c - corespunde cu a, urmat opțional de orice număr de b, urmat de c, (ac, abc, abbbbbc și așa mai departe).
- a|b - corespunde cu un caracter care este a sau b.
- abc|xyz - se potrivește exact cu abc sau exact cu xyz (dar nu abcxyz sau a sau y și așa mai departe).
Există multe alte posibilități despre care vom discuta la momentul potrivit.
Să implementăm un exemplu. Vom actualiza codul HTML pentru a adăuga un atribut pattern:
<form>
<label for="choose">Preferi o para sau o cireasa?</label>
<input id="choose" name="i_like" required pattern="[Pp]ara|[Cc]ireasa">
<button>Trimite</button>
</form>
În acest exemplu, elementul input acceptă una dintre cele patru valori posibile: șirurile, "Para", "para", "Cireasa" sau "cireasa". Expresiile uzuale (regular expressions), sunt case-sensitive, sensibile la majuscule, dar formularul nostru suporta atit majuscule, precum și versiuni cu litere mici, folosind un model "Aa" suplimentar, inclus în paranteze pătrate.
Dacă o valoare introdusă nu se potrivește cu modelul expresiei obișnuite, intrarea se va potrivi cu pseudo-clasa :invalid.
☞ Unele tipuri de elemente input nu au nevoie de un atribut
pattern, pentru a fi validate împotriva unei expresii obișnuite. Specificarea tipului e-mail
(type="email"), de exemplu, validează valoarea intrărilor cu un model de adresă de e-mail bine formatat sau cu
un model care se potrivește cu o listă de adrese de e-mail separate de virgule, dacă are setat atributul
multiplu.
Elementul textarea nu acceptă atributul pattern.
Restricționarea lungimii intrărilor
Puteți constrânge lungimea caracterelor tuturor câmpurilor de text create de input sau textarea folosind atributele minlength și maxlength. Un câmp nu este valabil dacă are o valoare și această valoare, are mai puține caractere decât valoarea minlength sau mai multe decât valoarea maxlength.
De multe ori browserele nu permit utilizatorului, să tasteze în câmpurile de text, o valoare mai lungă decât cea așteptată. O experiență mai bună a utilizatorului decât folosirea maxlength, este de a oferi feedback de numărare a caracterelor, într-o manieră accesibilă și de a le permite să-și editeze conținutul până la dimensiunile acceptate. Un exemplu în acest sens este limita de caractere văzută pe Twitter. JavaScript, inclusiv soluțiile care utilizează maxlength, pot fi utilizate pentru a face acest lucru.
Limitarea valorilor intrărilor
Pentru câmpurile numerice (de ex. <input type="number">), atributele min și max pot fi utilizate pentru a oferi o serie de valori valide. Dacă câmpul, conține o valoare în afara acestui interval, acesta va fi nevalid.
Să ne uităm la un alt exemplu:
<form>
<div>
<label for="choose">Preferi pere sau mere?</label>
<input type="text" id="choose" name="i_like" required minlength="4" maxlength="4">
</div>
<div>
<label for="number">Cît de multe ai vrea?</label>
<input type="number" id="number" name="amount" value="1" min="1" max="10">
</div>
<div>
<button>Trimite</button>
</div>
</form>
Dupa cum puteti observa, am dat câmpului de text o lungime minima și o lungime maximă de patru caractere, care corespunde cu fructele noastre din exemplu (mere / pere).
De asemenea, am dat câmpului number un minim de unu și un maxim de zece. Numerele introduse în afara acestui interval vor apărea ca nevalide, utilizatorii nu vor putea utiliza săgețile increment / decrement pentru a muta valoarea în afara acestui interval. Dacă utilizatorul introduce manual un număr în afara acestui interval, datele sunt nevalide. Intrarea numerica nu este necesara (required), astfel încât eliminarea valorii, va avea ca rezultat o valoare validă.
Validarea formularelor cu JavaScript
Trebuie să utilizați JavaScript, dacă doriți să preluați aspectul mesajelor de eroare native sau pentru a face față browserelor vechi care nu acceptă validarea HTML încorporată.
Validarea formularelor cu JavaScript, constituie un subiect mai complex, pe are il vom trata pe larg, in cursul dedicat invatarii Javascript.
Trimiterea datelor formularului
După ce am învățat cum să structurăm și să stilizăm formularele, ultimul pas este să înțelegem cum se trimit datele completate de utilizator. Acest proces este esențial pentru interacțiunea cu serverul și pentru colectarea informațiilor din partea clientului.
Metoda de trimitere
Formularele HTML pot trimite datele folosind două metode principale:
- GET - trimite datele în URL. Este potrivit pentru căutări sau formulare simple.
- POST - trimite datele în corpul cererii HTTP. Este recomandat pentru date sensibile sau formulare complexe.
<form action="procesare.php" method="post"><label for="nume">Nume:</label><input type="text" name="nume" id="nume"><button>Trimite</button></form>
Atributul Action
Definește adresa (URL-ul) către care se trimit datele. Poate fi o pagină PHP, un script server-side sau un endpoint API.
Atributul Method
Definește modul în care sunt trimise datele. GET adaugă datele în URL, POST le trimite în fundal.
Ce se întâmplă la trimitere
Când utilizatorul apasă pe butonul „Trimite”, browserul:
- Verifică dacă formularul este valid (dacă există atribute precum required)
- Trimite datele conform metodei și acțiunii specificate
- Deschide pagina specificată în action (dacă nu se folosește JavaScript)
Trimiterea cu JavaScript (opțional)
Putem intercepta trimiterea și procesa datele manual:
document.querySelector("form").addEventListener("submit", function(e) {e.preventDefault(); // oprim trimiterea automată
const formData = new FormData(this);
fetch("procesare.php", {method: "POST",body: formData}).then(r => r.text()).then(data => {console.log("Răspuns server:", data);});});
Concluzie
Trimiterea datelor este punctul final al interacțiunii cu formularul. Poți folosi metode simple cu HTML sau soluții dinamice cu JavaScript, în funcție de nevoile aplicației tale.
🧠 Quiz - Formulare Web și Validare
