Title: CSS Form Control Styling Level 1
Shortname: css-forms
Level: 1
Repository: w3c/csswg-drafts
Prepare for TR: no
ED: https://drafts.csswg.org/css-forms-1/
TR: https://www.w3.org/TR/css-forms-1/
Editor: Tim Nguyen, w3cid 137443, Apple Inc. https://apple.com/, ntim@apple.com
Abstract: This CSS Module defines various ways of styling form controls and their different parts.
Group: csswg
Status: ED
Work Status: Exploring
Markup Shorthands: css yes, markdown yes
# Introduction # {#intro} This section is non-normative. User agents have long provided non-standard ways of styling form controls. However, all of these controls are implemented inconsistently across user agents, creating unnecessary friction for authors. This module aims to define a set of form control parts in enough detail that they can be used interoperably. It also defines some new ways of customizing form controls, covering common use cases that were previously only possible by implementing custom controls from scratch, which was a lot of work, hard to get right, and often broke either accessibility or platform conventions. # Opting Into [=Basic Appearance=]: the ''appearance: base'' value # {#appearance} ISSUE: Move definition of ''appearance'' here.
  Name: appearance
  New values: base
  
When applied on a form control, base puts that control in the basic appearance state. A control that has [=basic appearance=] is consistently styleable using standard CSS and the pseudo-elements defined below, and applies overridable default styles that are consistent across UAs. When a control is in that state, the user agent applies styles from the [[#basic-appearance-stylesheet]] to that control. The user agent must also enable the pseudo-elements defined by [[#pseudo-elements]]. These pseudo-elements (excluding ''::picker()'') always inherit 'appearance' from their [=originating element=]. The user agent may implement this using an ''appearance: inherit !important'' declaration. NOTE: The inheritance prevents authors from mixing native and non-native parts for the same control. ## Design Principles for the [=Basic Appearance=] ## {#basic-appearance-principles} The following design principles apply to the design of the [=basic appearance=] stylesheet for form controls, in approximate order of descending importance: 1. The styles are identical in every user agent. 1. The controls are recognizable and usable on their own without additional styles. 1. The controls pass 100% of WCAG 2.2 AA standards. 1. The styles are consistent across controls… 1. …in look & feel. 1. …in how they are defined in code. 1. …in sizing and interaction. 1. The styles are easily adapted to the website’s branding, without needing complex reset stylesheets: 1. They use minimal code and are easy to override. 1. They do not have a strong voice & tone of their own, and are visually as simple as possible. 1. They inherit page styles rather than define new styles whenever possible. 1. They are resilient to adjustments… 1. …when changed themselves (e.g. changing font, border, layout). 1. …when put in context (e.g. ready to be flex or grid children). 1. They are comprehensive: 1. Covering all states for each control. 1. Supporting all writing modes and color schemes. For HTML form controls specifically, these principles are applied through the required user agent stylesheet defined in [[#basic-appearance-stylesheet]]. ## Examples ## {#ex-appearance} ISSUE: Refine these examples through implementation, experimentation, bikeshedding and improvements to the user agent stylesheet. The main purpose of these examples is to show how the design principles for the [=basic appearance=] apply in practice. To apply the [=basic appearance=] on individual controls, the following code is used:
    input, textarea, meter, progress, button, select {
      appearance: base;
    }
  
NOTE: The form layout used by the following examples is not detailed. ### Default User Agent Colors ### {#colors} Here are the [=basic appearance=] colors inheriting respectively the default light and dark mode colors from the root element: Screenshot of the basic appearance with a light color scheme Screenshot of the basic appearance with a dark color scheme ### Color/Font Customization ### {#custom} Here are some examples of customization being done on top of the [=basic appearance=]:
    form {
      font-family: "American Typewriter";
      background-color: rgb(254, 252, 221);
      color: rgb(131, 17, 0);
    }

    input, textarea, meter, progress, button, select {
      appearance: base;
    }
    
Screenshot of a customized basic appearance with brown text and a pale yellow background
    form {
      font-family: "Courier New";
      font-size: 14px;
      background-color: rgb(0, 0, 0);
      color: rgb(0, 249, 0);
    }

    input, textarea, meter, progress, button, select {
      appearance: base;
    }
    
Screenshot of a customized basic appearance with green text and a black background
# Styling Pickers # {#pickers} ## The ''::picker()'' pseudo-element ## {#picker-pseudo} The ::picker() pseudo-element represents the part of the form control that pops out of the page.
    ::picker() = ::picker( <>+ )
    <> = select
  
The ''::picker()'' pseudo-element only matches when the [=originating element=] supports [=basic appearance=] and has a popup picker. The specified <> must also match the unique picker name of the [=originating element=]. For example, the [=unique picker name=] for the <{select}> element is ''select''. In order for the ''::picker()'' pseudo-element to be rendered, it and its [=originating element=] must both have a [=computed value|computed=] 'appearance' of ''appearance/base''.
The following styles apply the [=basic appearance=] to the select picker and the select and add some additional styling to the picker: ```css select, select::picker(select) { appearance: base; } select::picker(select) { border: 5px solid red; background-color: blue; } ```
NOTE: The non-functional form of ''::picker()'' currently doesn't work to prevent unintended styling of pickers as new pickers become supported. Once styling for all form control pickers is finalized, this non-functional form will work for all pickers. # Pseudo-Elements # {#pseudo-elements} Form controls are composed of many parts that authors may want to style separately, hence the need for user agents to provide pseudo-elements for individual form controls. The section below introduces a set of pseudo-elements that attempts to cover the most common use cases, so they can be addressed in a consistent manner across user agents.
Informative overview of form control pseudo-elements as applied to HTML
Control Pseudo-elements
``
        ├─ ''::slider-track''
        │  └─ ''::slider-fill''
        └─ ''::slider-thumb''
        
``
``
``
`` ''::checkmark''
``
`` ''::file-selector-button''
`` * ''::field-component'' * ''::field-separator'' * ''::picker-icon'' See [[#date-time-pseudos]]
``
``
``
``
`` (with no type) See [[#field-pseudos]]
``
``
``
``
``
``
`` See [[#number-pseudos]]
`` ''::color-swatch''
`