# Styling Web Forms Reference --- ## 1. Styling Web Forms > **Source:** ### Overview This section covers CSS techniques for styling HTML form elements. It is essential for understanding which form elements are easy to style and which require special techniques. **Prerequisites:** - Basic understanding of HTML - CSS styling basics **Objective:** Learn styling techniques applicable to form widgets and understand the challenges involved. ### Challenges in Styling Form Widgets #### Historical Context - **1995:** HTML 2 specification introduced form controls. - **Late 1996:** CSS was released but was not widely supported. - **Early era:** Browsers relied on operating system rendering for form widgets. - **Modern era:** Most form widgets are now stylable, with some exceptions. #### Form Widget Classification **Easy-to-Style Elements:** 1. `
` 2. `
` and `` 3. Single-line text `` (type: text, url, email) 4. Multi-line `
``` #### Set Up Web Fonts ```css @font-face { font-family: "handwriting"; src: url("fonts/journal-webfont.woff2") format("woff2"), url("fonts/journal-webfont.woff") format("woff"); font-weight: normal; font-style: normal; } @font-face { font-family: "typewriter"; src: url("fonts/momot___-webfont.woff2") format("woff2"), url("fonts/momot___-webfont.woff") format("woff"); font-weight: normal; font-style: normal; } ``` #### Overall Layout ```css body { font: 1.3rem sans-serif; padding: 0.5em; margin: 0; background: #222222; } form { position: relative; width: 740px; height: 498px; margin: 0 auto; padding: 1em; box-sizing: border-box; background: white url("background.jpg"); /* CSS Grid for layout */ display: grid; grid-gap: 20px; grid-template-columns: repeat(2, 1fr); grid-template-rows: 10em 1em 1em 1em; } ``` #### Heading and Layout ```css h1 { font: 1em "typewriter", monospace; align-self: end; } #message { grid-row: 1 / 5; } #from, #reply { display: flex; } ``` #### Labels ```css label { font: 0.8em "typewriter", sans-serif; } ``` #### Text Fields ```css input, textarea { font: 1.4em/1.5em "handwriting", cursive, sans-serif; border: none; padding: 0 10px; margin: 0; width: 80%; background: none; } input:focus, textarea:focus { background: rgb(0 0 0 / 10%); border-radius: 5px; } ``` #### Textarea Adjustments ```css textarea { display: block; padding: 10px; margin: 10px 0 0 -10px; width: 100%; height: 90%; border-right: 1px solid; /* resize: none; */ overflow: auto; } ``` Tips: - Use `resize: none` only if necessary (avoid restricting user control). - Set `overflow: auto` for consistent cross-browser rendering. #### Button Styling ```css button { padding: 5px; font: bold 0.6em sans-serif; border: 2px solid #333333; border-radius: 5px; background: none; cursor: pointer; transform: rotate(-1.5deg); } button::after { content: " >>>"; } button:hover, button:focus { background: black; color: white; } ``` ### Key CSS Properties for Forms | Property | Purpose | |---|---| | `font-family: inherit` | Inherit parent font | | `font-size: 100%` | Inherit parent size | | `box-sizing: border-box` | Include padding/border in width | | `border: none` | Remove default borders | | `padding` | Add space inside elements | | `margin` | Add space outside elements | | `background` | Control background appearance | | `:focus` | Style focused form fields | | `resize` | Allow/prevent textarea resizing | | `overflow: auto` | Handle scrolling consistently | ### Best Practices 1. **Consistency:** Use `box-sizing: border-box` for predictable sizing. 2. **Inheritance:** Explicitly set `font-family` and `font-size` on form elements. 3. **Accessibility:** Always include `:focus` styles for keyboard navigation. 4. **Browser Support:** Test across browsers for consistent rendering. 5. **User Control:** Avoid removing useful defaults like textarea resizing. 6. **Custom Fonts:** Use `@font-face` with multiple formats (woff2 + woff) for compatibility. --- ## 2. Advanced Form Styling > **Source:** ### Overview This section covers styling form controls that are difficult to style using CSS, categorized into "bad" (more complex CSS needed) and "ugly" (impossible to style thoroughly) categories. **The Bad:** - Checkboxes and radio buttons - `` **The Ugly:** - Dropdown widgets: `` - Date-related controls: `` - `` - `` - `` and `` ### The `appearance` Property The `appearance` property controls OS-level styling on form controls. The most useful value is `none`, which removes system-level styling and allows custom CSS styling. ```css input { appearance: none; } ``` This stops controls from using system-level styling, allowing you to build custom styles using CSS. ### Styling Checkboxes and Radio Buttons #### Approach: Using `appearance: none` Remove the default checkbox/radio styles completely and create custom designs: ```html
Fruit preferences

``` #### CSS Custom Checkbox Styling ```css input[type="checkbox"] { appearance: none; position: relative; width: 1em; height: 1em; border: 1px solid gray; /* Adjusts the position of the checkboxes on the text baseline */ vertical-align: -2px; /* Set here so that Windows' High-Contrast Mode can override */ color: green; } input[type="checkbox"]::before { content: "\2714"; position: absolute; font-size: 1.2em; right: -1px; top: -0.3em; visibility: hidden; } input[type="checkbox"]:checked::before { /* Use `visibility` instead of `display` to avoid recalculating layout */ visibility: visible; } input[type="checkbox"]:disabled { border-color: black; background: #dddddd; color: gray; } ``` **Key Pseudo-Classes:** - `:checked` -- checkbox/radio button is in a checked state - `:disabled` -- checkbox/radio button is disabled and cannot be interacted with ### Search Boxes and `appearance` For `` elements, `appearance: none` was historically necessary but is no longer required in Safari 16+. Removing the "x" delete button: ```css input[type="search"]:not(:focus, :active)::-webkit-search-cancel-button { display: none; } ``` ### Styling "Ugly" Form Controls #### Global Normalization Apply consistent styles across all form controls: ```css button, label, input, select, progress, meter { display: block; font-family: inherit; font-size: 100%; margin: 0; box-sizing: border-box; width: 100%; padding: 5px; height: 30px; } input[type="text"], input[type="datetime-local"], input[type="color"], select { box-shadow: inset 1px 1px 3px #cccccc; border-radius: 5px; } ``` ### Styling Select and Datalist Elements #### Creating a Custom Select Arrow ```html
``` ```css select { appearance: none; width: 100%; height: 100%; } .select-wrapper { position: relative; } .select-wrapper::after { content: "\25BC"; font-size: 1rem; top: 3px; right: 10px; position: absolute; } ``` **Limitations:** - You cannot style the dropdown option box that appears when clicked. - You cannot style the autocomplete list with ``. - For full control, use a library, build a custom control, or use the `multiple` attribute. ### Styling Date Input Types Date/time inputs (`datetime-local`, `time`, `week`, `month`) have limited styling options: ```css input[type="datetime-local"] { box-shadow: inset 1px 1px 3px #cccccc; border-radius: 5px; } ``` The containing box can be styled, but internal parts (popup calendar, spinners) cannot. For full control, use a custom control library or build your own. ### Styling Range Input Types Range sliders can be customized with significant CSS effort: ```css input[type="range"] { appearance: none; background: red; height: 2px; padding: 0; outline: 1px solid transparent; } ``` Full range styling requires complex CSS with browser-specific pseudo-elements (`::-webkit-slider-thumb`, `::-moz-range-thumb`, etc.). ### Styling Color Input Types ```css input[type="color"] { border: 0; padding: 0; } ``` For more significant customization, a custom solution is required. ### Styling File Input Types File inputs are mostly stylable except for the file picker button, which is completely unstylable. The recommended approach is to hide the input and style the label. ```html ``` ```css input[type="file"] { height: 0; padding: 0; opacity: 0; } label[for="file"] { box-shadow: 1px 1px 3px #cccccc; background: linear-gradient(to bottom, #eeeeee, #cccccc); border: 1px solid darkgrey; border-radius: 5px; text-align: center; line-height: 1.5; } label[for="file"]:hover { background: linear-gradient(to bottom, white, #dddddd); } label[for="file"]:active { box-shadow: inset 1px 1px 3px #cccccc; } ``` #### JavaScript to Display File Information ```javascript const fileInput = document.querySelector("#file"); const fileList = document.querySelector("#file-list"); fileInput.addEventListener("change", updateFileList); function updateFileList() { while (fileList.firstChild) { fileList.removeChild(fileList.firstChild); } const curFiles = fileInput.files; if (curFiles.length > 0) { for (const file of curFiles) { const listItem = document.createElement("li"); listItem.textContent = `File name: ${file.name}; file size: ${returnFileSize(file.size)}.`; fileList.appendChild(listItem); } } } function returnFileSize(number) { if (number < 1e3) { return `${number} bytes`; } else if (number >= 1e3 && number < 1e6) { return `${(number / 1e3).toFixed(1)} KB`; } return `${(number / 1e6).toFixed(1)} MB`; } ``` ### Styling Progress and Meter Elements Progress bars and meters are the most difficult to style. ```css progress, meter { display: block; width: 100%; padding: 5px; height: 30px; } ``` **Limitations:** - Inconsistent height handling between browsers. - Cannot style foreground bar color separately. - `appearance: none` makes things worse, not better. - **Recommendation:** Use custom solutions or third-party libraries. ### Summary of Styling Approaches | Control Type | Approach | Difficulty | |---|---|---| | Checkbox/Radio | `appearance: none` + custom design | Medium | | Search input | `appearance: none` for older browsers | Low | | Select/Datalist | Wrapper + custom arrow, limited control | Medium | | Date inputs | Basic styling only | High | | Range slider | `appearance: none` + complex pseudo-elements | High | | Color input | Remove borders/padding | Low | | File input | Hide + style label | Medium | | Progress/Meter | Custom solution recommended | Very High | ### Key Takeaways 1. Use `appearance: none` to remove OS-level styling before applying custom CSS. 2. Pseudo-classes like `:checked` and `:disabled` are essential for form control states. 3. Some controls (dropdown internals, file button, progress internals) have inherent limitations. 4. For full customization of "ugly" elements, consider custom JavaScript-based controls, third-party libraries, or modern HTML/CSS features like Customizable Select Elements. --- ## 3. Customizable Select Elements > **Source:** ### Overview Customizable select elements allow you to build fully-styled ``, `` elements:** - Work like traditional selects but with additional permitted content types. - `

``` **Key Markup Points:** - Use `aria-hidden="true"` on decorative icons to prevent duplicate announcements to assistive technology. - `` represents the select button and allows style customization. - Multi-element `