├── 01-introduction.md ├── 02-structure.md ├── 03-data-exchange.md ├── 04-dom-101.md ├── 10-real-life-scenarios.md ├── draft.md └── readme.md /01-introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | ## Why forms 4 | 5 | Forms are everywhere on the web. We use forms to do all kind of activities like logging into a system, sending messages and files, answering quizzes and a lot more. This is why understanding how to create forms is important. Not just for developers but for UX engineers and designers as well. 6 | 7 | Forms exist from the first day HTML was created. HTML5 introduced a lot of new features to the forms (native validation, new input types) 8 | 9 | In this series we will explore everything related to forms like: 10 | 11 | * How to leverage semantic HTML to create intuitive and accessible forms 12 | * How to style forms using CSS 13 | * How to enforce client side validation using HTML5 APIs 14 | * What are the common practices and pitfalls we should be aware of when we create forms 15 | 16 | ## The motive behind this book 17 | 18 | Forms are important to web applications and web development. There is a lot of techniques and tricks people are missing when they work with forms. With the rise of the modern frontend frameworks, most of the developers I met are caring less about forms and do a lot of bad practices. That's not the fault of the frameworks though, it might be due to the forgiving nature of the web or the availability of learning resources. 19 | 20 | For example, one of the tasks we give to junior developers applying to my company is an HTML form. We asked them to do the changes they see necessary and ask them to add validation for a couple of fields. Most of the submissions were: 21 | 22 | * unable to spot invalid HTML (like duplicate IDs), 23 | * unable to bind labels to inputs properly or not using labels at all, 24 | * unable to use validation without JavaScript (like required, proper input types ... etc) 25 | 26 | This is why I saw an opportunity to try to fill this gap. -------------------------------------------------------------------------------- /02-structure.md: -------------------------------------------------------------------------------- 1 | [TOC] 2 | 3 | # Forms structure 4 | 5 | HTML offers a variety of elements that can be used collect data from users. Due to the increase in the complexity of the web applications, developers are still creating custom components that extend existing elements and add new ones. In this chapter we will explore the native HTML elements used in HTML forms. 6 | 7 | ## Forms 101 8 | 9 | ### The `form` tag 10 | 11 | Forms always start with the `form` tag. It's used to define the *method* that will be used to submit the form data to the server and the *URL* where it will be submitted. 12 | 13 | ```html 14 |
17 | ``` 18 | 19 | The example above shows 2 different attributes written in the `form` tag, the `method` and the `action` attributes. 20 | 21 | #### The `method` attribute 22 | 23 | The `method` attribute describes the HTTP verb used to submit the form. It's case insensitive and can be either: 24 | 25 | 1. `get` which is the default value. The form data is submitted in the URL as *query string*. This method is usually used when we want to create an indexable URL (like a search form). 26 | 2. `post` method, the data is sent in the request body. 27 | 28 | 💡 If the author does not provide a `method` attribute, the form will use the `get` method by default. 29 | 30 | 💡 HTML5 introduced a new method `dialog` which can be used to close a native `dialog` element that enclose the form. For the sake of simplicity, this one will be discussed later in **Real life cases** section. 31 | 32 | ⚠️ Forms cannot be nested (i.e. we cannot add a form inside another form). Browsers usually ignore the inner `form` tag. Some authors try to do that in attempt to organize their form into different sections. This is done using different elements that we will discuss later. 33 | 34 | #### The `action` attribute 35 | 36 | The `action` attribute is used to define the URL where this form will be submitted. If this attribute is not available, the form will submit to the same URL. This URL can be overridden by some form elements that we will explore later. 37 | 38 | ### Form elements used to collect data 39 | 40 | In this section we will learn about the different elements used to collect inputs from the users. We will discuss the `input`, `textarea` and `select` tags. For the sake of simplicity, we will refer to them collectively as *form controls*. 41 | 42 | #### The `input` tag 43 | 44 | The `input` tag is used to collect data from the user. It has a lot of types that control the type of data it accepts. These types define the user interaction with that element and the kind of validation rules that will be triggered when it receives data. 45 | 46 | ```html 47 | 52 | ``` 53 | 54 | You can see there is a new tag we used here `label`. For now, let's just say that it is used to describe a form input. We will talk more about it in the next section. 55 | 56 | The `input` is a self-closing element. The `type` attribute defines what type of the element is. HTML5 introduced a lot of different types that can be used to collect different types of data. 57 | 58 | ##### Original input types 59 | 60 | * `text` accepts anything. This is the default value of the attribute. If the user doesn't provide a value for the `type`, the browser will consider the `input` type as `text`. Also, if the browser doesn't understand the value of the `type` attribute (like if it is an invalid value, or an older browser that doesn't understand new values) it will also be treated as `text`. 61 | * `password` accepts anything like text. The difference is, the browser will attempt to hide the value the user is writing on the screen for privacy purpose. The behavior is different on mobile phones where the browser will attempt to show the last character you wrote for a moment before hiding the entire value. 62 | * `checkbox` allows the user to choose multiple answers for one question. This one is suitable to use when the available options are few and your intent is to show them all together. 63 | * `radio` requires the user to pick one answer out of many. 64 | * `file` allows the user to pick one or more files from their machine. 65 | * `hidden` allows developers to include data when the form is not submitted without being visible to the users. It can be used in different scenarios, most commonly to include an automatically generated token to prevent an attack like Cross Site Request Forgery (CSRF). We will discuss this part in the forms security section. 66 | * `submit` transforms the `input` to look like a button that can be used to submit form. Since the introduction of the `button` element, authors shifted to the new element to submit forms because it offers richer render possibilities. 67 | * `reset` transforms the `input` to look like a button that can be used to reset the value of the form to match the corresponding `value` attribute on each element. Like the `submit` type, it can be replaced with a `button` tag with the same `type` which is now preferred for the same reason. 68 | 69 | ##### HTML5 new input types 70 | 71 | * `email` accepts email format. This will trigger validation errors and prevent form submission if the value provided doesn't match the email format. 72 | * `number` accepts numerical values. According to the specs it accepts floating-point numbers so exponential notation is accepted as well. We will discuss this later. 73 | * `date` accepts date format. This input display a mini calendar that allows the user to pick a date. The layout of that date picker differs from a browser to another and is affected by the device type and operating system as well. 74 | * `color` accepts color in a hexadecimal format. This input display a color picker for the user to choose. The layout of that color picker is dependent upon the operating system. 75 | * `datetime-local` 76 | * `range` 77 | * `search` 78 | * `tel` 79 | * `url` 80 | 81 | ##### How `input`'s value is calculated 82 | 83 | The `input` tag has the option to accept an initial value using the `value` attribute. If that attribute is missing, the value will be nothing. When the user submit a form, the text value written inside the form will be submitted. 84 | 85 | Some input types will resolve to special values that is different from the text being displayed inside the form control. For example, an `input` with the type `date` might display the date in the format `MM/DD/YYYY` (if your locale is en-US) but the submitted value will always be formatted according to ISO8601 like `YYYY-MM-DD`. These special cases will be explained when we discuss each `type` separately. 86 | 87 | #### The `textarea` tag 88 | 89 | The `textarea` allows the user to write multiple lines of text. It's suitable to use when the user is expected to insert big chunks of unstructured text (like a message, a feedback ... etc). 90 | 91 | ```html 92 | 96 | ``` 97 | 98 | Unlike the other form elements, the `textarea` does not require a value attribute. If we want to write a default value for a `textarea` we simply write it as text inside the tag itself (note that this isn't a self-closing tag like `input`) 99 | 100 | ```html 101 | 107 | ``` 108 | 109 | ⚠️ If you used a framework [like react](https://reactjs.org/docs/forms.html#the-textarea-tag), you will find that the binding of `textarea` value happens by using `value` attribute. The framework changes that on run time to work as we described above. The `value` attribute doesn't work on `textarea`. 110 | 111 | #### The `select` tag 112 | 113 | The `select` tag let the user select an option or more from a list. The available options we provide for the user to pick from is listed using the `option` tag. The `select` tag provides a similar functionality to that of the `input` of type `checkbox` or `radio`. 114 | 115 | A good use case for `select` is when there are too many options to display on the screen. The available options are only demonstrated when the user *open* the select control. check the following example: 116 | 117 | ```html 118 | 129 | ``` 130 | 131 | There are tens of car brands. Displaying all of them using checkboxes or radio buttons will unnecessarily occupy a huge space. 132 | 133 | Another good use case is when is when we want to group the different options together in a way that makes it easy for the user to understand. Check the following: 134 | 135 | ```html 136 | 152 | ``` 153 | 154 | The `optgroup` tag accepts a `label` attribute. Its value will be displayed on top of these options making it easier to distinguish for the user. It will also add the needed padding for each group of options to make it easier to read. 155 | 156 | A great benefit we get from `optgroup` is that we can disable a group of options by using the `disabled` attribute on that group. 157 | 158 | ⚠️ With the power offered by the `optgroup`, some authors nest `optgroup` inside each other. While this might work in some browser, it goes again the HTML specification and hence, it produces invalid HTML which could lead to unexpected results. The HTML specs define that the only allowed children of `optgroup` is zero or more `option` tags. Also, the only allowed parent is the `select` tag. Try to stick to that and keep your forms simple. 159 | 160 | ##### How `select`'s value is calculated 161 | 162 | The value of the `select` tag is determined by the selected `option`. This leads to a very interesting behavior. 163 | 164 | * If the selected `option` does not have a `value` attribute, the value will be the text written inside the `option` tag. 165 | * If the selection `option` have a `value` attribute, this value of this attribute will be used. 166 | 167 | ### Structural form elements 168 | 169 | HTML provides us with a few elements that can be used to improve structuring and laying out our forms. In this section we will be talking about `label`, `fields` and `legend`. 170 | 171 | #### The `label` tag 172 | 173 | You were introduced to the `label` tag in the previous section. As we described earlier; it is used to provide a caption for form controls. To associate a `label` with a form controls we have two options: 174 | 175 | ```html 176 | 187 | ``` 188 | 189 | The first option requires that we specify the `id` of that control to the value of the `for` attribute of the `label`. The second option involves wrapping that form control inside the `label` along with the text used to describe it. Both options are fine but the first one offers a greater styling control over the text. Also, no styles will be cascaded from the `label` to the enclosed form control. 190 | 191 | It's always encouraged to use `label`s for the following benefits: 192 | 193 | 1. It helps the users who use assistive technologies like screen reader. It will read out the label when the user is focused on the form input, helping the user to understand what this field is about and what data should be entered. 194 | 2. When the user clicks a `label`, it will activate the associated `input`. This offers great benefit when a user tries to activate a checkbox or a radio button. Instead of having to click precisely on the `input`, clicking the whole text will do the purpose. This is mostly noted when a user try to fill a form on a mobile device. 195 | 196 | 💡 We should always use labels to describe form controls. Sometimes, designers don't add labels on simple forms (like a search form with a single input) or replace them with `placeholders` (we will discuss it later). In the accessibility section, we will discuss some alternative approaches to provide form controls with descriptive text; either through `label` or other techniques. 197 | 198 | 💡 Multiple labels can be associated with a single form control. This becomes handy when you try to design a certain experience where multiple click areas can be used to activate the same form control. 199 | 200 | #### The `fieldset` and `legend` tags 201 | 202 | The `fieldset` element allows us to group some form controls in a single section. It's labelled by using a `legend` element. 203 | 204 | ```html 205 | 222 | ``` 223 | 224 | By default, the user agent stylesheet add some padding and margin around the `fieldset` as well as 2px groove border giving it a distinguished look. We will discuss how it look in details in the **Styling forms with CSS** section. 225 | 226 | Another common use case for `fieldset` is to group several checkboxes or radio buttons like the following 227 | 228 | ```html 229 | 240 | ``` 241 | 242 | In the previous example, screen readers will attempt to read the question defined in the `legend` tag giving a greater context for the users. This will be discussed in details in **Forms accessibility**. 243 | 244 | 💡 It's OK to nest several `fieldset`s inside each other as long as it makes sense. 245 | 246 | 💡 A `fieldset` can contain only one `legend`. The HTML specs define the `legend` as the first child to the `fieldset`. If the `legend` is nested in any place other than the first child, it will be rendered as if it is the first child. This odd behavior is intended by design and there were several proposals to change it. 247 | 248 | ### Form actions 249 | 250 | #### Submitting a form 251 | 252 | #### Resetting a form 253 | 254 | #### Custom form actions 255 | 256 | -------------------------------------------------------------------------------- /03-data-exchange.md: -------------------------------------------------------------------------------- 1 | # Data exchange 2 | 3 | TODO 4 | 5 | * How form data is collected 6 | * Constructing the URL query in `GET` requests 7 | * Different data formats and MIME types used when using `POST` methods 8 | * Dealing with arrays of data -------------------------------------------------------------------------------- /04-dom-101.md: -------------------------------------------------------------------------------- 1 | # DOM 101 2 | 3 | In this section we will shed the light on some important properties and methods provided by the DOM API that will help us working with forms using JavaScript. 4 | 5 | ## HTMLFormElement 6 | 7 | The `HTMLFormElement` interface represents a `