Tworzenie komponentu Ustawienia

Podstawowe omówienie sposobu tworzenia komponentu ustawień z suwakami i polami wyboru.

W tym poście chcę podzielić się przemyśleniami na temat tworzenia komponentu Ustawienia dla internetu, który jest elastyczny, obsługuje wiele urządzeń wejściowych i działa w różnych przeglądarkach. Wypróbuj wersję demonstracyjną.

Wersja demonstracyjna

Jeśli wolisz obejrzeć film lub chcesz zobaczyć podgląd interfejsu i wrażeń użytkownika, obejrzyj ten krótki film na YouTube:

Przegląd

Aspekty tego komponentu zostały podzielone na te sekcje:

  1. Układy
  2. Kolor
  3. Pole do wpisania niestandardowego zakresu
  4. Niestandardowe pole wyboru
  5. Ułatwienia dostępu
  6. JavaScript

Układy

To pierwsza demonstracja w ramach wyzwania GUI, która jest w całości oparta na siatce CSS. Oto każda siatka wyróżniona za pomocą Narzędzi deweloperskich w Chrome:

kolorowe kontury i nakładki odstępów, które pomagają wyświetlić wszystkie pola tworzące układ ustawień;

Tylko w przypadku luki

Najczęstszy układ:

foo {
  display: grid;
  gap: var(--something);
}

Ten układ nazywam „tylko dla odstępów”, ponieważ używa siatki tylko do dodawania odstępów między blokami.

Tę strategię wykorzystuje 5 układów. Oto one:

Układy siatki pionowej wyróżnione konturami i wypełnionymi lukami

Element fieldset, który zawiera każdą grupę danych wejściowych (.fieldset-item), używa gap: 1px do tworzenia cienkich obramowań między elementami. Nie ma trudnego rozwiązania dotyczącego obramowania.

Wypełniona luka
.grid {
  display: grid;
  gap: 1px;
  background: var(--bg-surface-1);

  & > .fieldset-item {
    background: var(--bg-surface-2);
  }
}
Sztuczka z obramowaniem
.grid {
  display: grid;

  & > .fieldset-item {
    background: var(--bg-surface-2);

    &:not(:last-child) {
      border-bottom: 1px solid var(--bg-surface-1);
    }
  }
}

Naturalne zawijanie siatki

Najbardziej złożonym układem okazał się układ makro, czyli logiczny system układu między <main> a <form>.

Wyśrodkowanie zawartości zawijanej

Zarówno flexbox, jak i grid umożliwiają align-items lub align-content, a w przypadku elementów zawijanych wyrównanie układu content rozdziela przestrzeń między elementy podrzędne jako grupę.

main {
  display: grid;
  gap: var(--space-xl);
  place-content: center;
}

Element główny używa skrótu wyrównania place-content: center, dzięki czemu elementy podrzędne są wyśrodkowane w pionie i poziomie zarówno w układzie jednokolumnowym, jak i dwukolumnowym.

Na filmie powyżej widać, że „treść” pozostaje wyśrodkowana, mimo że nastąpiło zawijanie.

Powtórz autodopasowanie minmax

W każdej sekcji <form> używa układu siatki adaptacyjnej. Ten układ przełącza się z jednej na dwie kolumny w zależności od dostępnego miejsca.

form {
  display: grid;
  gap: var(--space-xl) var(--space-xxl);
  grid-template-columns: repeat(auto-fit, minmax(min(10ch, 100%), 35ch));
  align-items: flex-start;
  max-width: 89vw;
}

Ta siatka ma inną wartość dla row-gap (--space-xl) niż column-gap (--space-xxl), aby nadać układowi responsywnemu niestandardowy charakter. Gdy kolumny są ułożone jedna na drugiej, chcemy, aby odstęp był duży, ale nie tak duży jak na szerokim ekranie.

Właściwość grid-template-columns używa 3 funkcji CSS: repeat(), minmax() i min(). Una Kravets napisała na ten temat świetny post na blogu, w którym nazywa tę metodę RAM.

W porównaniu z układem Uny nasz układ zawiera 3 specjalne dodatki:

  • Przekazujemy dodatkową funkcję min().
  • Określamy align-items: flex-start.
  • Dostępny jest styl max-width: 89vw.

Dodatkowa funkcja min() jest dobrze opisana przez Evana Minto na jego blogu we wpisie Intrinsically Responsive CSS Grid with minmax() and min(). Polecam go przeczytać. Korekta wyrównania flex-start ma na celu usunięcie domyślnego efektu rozciągania, dzięki czemu elementy podrzędne tego układu nie muszą mieć równej wysokości, ale mogą mieć naturalną, wewnętrzną wysokość. W tym filmie na YouTube znajdziesz krótkie podsumowanie tej zmiany.

max-width: 89vw zasługuje na krótkie omówienie w tym poście. Poniżej pokazujemy układ z zastosowanym stylem i bez niego:

Co się dzieje? Gdy określono max-width, zapewnia to kontekst, wyraźny rozmiar lub określony rozmiar dla algorytmu układu auto-fit, aby wiedział, ile powtórzeń może zmieścić się w przestrzeni. Chociaż wydaje się oczywiste, że przestrzeń ma „pełną szerokość”, zgodnie ze specyfikacją siatki CSS należy podać określony rozmiar lub maksymalny rozmiar. Podano maksymalny rozmiar.

Dlaczego więc 89vw? Bo „to działało” w moim układzie. Wraz z kilkoma innymi osobami z zespołu Chrome sprawdzamy, dlaczego bardziej rozsądna wartość, np. 100vw, nie wystarcza i czy jest to błąd.

Odstępy

Harmonia tego układu wynika głównie z ograniczonej palety odstępów, a dokładnie 7.

:root {
  --space-xxs: .25rem;
  --space-xs:  .5rem;
  --space-sm:  1rem;
  --space-md:  1.5rem;
  --space-lg:  2rem;
  --space-xl:  3rem;
  --space-xxl: 6rem;
}

Te funkcje świetnie współgrają z siatką, CSS @nest i składnią @media na poziomie 5. Oto przykład: zestaw stylów układu w pełni <main>.

main {
  display: grid;
  gap: var(--space-xl);
  place-content: center;
  padding: var(--space-sm);

  @media (width >= 540px) {
    & {
      padding: var(--space-lg);
    }
  }

  @media (width >= 800px) {
    & {
      padding: var(--space-xl);
    }
  }
}

Siatka z wyśrodkowaną treścią, domyślnie z umiarkowanym dopełnieniem (jak na urządzeniach mobilnych). Jednak gdy dostępna jest większa przestrzeń widocznego obszaru, rozprzestrzenia się, zwiększając dopełnienie. W 2021 roku usługa porównywania cen wygląda całkiem dobrze.

Pamiętasz wcześniejszy układ „tylko dla luki”? Oto bardziej kompletna wersja tego, jak wyglądają w tym komponencie:

header {
  display: grid;
  gap: var(--space-xxs);
}

section {
  display: grid;
  gap: var(--space-md);
}

Kolor

Kontrolowane użycie kolorów sprawiło, że ten projekt wyróżnia się wyrazistością, a jednocześnie minimalizmem. Robię to tak:

:root {
  --surface1: lch(10 0 0);
  --surface2: lch(15 0 0);
  --surface3: lch(20 0 0);
  --surface4: lch(25 0 0);

  --text1: lch(95 0 0);
  --text2: lch(75 0 0);
}

Nazywam kolory powierzchni i tekstu liczbami, a nie nazwami takimi jak surface-dark i surface-darker, ponieważ w zapytaniu o media będę je odwracać, a jasny i ciemny nie będą miały znaczenia.

Odwracam je w zapytaniu o media preferencji w ten sposób:

:root {
  ...

  @media (prefers-color-scheme: light) {
    & {
      --surface1: lch(90 0 0);
      --surface2: lch(100 0 0);
      --surface3: lch(98 0 0);
      --surface4: lch(85 0 0);

      --text1: lch(20 0 0);
      --text2: lch(40 0 0);
    }
  }
}

Zanim przejdziemy do szczegółów składni kolorów, warto rzucić okiem na ogólny obraz i strategię. Ale ponieważ trochę się pospieszyłem, pozwól, że się cofnę.

LCH?

Bez zagłębiania się w teorię kolorów, LCH to składnia zorientowana na człowieka, która odpowiada temu, jak postrzegamy kolory, a nie temu, jak mierzymy je za pomocą matematyki (np. 255). Daje to wyraźną przewagę, ponieważ ludzie mogą łatwiej pisać takie teksty, a inni ludzie będą lepiej reagować na te zmiany.

Zrzut ekranu strony pod.link/csspodcast z odcinkiem Color 2: Perception
Dowiedz się więcej o kolorach postrzeganych (i nie tylko) w CSS Podcast

W tej demonstracji skupmy się na składni i wartościach, które zmieniam, aby uzyskać jasny i ciemny motyw. Przyjrzyjmy się 1 kolorowi powierzchni i 1 kolorowi tekstu:

:root {
  --surface1: lch(10 0 0);
  --text1:    lch(95 0 0);

  @media (prefers-color-scheme: light) {
    & {
      --surface1: lch(90 0 0);
      --text1:    lch(40 0 0);
    }
  }
}

--surface1: lch(10 0 0) odpowiada jasności 10%, nasyceniu 0 i odcieniowi 0, czyli bardzo ciemnej, bezbarwnej szarości. Następnie w zapytaniu o media dla trybu jasnego jasność jest zmieniana na 90% za pomocą --surface1: lch(90 0 0);. I to jest sedno strategii. Zacznij od zmiany jasności między 2 motywami, zachowując współczynniki kontrastu wymagane przez projekt lub zapewniające dostępność.

The bonus with lch() here is that lightness is human oriented, and we can feel good about a % change to it, that it will be perceptually and consistently that % different. hsl() na przykład nie jest tak niezawodny.

Jeśli chcesz, możesz dowiedzieć się więcej o przestrzeniach barw i lch(). Już niedługo!

Obecnie CSS nie ma dostępu do tych kolorów. Powtórzę: nie mamy dostępu do 1/3 kolorów na większości nowoczesnych monitorów. I nie są to byle jakie kolory, ale najbardziej żywe barwy, jakie ekran może wyświetlić. Nasze witryny są wyblakłe, ponieważ sprzęt monitorów rozwijał się szybciej niż specyfikacje CSS i implementacje przeglądarek.

Lea Verou

Adaptacyjne elementy sterujące formularza ze schematem kolorów

Wiele przeglądarek, obecnie Safari i Chromium, ma opcje ciemnego motywu, ale musisz określić w CSS lub HTML, że Twój projekt ich używa.

Powyżej pokazano efekt właściwości z panelu Style w Narzędziach deweloperskich. W wersji demonstracyjnej użyto tagu HTML, który moim zdaniem jest ogólnie lepszym miejscem:

<meta name="color-scheme" content="dark light">

Więcej informacji znajdziesz w tym color-scheme artykule, którego autorem jest Thomas Steiner. Możesz zyskać o wiele więcej niż tylko ciemne pola wyboru.

Usługa porównywania cen accent-color

Ostatnio dużo się działo wokół accent-color w elementach formularza, czyli pojedynczego stylu CSS, który może zmieniać kolor odcienia używany w elemencie wejściowym przeglądarki. Więcej informacji na ten temat znajdziesz tutaj na GitHubie. Uwzględniłem go w stylach tego komponentu. Ponieważ przeglądarki obsługują tę funkcję, moje pola wyboru będą bardziej pasować do motywu dzięki różowym i fioletowym akcentom kolorystycznym.

input[type="checkbox"] {
  accent-color: var(--brand);
}

Zrzut ekranu z Chromium w systemie Linux przedstawiający różowe pola wyboru

Wyostrzenie kolorów ze stałymi gradientami i fokusem

Kolor jest najbardziej widoczny, gdy jest używany oszczędnie. Jednym ze sposobów, w jaki lubię to osiągać, są kolorowe interakcje w interfejsie.

W powyższym filmie widać wiele warstw interakcji i informacji zwrotnych w interfejsie, które nadają interakcji charakter:

  • Wyróżnianie kontekstu.
  • Przekazywanie w interfejsie informacji o tym, „jak pełna” jest wartość w zakresie.
  • Przekazywanie informacji zwrotnej w interfejsie, że pole akceptuje dane wejściowe.

Aby przekazać informację zwrotną, gdy użytkownik wchodzi w interakcję z elementem, CSS używa pseudoklasy :focus-within do zmiany wyglądu różnych elementów. Przyjrzyjmy się .fieldset-item, to bardzo ciekawe:

.fieldset-item {
  ...

  &:focus-within {
    background: var(--surface2);

    & svg {
      fill: white;
    }

    & picture {
      clip-path: circle(50%);
      background: var(--brand-bg-gradient) fixed;
    }
  }
}

Gdy jeden z elementów podrzędnych tego elementu ma focus-within:

  1. Tło .fieldset-item ma przypisany kolor powierzchni o wyższym kontraście.
  2. Zagnieżdżona ikona svg jest wypełniona kolorem białym, aby zapewnić większy kontrast.
  3. Zagnieżdżony element <picture> clip-path rozwija się do pełnego okręgu, a tło wypełnia się jasnym, stałym gradientem.

Niestandardowy zakres

Poniżej pokazuję, jak dostosować wygląd elementu wejściowego HTML:

<input type="range">

Musimy dostosować 3 części tego elementu:

  1. Element/kontener zakresu
  2. Program
  3. Thumb

Style elementów zakresu

input[type="range"] {
  /* style setting variables */
  --track-height: .5ex;
  --track-fill: 0%;
  --thumb-size: 3ex;
  --thumb-offset: -1.25ex;
  --thumb-highlight-size: 0px;

  appearance: none;         /* clear styles, make way for mine */
  display: block;
  inline-size: 100%;        /* fill container */
  margin: 1ex 0;            /* ensure thumb isn't colliding with sibling content */
  background: transparent;  /* bg is in the track */
  outline-offset: 5px;      /* focus styles have space */
}

Pierwsze kilka wierszy kodu CSS to niestandardowe części stylów. Mam nadzieję, że ich wyraźne oznaczenie ułatwi Ci pracę. Pozostałe style to głównie style resetowania, które zapewniają spójną podstawę do tworzenia trudnych części komponentu.

Style tras

input[type="range"]::-webkit-slider-runnable-track {
  appearance: none; /* clear styles, make way for mine */
  block-size: var(--track-height);
  border-radius: 5ex;
  background:
    /* hard stop gradient:
        - half transparent (where colorful fill we be)
        - half dark track fill
        - 1st background image is on top
    */
    linear-gradient(
      to right,
      transparent var(--track-fill),
      var(--surface1) 0%
    ),
    /* colorful fill effect, behind track surface fill */
    var(--brand-bg-gradient) fixed;
}

Sztuczka polega na „odsłonięciu” żywego koloru wypełnienia. Służy do tego gradient z ostrym przejściem na górze. Gradient jest przezroczysty do wartości procentowej wypełnienia, a następnie używa koloru powierzchni niewypełnionej ścieżki. Za tą niewypełnioną powierzchnią znajduje się kolor na całą szerokość, który czeka na ujawnienie przez przezroczystość.

Styl wypełnienia ścieżki

Mój projekt wymaga JavaScriptu, aby zachować styl wypełnienia. Istnieją strategie oparte wyłącznie na CSS, ale wymagają one, aby element suwaka miał taką samą wysokość jak ścieżka, a ja nie mogłem znaleźć harmonii w tych granicach.

/* grab sliders on page */
const sliders = document.querySelectorAll('input[type="range"]')

/* take a slider element, return a percentage string for use in CSS */
const rangeToPercent = slider => {
  const max = slider.getAttribute('max') || 10;
  const percent = slider.value / max * 100;

  return `${parseInt(percent)}%`;
};

/* on page load, set the fill amount */
sliders.forEach(slider => {
  slider.style.setProperty('--track-fill', rangeToPercent(slider));

  /* when a slider changes, update the fill prop */
  slider.addEventListener('input', e => {
    e.target.style.setProperty('--track-fill', rangeToPercent(e.target));
  })
})

Myślę, że to dobra zmiana wizualna. Suwak działa świetnie bez JavaScriptu, właściwość --track-fill nie jest wymagana, po prostu nie będzie miała stylu wypełnienia, jeśli nie będzie obecna. Jeśli JavaScript jest dostępny, wypełnij właściwość niestandardową, obserwując jednocześnie wszelkie zmiany wprowadzane przez użytkownika i synchronizując właściwość niestandardową z wartością.

Oto świetny post na stronie CSS-Tricks autorstwa Any Tudor, który przedstawia rozwiązanie oparte wyłącznie na CSS do wypełniania ścieżki. Bardzo inspirujący był też dla mnie ten element: range.

Style kciuka

input[type="range"]::-webkit-slider-thumb {
  appearance: none; /* clear styles, make way for mine */
  cursor: ew-resize; /* cursor style to support drag direction */
  border: 3px solid var(--surface3);
  block-size: var(--thumb-size);
  inline-size: var(--thumb-size);
  margin-top: var(--thumb-offset);
  border-radius: 50%;
  background: var(--brand-bg-gradient) fixed;
}

Większość tych stylów służy do utworzenia ładnego okręgu. Ponownie widzisz stały gradient tła, który ujednolica dynamiczne kolory suwaków, ścieżek i powiązanych elementów SVG. Style interakcji zostały rozdzielone, aby ułatwić wyodrębnienie techniki box-shadow używanej do podświetlania po najechaniu kursorem:

@custom-media --motionOK (prefers-reduced-motion: no-preference);

::-webkit-slider-thumb {
  …

  /* shadow spread is initally 0 */
  box-shadow: 0 0 0 var(--thumb-highlight-size) var(--thumb-highlight-color);

  /* if motion is OK, transition the box-shadow change */
  @media (--motionOK) {
    & {
      transition: box-shadow .1s ease;
    }
  }

  /* on hover/active state of parent, increase size prop */
  @nest input[type="range"]:is(:hover,:active) & {
    --thumb-highlight-size: 10px;
  }
}

Celem było stworzenie łatwego w zarządzaniu i animowanego wyróżnienia wizualnego dla opinii użytkowników. Używając cienia, mogę uniknąć wywoływania układu przez efekt. W tym celu tworzę cień, który nie jest rozmyty i pasuje do okrągłego kształtu elementu suwaka. Następnie zmieniam i przekształcam rozmiar rozprzestrzeniania po najechaniu kursorem.

Gdyby tylko efekt podświetlenia był tak łatwy do uzyskania w przypadku pól wyboru…

Selektory między przeglądarkami

Aby uzyskać spójność między przeglądarkami, musiałem użyć tych selektorów: -webkit- i -moz-:

input[type="range"] {
  &::-webkit-slider-runnable-track {}
  &::-moz-range-track {}
  &::-webkit-slider-thumb {}
  &::-moz-range-thumb {}
}

Niestandardowe pole wyboru

Poniżej pokazuję, jak dostosować wygląd elementu wejściowego HTML:

<input type="checkbox">

Musimy dostosować 3 części tego elementu:

  1. Element pola wyboru
  2. Powiązane etykiety
  3. Efekt wyróżnienia

Element pola wyboru

input[type="checkbox"] {
  inline-size: var(--space-sm);   /* increase width */
  block-size: var(--space-sm);    /* increase height */
  outline-offset: 5px;            /* focus style enhancement */
  accent-color: var(--brand);     /* tint the input */
  position: relative;             /* prepare for an absolute pseudo element */
  transform-style: preserve-3d;   /* create a 3d z-space stacking context */
  margin: 0;
  cursor: pointer;
}

Style transform-style i position przygotowują pseudoelement, który wprowadzimy później, aby nadać styl wyróżnieniu. W przeciwnym razie są to głównie moje drobne uwagi dotyczące stylu. Chcę, żeby kursor był wskaźnikiem, lubię przesunięcia konturu, domyślne pola wyboru są za małe, a jeśli accent-color jest obsługiwany, chcę, żeby te pola wyboru były w schemacie kolorów marki.

Etykiety pól wyboru

Etykiety pól wyboru są ważne z 2 powodów. Pierwsza z nich określa, do czego służy wartość pola wyboru, czyli odpowiada na pytanie „co jest włączone lub wyłączone?”. Po drugie, ze względu na wygodę użytkowników internetu, którzy przyzwyczaili się do interakcji z polami wyboru za pomocą powiązanych z nimi etykiet.

wprowadzanie danych
<input
  type="checkbox"
  id="text-notifications"
  name="text-notifications"
>
etykieta
<label for="text-notifications">
  <h3>Text Messages</h3>
  <small>Get notified about all text messages sent to your device</small>
</label>

W etykiecie umieść atrybut for, który wskazuje pole wyboru według identyfikatora: <label for="text-notifications">. W przypadku pola wyboru podaj zarówno nazwę, jak i identyfikator, aby mieć pewność, że zostanie ono znalezione przez różne narzędzia i technologie, takie jak mysz czy czytnik ekranu: <input type="checkbox" id="text-notifications" name="text-notifications">. :hover, :active i inne są dostępne bezpłatnie w ramach połączenia, co zwiększa liczbę sposobów interakcji z formularzem.

Wyróżnienie pola wyboru

Chcę zachować spójność interfejsów, a element suwaka ma ładne podświetlenie miniatury, którego chcę użyć z polem wyboru. Miniatura mogła używać właściwości box-shadow i spread do skalowania cienia w górę i w dół. Jednak ten efekt nie działa tutaj, ponieważ nasze pola wyboru są i powinny być kwadratowe.

Udało mi się uzyskać ten sam efekt wizualny za pomocą pseudoelementu i dużej ilości skomplikowanego kodu CSS:

@custom-media --motionOK (prefers-reduced-motion: no-preference);

input[type="checkbox"]::before {
  --thumb-scale: .01;                        /* initial scale of highlight */
  --thumb-highlight-size: var(--space-xl);

  content: "";
  inline-size: var(--thumb-highlight-size);
  block-size: var(--thumb-highlight-size);
  clip-path: circle(50%);                     /* circle shape */
  position: absolute;                         /* this is why position relative on parent */
  top: 50%;                                   /* pop and plop technique (https://web.dev/centering-in-css#5-pop-and-plop) */
  left: 50%;
  background: var(--thumb-highlight-color);
  transform-origin: center center;            /* goal is a centered scaling circle */
  transform:                                  /* order here matters!! */
    translateX(-50%)                          /* counter balances left: 50% */
    translateY(-50%)                          /* counter balances top: 50% */
    translateZ(-1px)                          /* PUTS IT BEHIND THE CHECKBOX */
    scale(var(--thumb-scale))                 /* value we toggle for animation */
  ;
  will-change: transform;

  @media (--motionOK) {                       /* transition only if motion is OK */
    & {
      transition: transform .2s ease;
    }
  }
}

/* on hover, set scale custom property to "in" state */
input[type="checkbox"]:hover::before {
  --thumb-scale: 1;
}

Utworzenie pseudoelementu koła jest proste, ale umieszczenie go za elementem, do którego jest dołączony, było trudniejsze. Oto jak to wyglądało przed poprawką i po niej:

To zdecydowanie mikrointerakcja, ale ważne jest dla mnie zachowanie spójności wizualnej. Technika skalowania animacji jest taka sama jak ta, której używaliśmy w innych miejscach. Ustawiamy nową wartość właściwości niestandardowej i pozwalamy CSS na jej przejście na podstawie preferencji dotyczących ruchu. Najważniejsza funkcja to translateZ(-1px). Element nadrzędny utworzył przestrzeń 3D, a ten podrzędny pseudoelement wykorzystał ją, umieszczając się nieco z tyłu w przestrzeni Z.

Ułatwienia dostępu

Film na YouTube świetnie pokazuje interakcje z myszą, klawiaturą i czytnikiem ekranu w przypadku tego komponentu ustawień. Omówię tutaj niektóre szczegóły.

Opcje elementów HTML

<form>
<header>
<fieldset>
<picture>
<label>
<input>

Każdy z nich zawiera wskazówki i porady dotyczące narzędzia do przeglądania. Niektóre elementy dostarczają wskazówek dotyczących interakcji, inne łączą interaktywność, a jeszcze inne pomagają kształtować drzewo ułatwień dostępu, po którym porusza się czytnik ekranu.

Atrybuty HTML

Możemy ukryć elementy, które nie są potrzebne czytnikom ekranu, w tym przypadku ikonę obok suwaka:

<picture aria-hidden="true">

Film powyżej przedstawia działanie czytnika ekranu w systemie Mac OS. Zwróć uwagę, że fokus wejściowy przechodzi bezpośrednio z jednego suwaka na drugi. Dzieje się tak, ponieważ ukryliśmy ikonę, która mogła być przystankiem na drodze do następnego suwaka. Bez tego atrybutu użytkownik musiałby się zatrzymać, wysłuchać i przejść dalej, mimo że nie widzi obrazu.

Plik SVG to zbiór obliczeń matematycznych. Dodajmy element <title>, aby uzyskać bezpłatny tytuł po najechaniu kursorem i zrozumiały dla człowieka komentarz na temat tego, co tworzą te obliczenia:

<svg viewBox="0 0 24 24">
  <title>A note icon</title>
  <path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/>
</svg>

Poza tym użyliśmy wystarczająco dużo wyraźnie oznaczonego kodu HTML, aby formularz działał prawidłowo z myszą, klawiaturą, kontrolerami do gier wideo i czytnikami ekranu.

JavaScript

Wcześniej omówiliśmy, jak zarządzać kolorem wypełnienia ścieżki za pomocą kodu JavaScript, więc teraz przyjrzyjmy się kodowi JavaScript powiązanemu z elementem <form>:

const form = document.querySelector('form');

form.addEventListener('input', event => {
  const formData = Object.fromEntries(new FormData(form));
  console.table(formData);
})

Za każdym razem, gdy formularz jest używany i zmieniany, konsola rejestruje go jako obiekt w tabeli, aby ułatwić jego sprawdzenie przed przesłaniem na serwer.

Zrzut ekranu przedstawiający wyniki console.table(), gdzie dane formularza są wyświetlane w tabeli

Podsumowanie

Teraz, gdy już wiesz, jak ja to zrobiłem, jak Ty byś to zrobił? Dzięki temu architektura komponentów jest bardzo ciekawa. Kto stworzy pierwszą wersję ze slotami w swoim ulubionym frameworku? 🙂

Zróżnicujmy nasze podejście i poznajmy wszystkie sposoby tworzenia stron internetowych. Utwórz wersję demonstracyjną, wyślij mi linki na Twitterze, a ja dodam je do sekcji Remiksy społeczności poniżej.

Remiksy społeczności

  • @tomayac, który zaproponował styl obszaru najechania kursorem dla etykiet pól wyboru. W tej wersji nie ma odstępu między elementami po najechaniu kursorem: demo i źródło.