STYLING
FORMS

Front-end elective,

3rd Semester

But first...

An extensive talk about

CORS

by Jonas Holbech

But first...

An extensive talk about

CORS

by Jonas Holbech

But first...

An extensive talk about

CORS

by Jonas Holbech

Styling

Search for a topic of interest...

Search

HTML forms

Styling

A better user experience

HTML forms

Frontend elective, 3rd SEM

Search

Search for a topic of interest...

HTML forms

style

CSS

UI States

What are states?

  • "Situations"

  • Two or more circumstances

  • "On or Off"

  • "To do", "doing", "done"

  • Improves UX (sometimes)

Input states

HTML Forms

Styling Forms

Last time

Today

Mostly HTML

Mostly CSS

Today's focus

  • Understand form states
  • Styling techniques
  • Style organization
  • Basic accessibility principles

Pseudo-classes

A CSS pseudo-class is a keyword added to a selector that specifies a special state of the selected element(s). For example, :hover can be used to change a button's color when the user's pointer hovers over it.

Pseudo-classes

Pseudo-classes

:valid

represents any <input> or other <form> element whose contents validate successfully

input:valid {
  border-color: green;
}

needs "required"

Pseudo-classes

:invalid

any <input> or other <form> element whose contents fail to validate.

input:invalid {
  border-color: red;
}

needs "required"

Pseudo-classes = states

Pseudo-classes = states

Pseudo-classes = states

What Jonas sees

Pseudo-classes = states

Pseudo-classes / states

:disabled

represents any disabled element

:checked

selector represents any radio, checkbox, or option element that is checked or toggled to an on state

:focus

represents an element that has received focus

:placeholder-shown

represents any <input> or <textarea> element that is currently displaying placeholder text.

:not(

:not(

:not(

:not(

)

)

)

)

Pseudo-classes / states

:disabled

doesn't represents any disabled element

:checked

selector represents any radio, checkbox, or option element that is not checked or toggled to an on state

:focus

represents an element that hasn't received focus

:placeholder-shown

represents any <input> or <textarea> element that is currently not displaying placeholder text.

:not(

:not(

:not(

:not(

)

)

)

)

input:invalid:not(:focus, :placeholder-shown) { ... }

Placeholder-shown

input:invalid:not(:focus, :placeholder-shown) ~ .error-message { ... }

JS is required to adhere to A11y standards

:has()

.form-group:has(input:invalid) { ... }
.form-group:has(input:not(:focus, :placeholder-shown):invalid) .error-message { ... }
.form-group:has(input:not(:focus, :placeholder-shown):invalid) label { ... }

:has()

.form-group:has(input:invalid) { ... }
.form-group:has(input:not(:focus, :placeholder-shown):invalid) .error-message { ... }
label:has( + input:not(:focus, :placeholder-shown):invalid) { ... }

:has()

:has()

:has()

label {
  color: var(--color);
}

.form-field:has(:invalid) {
  --color: red;
}

.form-field:has(:valid) {
  --color: green;
}

:has()

:has()

:has()

:has()

Browser compatibility

🫢

form:focus-within {
  border-color: blue;
}
.form-control:focus-within .hint {
  color: red;
}

:focus-within

:focus-within

Exercise

Focus states

Focus states

Safari 💩

Focus states

Firefox 💩

Focus states

:focus-visible {
  outline: 2px solid #000;
  outline-offset: -2px;
  box-shadow: 0 0 0 2px #fff, inset 0 0 0 3px #fff;
}

input {
  appearance: none; /* Safari fix */
}

Add “states” (aka. pseudo-classes) to your form

  • :focus-visible
  • :valid
  • :invalid (with error messages)
  • :disabled
  • :has

Add styles for the following pseudo-classes:

Checkbox "hack"

Custom Checkboxes / Radios

User Agent styles

UA styles

:root {
  accent-color: deeppink;
}

doesn't work in Safari 💩

it does actually now (15.4) 🎊

but...

UA styles

form {
  accent-color: deeppink;
}

Rule of Least Power

Customize

input {
  appearance: none;
  ...
}

/* Checked state */
input:checked::before {
  ...
}

Remove browser styles

Style custom checkmark with pseudo-elements

Helpful resources

Make it interesting

Reduces cognitive load

Make it interesting

Animated checkmark

Animated checkmark

Preparing an SVG in Figma / Illustrator / XD

Animated checkmark

Animated checkmark

Animated checkmark

Resources

Task 2 (optional)

Craft your own form design

  • Style the form elements in your video game form
  • Style the different states with the corresponding pseudo-classes
  • Customize your form controls (e.g. radio, checkbox, etc)

Default:

:focus

Buttons

Custom checkboxes and radio buttons

:invalid

:disabled

Craft your own form design

Craft your own form design

Style organization

reset

Style organization

form,
fieldset,
legend,
input,
button,
textarea,
select {
  margin: 0;
  padding: 0;
}

input,
button,
textarea,
select {
  font-family: inherit;
  font-size: max(16px, 1em);
}

button {
  appearance: none;
  border: 1px solid;
  background: transparent;
  cursor: pointer;
}

input[type="text"],
input[type="email"],
textarea {
  appearance: none;
  border: 1px solid;
  background: transparent;
}

reset

Origin

Style organization

Your styles (Author styles)

0,0,0

0,0,1

🤷‍♂️

Cascade layers

Cascade layers

@layer reset {
  /* ... other reset rules */
  
  input[type="text"] {
    border: 1px solid gray;
  }
}

@layer components {
  /* ... other component rules */
  
  .my-input {
    border: 4px solid blue;
  }
}

order matters

Cascade layers

@layer reset, components, utilities;


@layer reset {
  /* ... other reset rules */
  
  input[type="text"] {
    border: 1px solid gray;
  }
}

@layer components {
  /* ... other component rules */
  
  .my-input {
    border: 4px solid blue;
  }
}

configure up front

1

2

3

Cascade layers

@layer reset, components, utilities;


@layer components {
  /* ... other component rules */
  
  .my-input {
    border: 4px solid blue;
  }
}

@layer reset {
  /* ... other reset rules */
  
  input[type="text"] {
    border: 1px solid gray;
  }
}

configure up front

1

2

3

Cascade layers

@layer reset, components, states;

@layer components {
  /* Buttons, inputs etc. */
}

@layer states {
  /* Make sure stats override, no matter specificity count */
  :disabled {
    background-color: #ddd;
    color: #999;
  }
  
  :focus-visible {
    outline: 2px solid var(--focus-color, currentColor);
    outline-offset: 2px;
  }
}

A sensible CSS reset

Default styling

:root {
  --theme-color: 258 29% 43%;
  --accent-color: 180 50% 43%;
}

input {
  font-family: inherit;
  font-size: max(16px, 1em);
  padding: 0.25em 0.5em;
  background-color: #fff;
  border: 2px solid hsl(var(--theme-color));
}

input:is(:focus-visible, :hover) {
  border-color: hsl(var(--accent-color));
}

A sensible CSS reset

Default styling

input:is([type="checkbox"], [type="radio"]) {
  appearance: none;
  /* custom styling */
}

A sensible CSS reset

Or with accent-color

form {
  accent-color: var(--theme-color, hotpink);
  /* checkbox, radio, progress, range etc. */
}

A sensible CSS reset

Form layout

form {
  display: grid;
  gap: 1.5rem;
}

.form-group {
  display: grid;
  gap: .3125rem;
}
form {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

form > input {
  flex: 1 1 10ch;
}

input[type="email"] {
  flex: 3 1 30ch;
}
.container {
  container-type: inline-size;
}

@container (width > 25rem) {
  .newsletter { ... }
}

Extensions

axe Accessibility Linter

Error Lens

Buttons

Differentiate between primary and secondary buttons

Buttons

User Interface

Make your form look & feel nice

Contrast

Too many websites are too hard to read for too many people

Contrast

Contrast

Contrast

Contrast

Contrast

Contrast

DevTools

DevTools

DevTools

Resources

Layout & style

Layout & style

Tiny helpers

Line Height

@media (prefers-color-scheme: dark) {
  /* Dark styles */
}

Dark mode

html {
  --background-color: #222;
  --foreground-color: #fafafa;
}

@media (prefers-color-scheme: dark) {
  html {
    --background-color: #fafafa;
    --foreground-color: #222;
  }
}

body {
  background-color: var(--background-color);
  color: var(--foreground-color);
}

Dark mode

@media (prefers-color-scheme: dark) {
  /* Dark styles */
}

Dark mode

Color palette

Color palette

💩

Color palette

💩

Color palette

Color palette

Color palette

Color palette

Color palette

Styling forms

By Dannie Vinther

Styling forms

Styling forms

  • 521