Xây dựng thành phần Cài đặt

Tổng quan cơ bản về cách tạo thành phần cài đặt của thanh trượt và hộp đánh dấu.

Trong bài đăng này, tôi muốn chia sẻ suy nghĩ về việc tạo thành phần Cài đặt cho web thích ứng, hỗ trợ nhiều đầu vào của thiết bị và hoạt động trên trình duyệt. Xem bản minh hoạ.

Bản minh hoạ

Nếu bạn thích xem video hơn hoặc muốn xem trước giao diện/trải nghiệm người dùng của những gì chúng tôi đang tạo, đây là hướng dẫn từng bước ngắn hơn trên YouTube:

Tổng quan

Tôi đã chia nhỏ những khía cạnh của thành phần này thành những phần sau:

  1. Bố cục
  2. Màu
  3. Dữ liệu đầu vào của dải ô tuỳ chỉnh
  4. Nhập hộp đánh dấu tuỳ chỉnh
  5. Những điều cần cân nhắc về khả năng hỗ trợ tiếp cận
  6. JavaScript

Bố cục

Đây là bản minh hoạ Thử thách GUI đầu tiên dành cho tất cả Lưới CSS! Sau đây là mỗi lưới được làm nổi bật bằng Công cụ của Chrome cho lưới:

Các đường viền đầy màu sắc và lớp phủ khoảng cách giãn cách giúp hiển thị tất cả các hộp tạo nên bố cục cài đặt

Để trống

Bố cục phổ biến nhất:

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

Tôi gọi bố cục này là "chỉ để tạo khoảng trống" vì nó chỉ sử dụng lưới để tạo thêm khoảng cách giữa các khối.

5 bố cục sử dụng chiến lược này, sau đây là toàn bộ bố cục hiển thị:

Bố cục lưới dọc được làm nổi bật với các đường viền và lấp đầy khoảng trống

Phần tử fieldset chứa từng nhóm đầu vào (.fieldset-item) đang sử dụng gap: 1px để tạo đường viền chân tóc giữa các thành phần. Không có giải pháp đường viền phức tạp nào!

Lấp đầy khoảng trống
.grid {
  display: grid;
  gap: 1px;
  background: var(--bg-surface-1);

  & > .fieldset-item {
    background: var(--bg-surface-2);
  }
}
Thủ thuật vẽ đường viền
.grid {
  display: grid;

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

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

Tự nhiên xuống dòng

Bố cục phức tạp nhất cuối cùng là bố cục macro, bố cục logic hệ thống từ <main> đến <form>.

Căn giữa nội dung xuống dòng

Cả hộp linh hoạt và lưới đều có thể align-items hoặc align-content và khi xử lý các phần tử gói, bố cục content Việc căn chỉnh sẽ phân bổ không gian giữa các thành phần con thành một nhóm.

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

Phần tử chính đang sử dụng căn chỉnh place-content: center viết tắt nên để các phần tử con được căn giữa theo chiều dọc và chiều ngang trong cả bố cục một và hai cột.

Xem "nội dung" trong video trên luôn ở chính giữa, ngay cả khi xuống dòng đã xảy ra.

Lặp lại chế độ tự động điều chỉnh kích thước tối đa tối đa

<form> sử dụng bố cục lưới thích ứng cho từng phần. Bố cục này chuyển từ một đến hai cột dựa trên không gian có sẵn.

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

Lưới này có một giá trị cho row-gap (--space-xl) khác với column-gap (--space-xxl) để tạo điểm nhấn tuỳ chỉnh trên bố cục thích ứng. Khi các cột được xếp chồng, chúng ta muốn một khoảng cách lớn, nhưng không lớn như thể chúng ta sử dụng màn hình rộng.

Thuộc tính grid-template-columns sử dụng 3 hàm CSS: repeat(), minmax()min(). Una Kravets có một blog về bố cục tuyệt vời đăng về chủ đề này, RAM.

Có 3 bổ sung đặc biệt trong bố cục của chúng ta, nếu bạn so sánh với bố cục của Una:

  • Chúng ta truyền một hàm min() bổ sung.
  • Chúng ta chỉ định align-items: flex-start.
  • Có kiểu max-width: 89vw.

Hàm min() bổ sung được Evan Minto mô tả rõ ràng trên blog của họ trong đăng Lưới CSS phản hồi nội tại với minmax() và min(). Bạn nên đọc qua. Chỉnh sửa căn chỉnh flex-start là xoá hiệu ứng kéo giãn mặc định để phần tử con của bố cục này không cần có chiều cao bằng nhau, chúng có thể có chiều cao tự nhiên, nội tại. Chiến lược phát hành đĩa đơn Video trên YouTube có thông tin phân tích nhanh về việc bổ sung căn chỉnh này.

max-width: 89vw có giá trị phân tích nhỏ trong bài đăng này. Hãy để tôi cho bạn thấy bố cục có và không áp dụng kiểu:

Chuyện gì đang xảy ra? Khi bạn chỉ định max-width, hàm này sẽ cung cấp ngữ cảnh, kích thước rõ ràng hoặc xác định kích thước cho auto-fit thuật toán bố cục để biết cách nhiều lần lặp lại, nó có thể phù hợp với không gian. Mặc dù rõ ràng là không gian là "chiều rộng đầy đủ", theo thông số lưới CSS, kích thước xác định hoặc kích thước tối đa phải sẽ được cung cấp. Tôi đã cung cấp kích thước tối đa.

Vậy tại sao lại là 89vw? Vì "nó hoạt động" cho bố cục của mình. Tôi và một vài người dùng Chrome khác đang tìm hiểu lý do tại sao lại có một giá trị hợp lý hơn, như 100vw là không đủ và nếu đây thực sự là lỗi.

Giãn cách

Phần lớn sự hài hoà của bố cục này đến từ bảng màu hạn chế về khoảng cách, 7 chính xác hơn.

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

Việc sử dụng các flow này thực sự phù hợp với cú pháp lưới, CSS @nestcú pháp cấp 5 của @media. Dưới đây là một ví dụ về tập hợp bố cục <main> đầy đủ.

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

Lưới có nội dung ở giữa, được đệm vừa phải theo mặc định (như trên thiết bị di động). Nhưng khi có thêm không gian khung nhìn, khung nhìn sẽ mở rộng bằng cách tăng khoảng đệm. CSS 2021 có vẻ khá ổn!

Bạn còn nhớ bố cục trước đó, "chỉ để tạo khoảng trống"? Sau đây là phiên bản hoàn chỉnh hơn của cách chúng trông như thế nào trong thành phần này:

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

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

Màu

Việc sử dụng màu sắc có kiểm soát đã giúp thiết kế này nổi bật nhưng vẫn sinh động tối thiểu. Tôi làm như sau:

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

Tôi đặt tên màu cho bề mặt và văn bản bằng số thay vì các tên như surface-darksurface-darker vì trong một truy vấn đa phương tiện, tôi sẽ lật màu sáng và tối sẽ không có ý nghĩa.

Tôi lật chúng trong một truy vấn phương tiện ưu tiên như sau:

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

Bạn cần xem nhanh bức tranh và chiến lược tổng thể trước chúng ta sẽ đi sâu vào chi tiết về cú pháp màu. Nhưng vì tôi đã đi trước một chút, hãy để tôi sao lưu một chút.

LCH?

Không đi sâu vào lĩnh vực lý thuyết màu sắc, LCH là cú pháp do con người hướng đến, phục vụ cho cách chúng ta cảm nhận màu sắc, chứ không phải cách chúng ta đo màu bằng toán học (như 255). Điều này mang lại cho nó một lợi thế rõ ràng vì con người có thể viết mã dễ dàng hơn và con người sẽ thích ứng với những điều chỉnh này.

Ảnh chụp màn hình trang web pod.link/csspodcast, với Màu 2: Tập cảm nhận được hiển thị
Tìm hiểu về các màu nhận biết (và nhiều thông tin khác!) trong Podcast CSS

Hôm nay, trong bản minh hoạ này, hãy tập trung vào cú pháp và các giá trị mà tôi đang sử dụng để tạo chế độ sáng và tối. Hãy cùng xem 1 bề mặt và 1 màu văn bản:

: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) chuyển thành độ sáng 10%, 0 sắc độ và 0 sắc độ: a màu xám không màu rất sẫm. Sau đó, trong truy vấn phương tiện cho chế độ sáng, độ sáng được đổi thành 90% bằng --surface1: lch(90 0 0);. Và đó là ý chính của chiến lược. Bắt đầu bằng cách chỉ thay đổi độ sáng giữa 2 chủ đề, duy trì tỷ lệ tương phản mà thiết kế cần hoặc những yếu tố có thể duy trì khả năng tiếp cận.

lch() ở đây có lợi ích là sự nhẹ nhàng đó hướng đến con người và chúng ta có thể cảm thấy tốt về một thay đổi % đối với nó, rằng thay đổi đó sẽ dễ nhận biết và nhất quán % khác biệt. Ví dụ: hsl() không phải là đáng tin cậy.

Các lựa chọn khác tìm hiểu về hệ màu và lch() nếu bạn quan tâm. Sắp có!

CSS hiện không thể sử dụng các màu này. Để tôi nhắc lại: Chúng ta không thể sử dụng 1/3 màu sắc trong các màu sắc hiện đại nhất màn hình. Và đây không chỉ là bất kỳ màu nào, mà còn là màu sắc sống động nhất màn hình có thể hiển thị. Các trang web của chúng tôi sắp hết do phần cứng màn hình đã được cải tiến nhanh hơn so với thông số kỹ thuật CSS và việc triển khai trình duyệt.

Lea Verou

Chế độ điều khiển biểu mẫu thích ứng sử dụng bảng phối màu

Nhiều trình duyệt có các công cụ điều khiển giao diện tối, hiện là Safari và Chromium, nhưng bạn phải chỉ định trong CSS hoặc HTML rằng thiết kế của bạn sử dụng chúng.

Phần trên là minh hoạ hiệu quả của thuộc tính trong bảng điều khiển Kiểu của Công cụ cho nhà phát triển. Bản minh hoạ này sử dụng thẻ HTML, theo ý kiến của tôi thì đây thường là vị trí tốt hơn:

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

Tìm hiểu tất cả trong color-scheme này bài viết của Thomas steiner. Có nhiều lợi ích hơn nữa so với đầu vào hộp đánh dấu tối!

Dịch vụ so sánh giá (CSS) accent-color

gần đây hoạt động xung quanh accent-color trên các phần tử biểu mẫu, là một kiểu CSS có thể thay đổi phủ màu được sử dụng trong phần tử đầu vào của trình duyệt. Đọc thêm về vấn đề này tại đây trên GitHub. Tôi đã đưa mục này vào kiểu cho thành phần này. Khi các trình duyệt hỗ trợ tính năng này, hộp đánh dấu của tôi sẽ là chủ đề nổi bật hơn với màu hồng và tím nổi bật.

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

Ảnh chụp màn hình trong Chromium trên Linux, trong đó có các hộp đánh dấu màu hồng

Ảnh nổi bật màu với độ dốc cố định và tiêu điểm bên trong

Màu sắc nổi bật nhất khi sử dụng một cách tiết kiệm và là một trong những cách tôi muốn đạt được thông qua các tương tác nhiều màu sắc trên giao diện người dùng.

Có nhiều lớp phản hồi và tương tác trên giao diện người dùng trong video trên, giúp tạo nên cá tính riêng cho hoạt động tương tác bằng cách:

  • Ngữ cảnh nêu bật.
  • Cung cấp ý kiến phản hồi về "mức độ đầy đủ" trên giao diện người dùng giá trị nằm trong dải ô.
  • Cung cấp ý kiến phản hồi trên giao diện người dùng về một trường đang chấp nhận dữ liệu đầu vào.

Để cung cấp phản hồi khi một phần tử đang được tương tác, CSS sử dụng :focus-within giả để thay đổi giao diện của các phần tử khác nhau, hãy phân tích .fieldset-item, vô cùng thú vị:

.fieldset-item {
  ...

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

    & svg {
      fill: white;
    }

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

Khi một trong các phần tử con của phần tử này có tâm điểm nằm trong:

  1. Nền .fieldset-item được gán màu cho bề mặt có độ tương phản cao hơn.
  2. svg lồng nhau được tô màu trắng để có độ tương phản cao hơn.
  3. <picture> clip-path lồng nhau mở rộng thành một vòng tròn đầy đủ và được tô màu nền bằng hiệu ứng chuyển màu sáng và cố định.

Phạm vi tùy chỉnh

Với phần tử đầu vào HTML sau, tôi sẽ cho bạn biết cách tôi tuỳ chỉnh diện mạo:

<input type="range">

Có 3 phần trong phần tử này mà chúng ta cần tuỳ chỉnh:

  1. Phần tử phạm vi / vùng chứa
  2. Theo dõi
  3. Hình thích

Kiểu phần tử phạm vi

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 */
}

Một vài dòng đầu tiên của CSS là phần tuỳ chỉnh của kiểu và tôi hy vọng hãy gắn nhãn rõ ràng cho chúng. Các kiểu còn lại chủ yếu là đặt lại kiểu để cung cấp nền tảng nhất quán để xây dựng những phần phức tạp của thành phần.

Kiểu bản nhạc

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

Bí quyết cho vấn đề này là "hé lộ" màu nền rực rỡ. Việc này được thực hiện bằng chuyển màu ở trên cùng. Độ dốc trong suốt đến tỷ lệ phần trăm tô màu và sau sử dụng màu của giao diện kênh chưa được lấp đầy. Đằng sau bề mặt chưa được lấp đầy đó, là màu có độ rộng tối đa, chờ độ trong suốt hiển thị màu đó.

Kiểu tô màu theo dõi

Thiết kế của tôi yêu cầu JavaScript để duy trì kiểu tô màu nền. Có là các chiến lược chỉ dành cho CSS nhưng chúng yêu cầu phần tử thumb phải có cùng chiều cao bản nhạc, và tôi không thể tìm thấy sự hài hoà trong những giới hạn đó.

/* 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));
  })
})

Tôi nghĩ điều này tạo ra sự nâng cấp trực quan đẹp mắt. Thanh trượt hoạt động hiệu quả mà không cần JavaScript, tài sản --track-fill là không bắt buộc, chỉ đơn giản là nó sẽ không có kiểu tô màu nền nếu không có. Nếu có JavaScript, hãy điền vào đồng thời quan sát mọi thay đổi của người dùng, đồng bộ hoá thuộc tính tuỳ chỉnh với giá trị đó.

Đây là đăng bài trên CSS-Tricks của Ana Tudor, minh hoạ giải pháp chỉ dành cho CSS cho theo dõi lấp đầy. Tôi cũng tìm thấy thông tin này Yếu tố range rất truyền cảm hứng.

Kiểu ngón tay cái

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

Phần lớn các kiểu này là để tạo một vòng tròn đẹp. Một lần nữa, bạn lại thấy độ dốc của nền cố định ở đó hợp nhất màu động của hình thu nhỏ, bản nhạc và phần tử SVG được liên kết. Tôi đã phân tách các kiểu cho hoạt động tương tác để giúp tách biệt box-shadow kỹ thuật đang được sử dụng để làm nổi bật khi di chuột:

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

Mục tiêu là dễ quản lý và tạo ảnh động làm nổi bật cho người dùng phản hồi. Bằng cách sử dụng bóng hộp, tôi có thể tránh kích hoạt bố cục có hiệu ứng. Tôi làm việc này bằng cách tạo bóng không bị mờ và khớp với hình tròn của ngón tay cái. Sau đó, tôi thay đổi và chuyển đổi kích thước trải rộng khi di chuột.

Nếu chỉ có hiệu ứng đánh dấu là dễ dàng như vậy đối với các hộp đánh dấu...

Bộ chọn trên nhiều trình duyệt

Tôi nhận thấy mình cần bộ chọn -webkit--moz- này để sử dụng được trên nhiều trình duyệt tính nhất quán:

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

Hộp đánh dấu tuỳ chỉnh

Với phần tử đầu vào HTML sau, tôi sẽ cho bạn biết cách tôi tuỳ chỉnh diện mạo:

<input type="checkbox">

Có 3 phần trong phần tử này mà chúng ta cần tuỳ chỉnh:

  1. Phần tử hộp đánh dấu
  2. Nhãn được liên kết
  3. Hiệu ứng làm nổi bật

Thành phần hộp đánh dấu

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

Kiểu transform-styleposition chuẩn bị cho phần tử giả mà chúng tôi sẽ giới thiệu sau để tạo kiểu cho điểm nổi bật. Nếu không, thì chủ yếu những nội dung mang phong cách cố định nhỏ của tôi. Tôi thích con trỏ là con trỏ, tôi thích độ lệch đường viền, hộp đánh dấu mặc định là quá nhỏ và nếu accent-colorđược hỗ trợ, hãy sử dụng hộp đánh dấu vào bảng phối màu của thương hiệu.

Nhãn hộp đánh dấu

Bạn cần cung cấp nhãn cho hộp đánh dấu vì 2 lý do. Đầu tiên là thể hiện mục đích sử dụng giá trị hộp đánh dấu, để trả lời câu hỏi "bật hoặc tắt cho mục đích gì?" Thứ hai là dành cho trải nghiệm người dùng (UX), người dùng web đã quen với việc tương tác với thông qua nhãn liên quan.

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

Trên nhãn của bạn, hãy đặt thuộc tính for trỏ đến một hộp đánh dấu theo mã nhận dạng: <label for="text-notifications">. Trong hộp đánh dấu, hãy nhân đôi cả tên và mã nhận dạng để đảm bảo người dùng có thể tìm thấy màn hình của bạn bằng nhiều công cụ và công nghệ, chẳng hạn như chuột hoặc trình đọc màn hình: <input type="checkbox" id="text-notifications" name="text-notifications">. :hover, :active và các thiết bị khác được cung cấp miễn phí khi kết nối, giúp tăng cách tương tác với biểu mẫu.

Nội dung nổi bật trong hộp đánh dấu

Tôi muốn giữ giao diện nhất quán và phần tử thanh trượt có hình thu nhỏ nổi bật mà tôi muốn sử dụng với hộp đánh dấu. Hình thu nhỏ đó có thể sử dụng box-shadow cùng với thuộc tính spread để mở rộng phạm vi đổ bóng và xuống. Tuy nhiên, hiệu ứng đó không có tác dụng ở đây vì các hộp đánh dấu của chúng ta, và nên là hình vuông.

Tôi đã có thể đạt được hiệu ứng hình ảnh tương tự với phần tử giả số lượng CSS phức tạp đáng tiếc:

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

Việc tạo một phần tử giả vòng tròn là công việc đơn giản, nhưng việc đặt nó việc chèn phần tử vào phần tử liên kết với khó khăn hơn. Sau đây là diễn biến trước và sau khi tôi khắc phục xong:

Đó chắc chắn là một tương tác vi mô nhưng quan trọng với tôi là đảm bảo hình ảnh nhất quán. Kỹ thuật chuyển tỷ lệ ảnh động giống như kỹ thuật chúng tôi đang sử dụng trong những nơi khác. Chúng tôi đặt một thuộc tính tuỳ chỉnh thành một giá trị mới và để CSS chuyển đổi giá trị đó dựa trên lựa chọn ưu tiên về chuyển động. Tính năng chính ở đây là translateZ(-1px). Chiến lược phát hành đĩa đơn phần tử mẹ đã tạo một không gian 3D và phần tử con giả này được nhấn vào bằng cách đặt nó lùi lại một chút trong không gian z.

Hỗ trợ tiếp cận

Video trên YouTube minh hoạ tuyệt vời về chuột, bàn phím và hoạt động tương tác của trình đọc màn hình cho thành phần cài đặt này. Tôi sẽ nêu ra một vài chi tiết tại đây.

Lựa chọn phần tử HTML

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

Mỗi chính sách trong số này chứa gợi ý và mẹo cho công cụ duyệt web của người dùng. Một số phần tử đưa ra gợi ý tương tác, một số tương tác có tính kết nối và một số giúp định hình cây hỗ trợ tiếp cận mà trình đọc màn hình điều hướng.

Thuộc tính HTML

Chúng tôi có thể ẩn các phần tử mà trình đọc màn hình không cần đến, trong trường hợp này là biểu tượng bên cạnh thanh trượt:

<picture aria-hidden="true">

Video ở trên minh hoạ quy trình của trình đọc màn hình trên Mac OS. Lưu ý cách nhập tiêu điểm di chuyển thẳng từ một thanh trượt đến thanh trượt tiếp theo. Lý do là vì chúng tôi đã ẩn biểu tượng có thể đã dừng lại trên đường đến thanh trượt tiếp theo. Nếu không có người dùng sẽ cần phải dừng lại, lắng nghe và di chuyển qua khỏi hình ảnh họ có thể không xem được.

SVG là một tập hợp toán học, hãy thêm phần tử <title> để di chuột miễn phí tiêu đề và một nhận xét mà con người có thể đọc được về sản phẩm mà phép toán đang tạo ra:

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

Ngoài ra, chúng tôi đã sử dụng HTML được đánh dấu rõ ràng đủ để các biểu mẫu kiểm tra thực sự hiệu quả trên chuột, bàn phím, tay điều khiển trò chơi điện tử và trình đọc màn hình.

JavaScript

Tôi đã đề cập đến cách quản lý màu nền theo dõi từ JavaScript, vì vậy, hãy xem xét JavaScript có liên quan đến <form> ngay bây giờ:

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

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

Mỗi khi người dùng tương tác và thay đổi biểu mẫu, bảng điều khiển sẽ ghi lại biểu mẫu là đối tượng vào bảng để dễ dàng xem xét trước khi gửi đến máy chủ.

Ảnh chụp màn hình kết quả console.table(), trong đó dữ liệu biểu mẫu được hiển thị trong một bảng

Kết luận

Giờ bạn đã biết cách tôi thực hiện điều đó, bạn sẽ làm thế nào?! Điều này mang lại niềm vui cấu trúc thành phần! Ai sẽ tạo phiên bản đầu tiên với vị trí trong khung yêu thích của bạn là gì? 🙂

Hãy đa dạng hoá phương pháp tiếp cận và tìm hiểu tất cả các cách xây dựng ứng dụng trên web. Tạo một bản minh hoạ, tweet cho tôi các đường liên kết và tôi sẽ thêm vào vào phần Bản phối lại của cộng đồng bên dưới!

Bản phối lại của cộng đồng

  • @tomayac với phong cách của họ khu vực di chuột cho các nhãn hộp đánh dấu! Phiên bản này không có khoảng cách di chuột giữa các phần tử: demonguồn.