Tworzenie komponentu Ustawienia

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

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

Wersja demonstracyjna

Jeśli wolisz filmy lub chcesz zobaczyć podgląd interfejsu, nad którym pracujemy, obejrzyj ten krótszy film w 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 prezentacja GUI Challenge, która jest w całości oparta na siatce CSS. Każda siatka jest wyróżniona za pomocą Narzędzi deweloperskich w Chrome dla siatki:

Kolorowe obrysy i nakładki odstępów, które pomagają wyświetlić wszystkie pola składające się na układ ustawień.

Tylko dla luki

Najczęstszy układ:

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

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

Z tej strategii korzysta 5 układów. Oto one:

Układy siatki pionowej wyróżnione obrysami i wypełnionymi przerwami

Element fieldset, który zawiera każdą grupę wejściową (.fieldset-item), używa gap: 1px do tworzenia cienkich linii między elementami. Bez skomplikowanego 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);
    }
  }
}

Zawijanie wierszy w siatce naturalnej

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

Wyśrodkowywanie zawijanych treści

Zarówno flexbox, jak i grid umożliwiają align-items lub align-content, a w przypadku elementów zawijających content wyrównanie układucontent rozdzieli przestrzeń między elementami podrzędnymi jako grupą.

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

Głównym elementem jest użycie place-content: center skrótu wyrównania, aby elementy podrzędne były wyśrodkowane w pionie i poziomie w układach jedno- i dwukolumnowych.

Na powyższym filmie możesz zobaczyć, jak „treść” pozostaje wyśrodkowana, mimo że nastąpiło zawijanie.

Powtórz autodopasowanie minmax

<form> korzysta z adaptacyjnego układu siatki w każdej sekcji. Układ ten zmienia się z 1-kolumnowego na 2-kolumnowy w zależności od dostępnej przestrzeni.

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ć responsywnemu układowi indywidualny charakter. Gdy kolumny są ułożone jedna pod drugą, chcemy, aby odstęp między nimi był duży, ale nie tak duży jak na szerokim ekranie.

Właściwość grid-template-columns korzysta z 3 funkcji CSS: repeat(), minmax()min(). Una Kravets napisała na ten temat świetny post na blogu o układach, nazywając to RAM.

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

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

Dodatkowa funkcja min() jest dobrze opisana przez Evana Minto na jego blogu w poście Intrinsically Responsive CSS Grid with minmax() and min(). Zachęcam do jego przeczytania. flex-startKorekta wyrównania 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 w YouTube znajdziesz krótkie omówienie tego dodatku do wyrównania.

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

Co się dzieje? Gdy podana jest wartość max-width, zapewnia ona kontekst, wyraźne określenie rozmiaru lub określony rozmiar, aby auto-fitalgorytm układu wiedział, ile powtórzeń może zmieścić w przestrzeni. Chociaż wydaje się oczywiste, że przestrzeń ma „pełną szerokość”, zgodnie ze specyfikacją siatki CSS musi być podany określony rozmiar lub maksymalny rozmiar. Podałem maksymalny rozmiar.

Dlaczego więc 89vw? Dlatego, że „pasuje” do mojego układu. Ja i kilka innych osób z zespołu Chrome sprawdzamy, dlaczego bardziej rozsądna wartość, np. 100vw, nie wystarcza i czy jest to błąd.

Odstępy

Większość harmonii tego układu wynika z ograniczonej palety odstępów, a dokładnie z 7 odstępów.

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

Te przepływy dobrze współgrają z siatką, CSS @nest i składnią poziomu 5 funkcji @media. Oto przykład pełnego zestawu stylów <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ń widoku, rozszerza się ona, zwiększając dopełnienie. Usługa porównywania cen w 2021 roku wygląda całkiem dobrze.

Pamiętasz wcześniejszy układ „tylko dla odstępu”? Oto pełniejsza 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 koloru 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);
}

Kolory powierzchni i tekstu oznaczam numerami, a nie nazwami, np. surface-darksurface-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 dotyczącym preferencji, takim jak to:

: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 trochę się pospieszyłem, więc cofnijmy się na chwilę.

LCH?

Nie zagłębiając się zbytnio w teorię kolorów, LCH to składnia zorientowana na człowieka, która odzwierciedla sposób, w jaki postrzegamy kolory, a nie sposób, w jaki mierzymy je za pomocą matematyki (np. 255). Daje to wyraźną przewagę, ponieważ ludzie mogą łatwiej pisać w tym stylu, a inni ludzie będą rozumieć te zmiany.

Zrzut ekranu ze strony pod.link/csspodcast z wybranym odcinkiem podcastu Color 2: Perception
Dowiedz się więcej o kolorach postrzeganych (i nie tylko!) w podcaście CSS.

W tej prezentacji skupimy się na składni i wartościach, które zmieniam, aby uzyskać jasny i ciemny motyw. Spójrzmy na 1 powierzchnię i 1 kolor 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) oznacza 10% jasność, 0 chromatyczności i 0 odcienia: bardzo ciemny bezbarwny odcień szarości. Następnie w zapytaniu o multimedia dla trybu jasnego jasność jest odwracana na 90% za pomocą --surface1: lch(90 0 0);. To jest sedno tej strategii. Zacznij od zmiany jasności między 2 motywami, zachowując współczynniki kontrastu wymagane przez projekt lub takie, które zapewniają dostępność.

Zaletą lch() jest to, że jasność jest zorientowana na człowieka i możemy mieć pewność, że zmiana o % będzie postrzegana jako %. hsl() jest na przykład mniej wiarygodny.

Jeśli chcesz dowiedzieć się więcej o przestrzeniach kolorów, przeczytaj ten artykuł. lch() Nadchodzi!

Obecnie nie ma dostępu do tych kolorów. Powtórzę: nie mamy dostępu do jednej trzeciej kolorów na większości nowoczesnych monitorów. Nie są to jednak zwykłe kolory, ale najżywsze kolory, jakie może wyświetlić ekran. Nasze witryny są wyblakłe, ponieważ sprzęt monitora rozwijał się szybciej niż specyfikacje CSS i implementacje przeglądarek.

Lea Verou

Adaptacyjne elementy formularza z schematem kolorów

Wiele przeglądarek, np. Safari i Chromium, ma elementy sterujące motywem ciemnym, ale musisz określić w CSS lub HTML, że Twój projekt ich używa.

Powyższy przykład pokazuje efekt działania właściwości w panelu Style w Narzędziach deweloperskich. W wersji demonstracyjnej użyto tagu HTML, który moim zdaniem jest ogólnie lepszym rozwiązaniem:

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

Więcej informacji na ten temat znajdziesz w tym color-schemeartykule autorstwa Thomasa Steinera. Możesz zyskać znacznie więcej niż tylko ciemne pola wyboru.

CSS accent-color

Ostatnio pojawiła się aktywność związana z accent-color w elementach formularza. Jest to pojedynczy styl CSS, który może zmieniać kolor odcienia używany w elemencie wejściowym przeglądarki. Więcej informacji znajdziesz tutaj w GitHubie. Dodałem go do stylów tego komponentu. Gdy przeglądarki będą obsługiwać tę funkcję, moje pola wyboru będą bardziej pasować do motywu z różowymi i fioletowymi akcentami.

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

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

Wyostrzenie kolorów z ustalonymi gradientami i skupieniem wewnątrz

Kolor najbardziej rzuca się w oczy, 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 informacji zwrotnych i interakcji w interfejsie, które nadają interakcji charakteru dzięki:

  • Wyróżnianie kontekstu.
  • Przekazywanie informacji w interfejsie o tym, jak bardzo wartość jest zbliżona do maksymalnej.
  • Przekazywanie informacji o tym, że pole przyjmuje dane wejściowe.

Aby przekazywać informacje zwrotne, gdy użytkownik wchodzi w interakcję z elementem, CSS używa pseudoklasy :focus-within do zmiany wyglądu różnych elementów. Przyjrzyjmy się bliżej .fieldset-item:

.fieldset-item {
  ...

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

    & svg {
      fill: white;
    }

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

Gdy jedno z dzieci tego elementu jest zaznaczone:

  1. Tło .fieldset-item ma przypisany kolor powierzchni o wyższym kontraście.
  2. Zagnieżdżony element svg jest wypełniony kolorem białym, aby zapewnić większy kontrast.
  3. Zagnieżdżony element <picture> clip-path rozszerza się do pełnego koła, a tło wypełnia jasny, stały gradient.

Zakres niestandardowy

Na przykładzie tego elementu wejściowego HTML pokażę Ci, jak dostosowałem jego wygląd:

<input type="range">

Ten element składa się z 3 części, które musimy dostosować:

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

Style elementu 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 CSS to niestandardowe części stylów. Mam nadzieję, że ich wyraźne oznaczenie będzie pomocne. Pozostałe style to głównie style resetowania, które zapewniają spójną podstawę do tworzenia skomplikowanych części komponentu.

Style ścieżek

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;
}

Chodzi o „odsłonięcie” żywego koloru wypełnienia. Służy do tego gradient z ostrym przejściem u góry. Gradient jest przezroczysty do momentu osiągnięcia procentu wypełnienia, a potem używa koloru powierzchni niewypełnionej ścieżki. Za tym nie wypełnionym obszarem znajduje się kolor na całej szerokości, 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 kciuka miał taką samą wysokość jak ścieżka. Nie udało mi się znaleźć rozwiązania 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 jest 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ą.

Ten post na stronie CSS-Tricks autorstwa Any Tudor zawiera rozwiązanie oparte wyłącznie na CSS, które umożliwia wypełnienie ścieżki. Ten rangeelement też bardzo mnie zainspirował.

Style miniatury

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 tworzenia ładnego okręgu. Ponownie widzisz tam stały gradient tła, który ujednolica dynamiczne kolory miniatur, ścieżek i powiązanych elementów SVG. Rozdzieliłem style interakcji, aby wyodrębnić technikę box-shadow używaną do wyróżnienia 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;
  }
}

Chcieliśmy stworzyć łatwy w obsłudze i animowany element wizualny, który będzie wyróżniać opinie użytkowników. Używając cienia pola, mogę uniknąć wywoływania układu za pomocą efektu. Robię to, tworząc cień, który nie jest rozmyty i pasuje do okrągłego kształtu elementu miniatury. Następnie zmieniam i przekształcam rozmiar rozkładówki po najechaniu kursorem.

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

Selektory w różnych przeglądarkach

Aby zapewnić spójność w różnych przeglądarkach, potrzebne były te selektory: -webkit--moz-.

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

Niestandardowe pole wyboru

Na przykładzie tego elementu wejściowego HTML pokażę Ci, jak dostosowałem jego wygląd:

<input type="checkbox">

Ten element składa się z 3 części, które musimy dostosować:

  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-styleposition przygotowują element pozorny, który wprowadzimy później, aby ostylować wyróżnienie. W przeciwnym razie będą to głównie drobne kwestie związane ze stylem. Chcę, aby kursor był wskaźnikiem, chcę przesunięć konturu, domyślne pola wyboru są zbyt małe, a jeśli accent-color jest obsługiwane, chcę, aby te pola wyboru były w kolorach marki.

Etykiety pól wyboru

Etykiety pól wyboru są ważne z 2 powodów. Pierwszy z nich to określenie, do czego służy wartość pola wyboru, czyli odpowiedź na pytanie „włączone lub wyłączone w jakim celu?”. Drugi powód to UX – użytkownicy internetu przyzwyczaili się do wchodzenia w interakcje 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>

Umieść na etykiecie atrybut for, który wskazuje pole wyboru według identyfikatora: <label for="text-notifications">. W przypadku pola wyboru podwój zarówno nazwę, jak i identyfikator, aby mieć pewność, że zostanie ono znalezione za pomocą różnych narzędzi i technologii, takich jak mysz czy czytnik ekranu:<input type="checkbox" id="text-notifications" name="text-notifications"> :hover, :active i inne funkcje są dostępne bezpłatnie w ramach połączenia, co zwiększa możliwości 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żywać w przypadku pola wyboru. Miniatura mogła używać właściwości box-shadowspread do powiększania i pomniejszania cienia. Ten efekt nie działa jednak w tym przypadku, ponieważ nasze pola wyboru są kwadratowe i takie powinny być.

Ten sam efekt wizualny udało mi się uzyskać za pomocą pseudoelementu i niezwykle 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 w postaci okręgu jest proste, ale umieszczenie go za elementem, do którego jest dołączony, było trudniejsze. Oto przykład przed i po poprawieniu:

To zdecydowanie mikrointerakcja, ale zależy mi na zachowaniu spójności wizualnej. Technika skalowania animacji jest taka sama jak w innych miejscach. Ustawiamy niestandardową właściwość na nową wartość i pozwalamy CSS na jej przejście na podstawie preferencji dotyczących ruchu. Kluczową funkcją jest translateZ(-1px). Rodzic utworzył przestrzeń 3D, a ten element podrzędny pseudo-elementu wykorzystał ją, umieszczając się nieco z tyłu w przestrzeni z.

Ułatwienia dostępu

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

Wybór elementów HTML

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

Każda z nich zawiera wskazówki i porady dotyczące narzędzia do przeglądania. Niektóre elementy zawierają wskazówki dotyczące interakcji, inne łączą interaktywność, a jeszcze inne pomagają kształtować drzewo dostępności, 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">

Powyższy film pokazuje, jak działa czytnik ekranu w systemie macOS. Zwróć uwagę, jak zaznaczenie pola wejściowego przechodzi bezpośrednio z jednego suwaka na drugi. Dzieje się tak, ponieważ ukryliśmy ikonę, która mogła być przystankiem w drodze do następnego suwaka. Bez tego atrybutu użytkownik musiałby się zatrzymać, posłuchać i przejść obok obrazu, którego może nie widzieć.

SVG to zbiór działań matematycznych. Dodajmy element <title>, aby uzyskać bezpłatny tytuł po najechaniu kursorem myszy i komentarz zrozumiały dla człowieka, który wyjaśni, co tworzą te działania:

<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ącej ilości wyraźnie oznaczonych elementów HTML, dzięki czemu testy formularza działają bardzo dobrze w przypadku myszy, klawiatury, kontrolerów do gier i czytników ekranu.

JavaScript

Omówiłem już, jak kolor wypełnienia ścieżki jest zarządzany za pomocą JavaScriptu, więc przyjrzyjmy się teraz powiązanemu kodowi JavaScript:<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 użytkownik wchodzi w interakcję z formularzem i go zmienia, konsola rejestruje go jako obiekt w tabeli, aby można go było łatwo sprawdzić przed przesłaniem na serwer.

Zrzut ekranu z wynikami działania funkcji console.table(), na którym dane z formularza są wyświetlane w tabeli.

Podsumowanie

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

Urozmaićmy nasze podejście i poznajmy wszystkie sposoby tworzenia treści w internecie. Utwórz demo, wyślij mi tweeta z linkami, a dodam je do sekcji Remiksy społeczności poniżej.

Remiksy społeczności

  • @tomayac za ich styl dotyczący obszaru najazdu w przypadku etykiet pól wyboru. W tej wersji nie ma odstępu między elementami demosource po najechaniu na nie kursorem.