Aiyana  Miller

Aiyana Miller

1625058300

Azure Data Services at 50,000 Feet

Azure Data Services at 50,000 Feet

A fun, high level, look at Azure Data Services (PaaS) options, when you would use them, how they scale, and how they integrate with R and Python. This presentation demystifies the subject.

#azure #data services #paas

What is GEEK

Buddha Community

Azure Data Services at 50,000 Feet
Phung Dang

Phung Dang

1685662740

Tạo thanh trượt phạm vi CSS tùy chỉnh với các bản nâng cấp JavaScript

Trong hướng dẫn CSS này, chúng ta sẽ tìm hiểu về Cách tạo thanh trượt phạm vi tùy chỉnh bằng CSS. cách sử dụng các kỹ thuật CSS hiện đại để tạo một thanh trượt phạm vi tùy chỉnh, bắt mắt không có gì ngoài <input>phần tử HTML gốc.

Thanh trượt phạm vi ( <input type="range">) cho phép người dùng chọn một giá trị trong một phạm vi nhất định, cung cấp các loại đầu vào thay thế như <input type="number">.

Các kiểu thanh trượt phạm vi mặc định trông không đẹp lắm. Hình ảnh bên dưới cung cấp ý tưởng về phạm vi hiển thị của các thanh trượt mà chúng tôi sẽ tạo kiểu dáng theo mặc định trong Chrome, Firefox và Safari.

Thanh trượt phạm vi mặc định trong Chrome, Firefox và Safari

Nhưng <input>các yếu tố rất khó để tạo kiểu. Hầu hết các giải pháp trực tuyến để tạo kiểu cho chúng đều dựa trên JavaScript và một số mã lộn xộn. Tệ hơn nữa, một số kỹ thuật này còn phá vỡ khả năng tiếp cận của phần tử.

Vì vậy, hãy xem cách làm mọi thứ tốt hơn, chỉ sử dụng CSS và không ảnh hưởng đến khả năng truy cập. Bản trình diễn CodePen bên dưới cho thấy những gì chúng ta sẽ xây dựng.

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--g:12px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  --_c: color-mix(in srgb, var(--c), #000 var(--p,0%));
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  overflow: hidden;
}
input:focus-visible,
input:hover{
  --p: 25%;
}
input:active,
input:focus-visible{
  --_b: var(--s)
}
/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--_c);
  border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -webkit-appearance: none;
  appearance: none;
  transition: .3s;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  width: var(--s);
  background: none;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--_c);
  border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -moz-appearance: none;
  appearance: none;
  transition: .3s;
}
@supports not (color: color-mix(in srgb,red,red)) {
  input {
    --_c: var(--c);
  }
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Mát mẻ phải không? Bạn cũng sẽ tìm thấy các biến thể của các phong cách này ở cuối bài viết!

Cấu trúc của phần tử đầu vào phạm vi

Hãy bắt đầu bằng cách phân tích cấu trúc của phần tử đầu vào phạm vi. Đó là một phần tử gốc và mỗi trình duyệt có triển khai riêng các phần tử đó. Chúng tôi chủ yếu có hai triển khai khác nhau.

Có một ứng dụng dành cho các trình duyệt Webkit và Blink như Chrome, Edge, Safari và Opera:

<input type="range" min="0" max="100" step="1" value="20">
  <div>
    <div pseudo="-webkit-slider-runnable-track" id="track">
      <div id="thumb">
    </div>
   </div>
  </div>
</input>

Tổng quan về đầu vào Chrome

Và đây là cái dành cho Firefox:

<input type="range" min="0" max="100" step="1" value="20">
  <div></div>
  <div></div>
  <div></div>
</input>

Tổng quan về đầu vào Firefox

Có một triển khai thứ ba cho IE, nhưng may mắn thay, trình duyệt đó đã chết và biến mất ngay bây giờ!

Sự không nhất quán như vậy giữa các trình duyệt là điều khiến nhiệm vụ trở nên khó khăn, vì chúng tôi cần cung cấp các kiểu dáng khác nhau cho mỗi lần triển khai. Tôi sẽ không tìm hiểu thêm về vấn đề này vì bài viết sẽ không bao giờ kết thúc, nhưng tôi thực sự khuyên bạn nên đọc bài viết này của Ana Tudor để tìm hiểu sâu hơn.

Điều duy nhất bạn cần ghi nhớ là, bất kể việc triển khai là gì, chúng tôi luôn có “thumb” như một thành phần chung.

Hiển thị phần tử ngón tay cái

Tôi sẽ chỉ tạo kiểu cho phần tử này, điều này sẽ làm cho thanh trượt phạm vi tùy chỉnh của tôi dễ dàng tùy chỉnh. Hãy nhảy ngay vào mã để thấy điều kỳ diệu đang diễn ra.

Tùy chỉnh đầu vào

Bước đầu tiên là đặt lại và tắt tất cả các kiểu mặc định của trình duyệt bằng cách sử dụng appearance: nonevà một số thuộc tính phổ biến khác:

input {
  appearance :none;
  background: none;
  cursor: pointer;
}

Trong trường hợp phức tạp hơn, chúng ta có thể cần thêm nhiều mã hơn trong trường hợp các kiểu mặc định khác được áp dụng cho phần tử của chúng ta. Đơn giản chỉ cần đảm bảo rằng chúng ta có một phần tử “trần trụi” mà không cần bất kỳ kiểu dáng trực quan nào.

Chúng ta cũng hãy xác định một vài biến CSS để chúng ta có thể dễ dàng tạo các biến thể khác nhau cho thanh trượt phạm vi:

input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/

  width: 400px; /* input width */
  height: var(--s); 
  appearance :none;
  background: none;
  cursor: pointer;
}

Ở bước này, chỉ có ngón tay cái hiển thị với các kiểu mặc định của nó, như bản trình diễn CodePen bên dưới hiển thị.

<input type="range" min="0" max="100" step="1" value="20">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  overflow: hidden;
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Tạo kiểu cho phần tử Thumb

Hãy tạo kiểu cho phần tử ngón tay cái. Chúng ta sẽ bắt đầu với thiết lập cơ bản:

<thumb selector> {
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  appearance: none;
}

Mã nên tự giải thích. Không có gì lạ mắt cho đến nay và chúng tôi sẽ nhận được kết quả hiển thị bên dưới.

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--g:12px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  overflow: hidden;
}

/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  -webkit-appearance: none;
  appearance: none;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  width: var(--s);
  background: none;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  -moz-appearance: none;
  appearance: none;
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Lưu ý việc sử dụng hai bộ chọn khác nhau, như chúng tôi đã giải thích trong phần đầu tiên:

/* Chrome, Edge, Safari, Opera */
input[type="range" i]::-webkit-slider-thumb { }
/* Firefox */
input[type="range"]::-moz-range-thumb { }

Nhưng làm thế nào để bạn biết bộ chọn để sử dụng?

Tôi chỉ cần kiểm tra mã của đầu vào bằng các công cụ dành cho nhà phát triển của trình duyệt để xem bộ chọn mà mỗi trình duyệt đang sử dụng để tạo kiểu cho ngón tay cái. Bài viết trước tôi đã chia sẻ cho bạn thấy cách thao tác với các công cụ dành cho nhà phát triển để có được những thông tin đó.

Thêm một số phép thuật với hình ảnh đường viền

Bây giờ chúng ta sẽ sử dụng thủ thuật CSS kỳ diệu để hoàn thành thanh trượt của mình. Nó liên quan đến việc sử dụng border-image:

border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));

Tôi biết nó trông đáng sợ, nhưng hãy phân tích dòng đó và bạn sẽ thấy nó không khó lắm. Trên đây là cách viết tắt cho những điều sau đây:

border-image-source: linear-gradient(90deg,var(--c) 50%,#ababab 0); 
border-image-slice: 1;
border-image-width: 0 100vw;
border-image-outset: 0 calc(100vw + var(--g));

Từ trang MDN , chúng tôi đọc:

Thuộc border-imagetính CSS vẽ một hình ảnh xung quanh một phần tử nhất định. Nó thay thế đường viền thông thường của phần tử.

Hình ảnh của chúng ta sẽ là một dải màu có hai màu — màu chính (được xác định bởi --c) và màu xám. Chúng tôi cần hình ảnh đường viền để bao phủ toàn bộ không gian của đầu vào theo chiều ngang, vì vậy chúng tôi sử dụng một giá trị lớn cho chiều rộng bên trái và bên phải ( 100vw) trong khi chúng tôi giữ nguyên trên cùng và dưới cùng tại ( 0).

Nhưng border-image-widthđược giới hạn ở kích thước phần tử. Để khắc phục điều này, chúng ta cũng cần sử dụng một giá trị lớn cho the border-image-outsetđể tăng không gian có sẵn cho hình ảnh đường viền. Từ MDN một lần nữa:

Thuộc border-image-outsettính CSS đặt khoảng cách mà hình ảnh đường viền của phần tử được đặt ra khỏi hộp đường viền của nó.

Các phần của hình ảnh đường viền được hiển thị bên ngoài hộp đường viền của phần tử border-image-outsetkhông kích hoạt thanh cuộn tràn và không ghi lại các sự kiện chuột.

Khi bạn nhìn thấy thanh trượt lần đầu tiên, có vẻ như chúng ta đang tăng màu chính ở bên trái, nhưng trên thực tế, chúng ta đang trượt một dải màu cố định tràn ngập phần tử của chúng ta.

Bản trình diễn sau đây cung cấp một cái nhìn tổng quan về những gì đang diễn ra bên trong.

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--g:12px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  outline: 2px dashed #000;
}

/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  border-image-source: linear-gradient(90deg,var(--c) 50%,#ababab 0); 
  border-image-slice: 1;
  border-image-width: 0 200px;
  border-image-outset: 0 calc(200px + var(--g));
  -webkit-appearance: none;
  appearance: none;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  width: var(--s);
  background: none;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  -moz-appearance: none;
  appearance: none;
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Kéo ngón tay cái và trượt nó để xem mọi thứ đang di chuyển như thế nào. Tôi đang sử dụng một giá trị nhỏ cho chiều rộng và phần mở đầu để chúng ta có thể dễ dàng hiểu được thủ thuật.

Ngoài ra, lưu ý rằng phần đầu cần phải lớn hơn chiều rộng để có khoảng cách. Vì lý do này, nó được xác định bằng chiều rộng cộng với giá trị của khoảng cách.

Bằng cách thêm overflow: hiddenvào phần tử đầu vào và sử dụng một giá trị lớn, ảo ảnh trở nên hoàn hảo, như hình bên dưới.

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--g:12px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  outline: 2px dashed #000;
  overflow: hidden;
}

/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  border-image-source: linear-gradient(90deg,var(--c) 50%,#ababab 0); 
  border-image-slice: 1;
  border-image-width: 0 100vw;
  border-image-outset: 0 calc(100vw + var(--g));
  -webkit-appearance: none;
  appearance: none;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  width: var(--s);
  background: none;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  -moz-appearance: none;
  appearance: none;
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Thế còn border-image-slice? Tại sao giá trị của 1?

Thuộc tính này hơi phức tạp, nhưng bắt buộc khi sử dụng border-image. Trong trường hợp của chúng tôi, giá trị này không phù hợp lắm và một giá trị dương nhỏ sẽ thực hiện công việc. Tôi có một câu trả lời chi tiết về Stack Overflow nếu bạn muốn tìm hiểu thêm về nó.

Bước cuối cùng là giảm kích thước của thanh để phù hợp với kích thước mà chúng ta đã xác định bởi biến --l. Đối với điều này, chúng tôi sẽ sử dụng clip-path:

clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);

Hình ảnh dưới đây cung cấp tổng quan về các điểm khác nhau để hiểu hình dạng của đa giác.

Tổng quan về đa giác clip-path

Đó là nó! Chúng tôi có một thanh trượt phạm vi tùy chỉnh với một vài dòng mã mà bạn có thể dễ dàng kiểm soát bằng cách điều chỉnh một số biến.

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--g:12px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  overflow: hidden;
}

/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  border-image: linear-gradient(90deg,var(--c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -webkit-appearance: none;
  appearance: none;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  width: var(--s);
  background: none;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  border-image: linear-gradient(90deg,var(--c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -moz-appearance: none;
  appearance: none;
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Thêm một số hoạt ảnh

Còn một số hoạt ảnh tinh tế khi chúng ta tương tác với thanh trượt thì sao? Nó không cần nhiều mã và nó sẽ nâng cao UX của thanh trượt.

Đầu tiên, chúng ta sẽ chuyển đổi ngón tay cái từ một vòng tròn chỉ có viền thành một vòng tròn đầy đủ khi chúng ta nhấp vào nó. Đối với điều này, chúng tôi tăng giá trị lây lan của box-shadow. Hãy nhớ rằng chúng tôi đã sử dụng box-shadowđể xác định đường viền của ngón tay cái:

box-shadow: 0 0 0 var(--l) inset var(--c);

Chúng tôi cập nhật thành var(--l)bằng cách var(--s)sử dụng :activebộ chọn và tệp :focus-visible. Cái sau liên quan đến điều hướng bàn phím và cho phép chúng ta có tác dụng tương tự cho dù chúng ta sử dụng chuột hay bàn phím.

Mã này như sau:

input[type="range" i]::-webkit-slider-thumb {
  box-shadow: 0 0 0 var(--l) inset var(--c);
  transition: .3s;
}

input[type="range" i]::-moz-range-thumb {
  box-shadow: 0 0 0 var(--l) inset var(--c);
  transition: .3s;
}

input:active::-webkit-slider-thumb,
input:focus-visible::-webkit-slider-thumb {
  box-shadow: 0 0 0 var(--s) inset var(--c);
}

input:active::-moz-range-thumb,
input:focus-visible::-moz-range-thumb {
  box-shadow: 0 0 0 var(--s) inset var(--c);
}

Hơi dài dòng cho một box-shadowđoạn chuyển cảnh đúng không? Chúng ta có thể tối ưu hóa nó bằng một biến CSS:

input[type="range" i]::-webkit-slider-thumb {
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--c);
  transition: .3s;
}

input[type="range" i]::-moz-range-thumb {
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--c);
  transition: .3s;
}

input:active,
input:focus-visible {
  --_b:  var(--s);
}

Tôi đang biểu thị giá trị chênh lệch bằng cách sử dụng một biến và tôi chỉ đang cập nhật biến đó trên :active:focus-visible.

Tôi cũng sẽ thêm một chút hoạt ảnh vào màu sắc. Tôi sẽ làm cho nó tối hơn một chút trên :hover. Đối với điều này, tôi sẽ không cập nhật màu mà trộn nó với màu đen bằng color-mix()chức năng mới. Thủ thuật này cho phép chúng tôi sử dụng màu chính được xác định bởi --cthay vì xác định màu tối mới cho mỗi thanh trượt theo cách thủ công:

--_c: color-mix(in srgb, var(--c), #000 var(--p,0%));

Tôi đang xác định một biến mới sẽ thay thế biến --ctrong mã. Sau đó, bằng cách điều chỉnh tỷ lệ phần trăm của màu đen ( #000) bằng cách sử dụng biến --p, tôi đang kiểm soát “độ tối” của màu:

input:focus-visible,
input:hover{
  --p: 25%;
}

Tính năng này chưa được hỗ trợ trong mọi trình duyệt, vì vậy chúng tôi khuyên bạn nên sử dụng dự phòng:

@supports not (color: color-mix(in srgb,red,red)) {
  input {
    --_c: var(--c); /* if no support we keep the color as defined */
  }
}

Thanh trượt phạm vi của chúng tôi hiện đã hoàn hảo!

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--g:12px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  --_c: color-mix(in srgb, var(--c), #000 var(--p,0%));
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  overflow: hidden;
}
input:focus-visible,
input:hover{
  --p: 25%;
}
input:active,
input:focus-visible{
  --_b: var(--s)
}
/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--_c);
  border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -webkit-appearance: none;
  appearance: none;
  transition: .3s;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  width: var(--s);
  background: none;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--_c);
  border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -moz-appearance: none;
  appearance: none;
  transition: .3s;
}
@supports not (color: color-mix(in srgb,red,red)) {
  input {
    --_c: var(--c);
  }
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Phần kết luận

Chúng ta đã hoàn thành và không phải xử lý bất kỳ triển khai phức tạp nào liên quan đến trình duyệt! Chúng tôi đã xác định bộ chọn của phần tử thumb và sử dụng một vài thủ thuật CSS, chúng tôi đã tạo kiểu cho toàn bộ thanh trượt phạm vi với nó. Đừng quên rằng chúng tôi đã làm điều này chỉ bằng cách sử dụng phần <input>tử, vì vậy chúng tôi không phải lo lắng về bất kỳ vấn đề nào về khả năng truy cập vì chúng tôi đã giữ nguyên chức năng gốc. Thanh trượt hỗ trợ điều hướng bàn phím mà không gặp sự cố.

Dưới đây là nhiều ví dụ về các thanh trượt sử dụng kỹ thuật tương tự. Tôi sẽ để bạn phân tích mã của họ như một bài tập.

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--w:20px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;--w: 20px;--h:20px">
input {
  --c: orange; /* active color */
  --l: 8px; /* line thickness*/
  --h: 30px; /* thumb height */
  --w: 10px; /* thumb width */
  
  width: 400px;
  height: var(--h); /* needed for Firefox*/
  --_c: color-mix(in srgb, var(--c), #000 var(--p,0%));
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  overflow: hidden;
}
input:focus-visible,
input:hover{
  --p: 25%;
}

/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--h);
  width: var(--w);
  background: var(--_c);
  border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 100vw;
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -webkit-appearance: none;
  appearance: none;
  transition: .3s;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--h);
  width: var(--w);
  background: var(--_c);
  border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 100vw;
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -webkit-appearance: none;
  appearance: none;
  transition: .3s;
}
@supports not (color: color-mix(in srgb,red,red)) {
  input {
    --_c: var(--c);
  }
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}


<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--w:20px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;--w: 20px;--h:20px">
input {
  --c: orange; /* active color */
  --l: 8px; /* line thickness*/
  --s: 30px; /* thumb size */
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  --_c: color-mix(in srgb, var(--c), #000 var(--p,0%));
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: 
    linear-gradient(-90deg,#ababab 60%,#0000 0) 100%/8% calc(var(--l) - 1px) repeat-x;
  cursor: pointer;
  overflow: hidden;
}
input:focus-visible,
input:hover{
  --p: 25%;
}

/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--_c);
  border-image: linear-gradient(var(--_c) 0 0) 1/0 0 0 100vw/0 0 0 100vw;
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       1px 0,100% 0,100% 100%,1px 100%);
  -webkit-appearance: none;
  appearance: none;
  transition: .3s;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--_c);
  border-image: linear-gradient(var(--_c) 0 0) 1/0 0 0 100vw/0 0 0 100vw;
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       1px 0,100% 0,100% 100%,1px 100%);
  -webkit-appearance: none;
  appearance: none;
  transition: .3s;
}
@supports not (color: color-mix(in srgb,red,red)) {
  input {
    --_c: var(--c);
  }
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Nguồn bài viết: https://www.sitepoint.com

#html  #css 

Создание собственного ползунка диапазона CSS с обновлениями JavaScript

В этом уроке по CSS мы узнаем, как создать настраиваемый ползунок диапазона с помощью CSS. как использовать современные методы CSS для создания привлекательного, пользовательского слайдера диапазона, используя только собственный HTML- <input>элемент.

Ползунки диапазона ( <input type="range">) позволяют пользователям выбирать значение в заданном диапазоне, предоставляя альтернативные типы ввода, такие как <input type="number">.

Стили ползунка диапазона по умолчанию выглядят не очень хорошо. Изображение ниже дает представление о том, как диапазон ползунков, которые мы будем стилизовать, отображаются по умолчанию в Chrome, Firefox и Safari.

Ползунки диапазона по умолчанию в Chrome, Firefox и Safari

Но <input>элементы трудно стилизовать. Большинство онлайн-решений для их стилизации основаны на JavaScript и каком-то загроможденном коде. Что еще хуже, некоторые из этих методов также нарушают доступность элемента.

Итак, давайте посмотрим, как сделать что-то лучше, используя только CSS и не ставя под угрозу доступность. Демонстрация CodePen ниже показывает, что мы будем создавать.

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--g:12px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  --_c: color-mix(in srgb, var(--c), #000 var(--p,0%));
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  overflow: hidden;
}
input:focus-visible,
input:hover{
  --p: 25%;
}
input:active,
input:focus-visible{
  --_b: var(--s)
}
/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--_c);
  border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -webkit-appearance: none;
  appearance: none;
  transition: .3s;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  width: var(--s);
  background: none;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--_c);
  border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -moz-appearance: none;
  appearance: none;
  transition: .3s;
}
@supports not (color: color-mix(in srgb,red,red)) {
  input {
    --_c: var(--c);
  }
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Круто, да? Вы также найдете варианты этих стилей в конце статьи!

Структура входного элемента Range

Начнем с анализа структуры элемента ввода диапазона. Это нативный элемент, и каждый браузер имеет собственную реализацию таких элементов. В основном у нас есть две разные реализации.

Есть один для браузеров Webkit и Blink, таких как Chrome, Edge, Safari и Opera:

<input type="range" min="0" max="100" step="1" value="20">
  <div>
    <div pseudo="-webkit-slider-runnable-track" id="track">
      <div id="thumb">
    </div>
   </div>
  </div>
</input>

Обзор ввода Chrome

А это для Firefox:

<input type="range" min="0" max="100" step="1" value="20">
  <div></div>
  <div></div>
  <div></div>
</input>

Обзор ввода Firefox

Есть и третья реализация для IE, но, к счастью, этот браузер уже почти мертв!

Такое несоответствие между браузерами усложняет задачу, поскольку нам нужно обеспечить разные стили для каждой реализации. Я не буду углубляться в это, так как статья никогда не закончится, но я настоятельно рекомендую прочитать эту статью Аны Тюдор для более глубокого изучения.

Единственное, что вам нужно иметь в виду, это то, что, какой бы ни была реализация, у нас всегда есть «большой палец» как общий компонент.

Отображение элемента большого пальца

Я собираюсь стилизовать только этот элемент, что упростит настройку моего пользовательского ползунка диапазона. Давайте сразу перейдем к коду, чтобы увидеть магию в игре.

Настройка ввода

Первый шаг — сбросить и отключить все стили браузера по умолчанию, используя appearance: noneи некоторые другие общие свойства:

input {
  appearance :none;
  background: none;
  cursor: pointer;
}

В более сложном сценарии нам может потребоваться добавить дополнительный код, если к нашему элементу применяются другие стили по умолчанию. Просто нужно убедиться, что у нас есть «голый» элемент без каких-либо визуальных стилей.

Давайте также определим несколько переменных CSS, чтобы мы могли легко создавать различные варианты для ползунка диапазона:

input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/

  width: 400px; /* input width */
  height: var(--s); 
  appearance :none;
  background: none;
  cursor: pointer;
}

На этом этапе виден только большой палец со стилями по умолчанию, как показано в демо CodePen ниже.

<input type="range" min="0" max="100" step="1" value="20">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  overflow: hidden;
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Стилизация элемента большого пальца

Давайте стилизуем элемент большого пальца. Начнем с базовой настройки:

<thumb selector> {
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  appearance: none;
}

Код должен быть понятным. Пока ничего особенного, и мы получим результат, показанный ниже.

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--g:12px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  overflow: hidden;
}

/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  -webkit-appearance: none;
  appearance: none;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  width: var(--s);
  background: none;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  -moz-appearance: none;
  appearance: none;
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Обратите внимание на использование двух разных селекторов, как мы объясняли в первом разделе:

/* Chrome, Edge, Safari, Opera */
input[type="range" i]::-webkit-slider-thumb { }
/* Firefox */
input[type="range"]::-moz-range-thumb { }

Но как узнать, какой селектор использовать?

Я просто проверил код ввода с помощью инструментов разработчика браузера, чтобы увидеть селектор, который каждый браузер использует для стилизации большого пальца. В статье, которой я поделился ранее, показано, как манипулировать инструментами разработчика для получения такой информации.

Добавляем немного волшебства с помощью border-image

Теперь мы собираемся использовать волшебный прием CSS, чтобы завершить наш слайдер. Она предполагает использование border-image:

border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));

Я знаю, это выглядит пугающе, но давайте проанализируем эту линию, и вы увидите, что это не так сложно. Вышеприведенное является сокращением для следующего:

border-image-source: linear-gradient(90deg,var(--c) 50%,#ababab 0); 
border-image-slice: 1;
border-image-width: 0 100vw;
border-image-outset: 0 calc(100vw + var(--g));

Со страницы MDN читаем:

Свойство border-imageCSS рисует изображение вокруг заданного элемента. Он заменяет обычную границу элемента.

Наше изображение будет градиентом двух цветов — основного (определяемого --c) и серого цвета. Нам нужно, чтобы изображение рамки покрывало все пространство ввода по горизонтали, поэтому мы используем большое значение ширины слева и справа ( 100vw), а верх и низ оставляем равными ( 0).

Но border-image-widthограничен размером элемента. Чтобы преодолеть это, нам нужно также использовать большое значение для border-image-outsetувеличения пространства, доступного для изображения границы. Снова из MDN :

Свойство border-image-outsetCSS задает расстояние, на которое изображение границы элемента отстоит от его рамки.

Части граничного изображения, отображаемые за пределами рамки элемента с помощью , border-image-outsetне запускают полосы прокрутки переполнения и не фиксируют события мыши.

Когда вы впервые видите ползунок, кажется, что мы увеличиваем основной цвет слева, но на самом деле мы скользим по фиксированному градиенту, который переполняет наш элемент.

Следующая демонстрация дает обзор того, что происходит под капотом.

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--g:12px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  outline: 2px dashed #000;
}

/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  border-image-source: linear-gradient(90deg,var(--c) 50%,#ababab 0); 
  border-image-slice: 1;
  border-image-width: 0 200px;
  border-image-outset: 0 calc(200px + var(--g));
  -webkit-appearance: none;
  appearance: none;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  width: var(--s);
  background: none;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  -moz-appearance: none;
  appearance: none;
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Перетащите большой палец и сдвиньте его, чтобы увидеть, как все движется. Я использую небольшое значение для ширины и начала, чтобы мы могли легко понять трюк.

Также обратите внимание, что начало должно быть больше, чем ширина, чтобы был зазор. По этой причине он определяется равным ширине плюс значение зазора.

При добавлении overflow: hiddenк элементу ввода и использовании большого значения иллюзия становится идеальной, как показано ниже.

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--g:12px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  outline: 2px dashed #000;
  overflow: hidden;
}

/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  border-image-source: linear-gradient(90deg,var(--c) 50%,#ababab 0); 
  border-image-slice: 1;
  border-image-width: 0 100vw;
  border-image-outset: 0 calc(100vw + var(--g));
  -webkit-appearance: none;
  appearance: none;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  width: var(--s);
  background: none;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  -moz-appearance: none;
  appearance: none;
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Что насчет border-image-slice? Почему значение 1?

Это свойство немного сложное, но обязательное при использовании border-image. В нашем случае это значение не очень актуально, и небольшое положительное значение будет работать. У меня есть подробный ответ на переполнение стека , если вы хотите узнать об этом больше.

Последний шаг — уменьшить размер полосы, чтобы он соответствовал размеру, который мы определили с помощью переменной --l. Для этого мы будем использовать clip-path:

clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);

На изображении ниже представлен обзор различных точек для понимания формы многоугольника.

Обзор полигона clip-path

Вот и все! У нас есть пользовательский ползунок диапазона с несколькими строками кода, которым вы можете легко управлять, настраивая несколько переменных.

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--g:12px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  overflow: hidden;
}

/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  border-image: linear-gradient(90deg,var(--c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -webkit-appearance: none;
  appearance: none;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  width: var(--s);
  background: none;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  border-image: linear-gradient(90deg,var(--c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -moz-appearance: none;
  appearance: none;
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Добавление анимации

А как насчет тонкой анимации, когда мы взаимодействуем с ползунком? Для этого не нужно много кода, и это улучшит UX слайдера.

Во-первых, мы собираемся преобразовать большой палец из круга только с рамкой в ​​полный круг, когда мы нажмем на него. Для этого мы увеличиваем значение спреда box-shadow. Помните, что мы использовали box-shadowдля определения границы большого пальца:

box-shadow: 0 0 0 var(--l) inset var(--c);

Мы обновляем var(--l)с var(--s)помощью :activeселектора и файла :focus-visible. Последнее связано с навигацией с помощью клавиатуры и позволяет нам добиться одинакового эффекта независимо от того, используем ли мы мышь или клавиатуру.

Код выглядит следующим образом:

input[type="range" i]::-webkit-slider-thumb {
  box-shadow: 0 0 0 var(--l) inset var(--c);
  transition: .3s;
}

input[type="range" i]::-moz-range-thumb {
  box-shadow: 0 0 0 var(--l) inset var(--c);
  transition: .3s;
}

input:active::-webkit-slider-thumb,
input:focus-visible::-webkit-slider-thumb {
  box-shadow: 0 0 0 var(--s) inset var(--c);
}

input:active::-moz-range-thumb,
input:focus-visible::-moz-range-thumb {
  box-shadow: 0 0 0 var(--s) inset var(--c);
}

Это немного долго для box-shadowперехода, не так ли? Мы можем оптимизировать его с помощью переменной CSS:

input[type="range" i]::-webkit-slider-thumb {
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--c);
  transition: .3s;
}

input[type="range" i]::-moz-range-thumb {
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--c);
  transition: .3s;
}

input:active,
input:focus-visible {
  --_b:  var(--s);
}

Я выражаю значение спреда с помощью переменной и просто обновляю эту переменную в :activeи :focus-visible.

Я также собираюсь добавить немного анимации к цвету. Я сделаю его немного темнее на :hover. Для этого я не буду обновлять цвет, а смешаю его с черным с помощью новой color-mix()функции. Этот трюк позволяет нам использовать основной цвет, определенный с помощью, --cа не определять новый темный цвет для каждого ползунка вручную:

--_c: color-mix(in srgb, var(--c), #000 var(--p,0%));

Я определяю новую переменную, которая заменит --cв коде. Затем, регулируя процент черного цвета ( #000) с помощью переменной --p, я контролирую «темноту» цвета:

input:focus-visible,
input:hover{
  --p: 25%;
}

Эта функция поддерживается не во всех браузерах, поэтому настоятельно рекомендуется использовать запасной вариант:

@supports not (color: color-mix(in srgb,red,red)) {
  input {
    --_c: var(--c); /* if no support we keep the color as defined */
  }
}

Наш ползунок диапазона теперь идеален!

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--g:12px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  --_c: color-mix(in srgb, var(--c), #000 var(--p,0%));
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  overflow: hidden;
}
input:focus-visible,
input:hover{
  --p: 25%;
}
input:active,
input:focus-visible{
  --_b: var(--s)
}
/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--_c);
  border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -webkit-appearance: none;
  appearance: none;
  transition: .3s;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  width: var(--s);
  background: none;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--_c);
  border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -moz-appearance: none;
  appearance: none;
  transition: .3s;
}
@supports not (color: color-mix(in srgb,red,red)) {
  input {
    --_c: var(--c);
  }
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Заключение

Мы достигли конца, и нам не пришлось иметь дело со сложной реализацией, связанной с браузером! Мы идентифицировали селектор элемента thumb и, используя несколько приемов CSS, применили к нему стиль всего ползунка диапазона. Не будем забывать, что мы сделали это, используя только <input>элемент, поэтому нам не нужно беспокоиться о каких-либо проблемах доступности, поскольку мы сохранили нативную функциональность. Слайдер без проблем поддерживает навигацию с помощью клавиатуры.

Вот еще примеры слайдеров, использующих ту же технику. Я позволю вам проанализировать их код в качестве упражнения.

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--w:20px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;--w: 20px;--h:20px">
input {
  --c: orange; /* active color */
  --l: 8px; /* line thickness*/
  --h: 30px; /* thumb height */
  --w: 10px; /* thumb width */
  
  width: 400px;
  height: var(--h); /* needed for Firefox*/
  --_c: color-mix(in srgb, var(--c), #000 var(--p,0%));
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  overflow: hidden;
}
input:focus-visible,
input:hover{
  --p: 25%;
}

/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--h);
  width: var(--w);
  background: var(--_c);
  border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 100vw;
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -webkit-appearance: none;
  appearance: none;
  transition: .3s;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--h);
  width: var(--w);
  background: var(--_c);
  border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 100vw;
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -webkit-appearance: none;
  appearance: none;
  transition: .3s;
}
@supports not (color: color-mix(in srgb,red,red)) {
  input {
    --_c: var(--c);
  }
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}


<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--w:20px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;--w: 20px;--h:20px">
input {
  --c: orange; /* active color */
  --l: 8px; /* line thickness*/
  --s: 30px; /* thumb size */
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  --_c: color-mix(in srgb, var(--c), #000 var(--p,0%));
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: 
    linear-gradient(-90deg,#ababab 60%,#0000 0) 100%/8% calc(var(--l) - 1px) repeat-x;
  cursor: pointer;
  overflow: hidden;
}
input:focus-visible,
input:hover{
  --p: 25%;
}

/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--_c);
  border-image: linear-gradient(var(--_c) 0 0) 1/0 0 0 100vw/0 0 0 100vw;
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       1px 0,100% 0,100% 100%,1px 100%);
  -webkit-appearance: none;
  appearance: none;
  transition: .3s;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--_c);
  border-image: linear-gradient(var(--_c) 0 0) 1/0 0 0 100vw/0 0 0 100vw;
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       1px 0,100% 0,100% 100%,1px 100%);
  -webkit-appearance: none;
  appearance: none;
  transition: .3s;
}
@supports not (color: color-mix(in srgb,red,red)) {
  input {
    --_c: var(--c);
  }
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Источник статьи: https://www.sitepoint.com

#html  #css 

Como criar um controle deslizante de intervalo personalizado usandoCSS

Neste tutorial de CSS, aprenderemos como criar um controle deslizante de intervalo personalizado usando CSS. como usar técnicas CSS modernas para criar um controle deslizante atraente e personalizado com nada além do <input>elemento HTML nativo.

Os controles deslizantes de intervalo ( <input type="range">) permitem que os usuários escolham um valor dentro de um determinado intervalo, fornecendo tipos de entrada alternativos, como <input type="number">.

Os estilos padrão do controle deslizante de intervalo não parecem ótimos. A imagem abaixo dá uma ideia de como os controles deslizantes que estilizaremos são exibidos por padrão no Chrome, Firefox e Safari.

Controles deslizantes de intervalo padrão no Chrome, Firefox e Safari

Mas <input>os elementos são difíceis de estilizar. A maioria das soluções online para estilizá-los depende de JavaScript e algum código confuso. Pior ainda, algumas dessas técnicas também quebram a acessibilidade do elemento.

Então, vamos ver como fazer as coisas melhor, usando apenas CSS e sem comprometer a acessibilidade. A demonstração do CodePen abaixo mostra o que iremos construir.

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--g:12px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  --_c: color-mix(in srgb, var(--c), #000 var(--p,0%));
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  overflow: hidden;
}
input:focus-visible,
input:hover{
  --p: 25%;
}
input:active,
input:focus-visible{
  --_b: var(--s)
}
/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--_c);
  border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -webkit-appearance: none;
  appearance: none;
  transition: .3s;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  width: var(--s);
  background: none;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--_c);
  border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -moz-appearance: none;
  appearance: none;
  transition: .3s;
}
@supports not (color: color-mix(in srgb,red,red)) {
  input {
    --_c: var(--c);
  }
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Legal certo? Você também encontrará variações desses estilos no final do artigo!

A estrutura do elemento de entrada de intervalo

Vamos começar dissecando a estrutura do elemento de entrada do intervalo. É um elemento nativo e cada navegador tem sua própria implementação de tais elementos. Temos principalmente duas implementações diferentes.

Há um para navegadores Webkit e Blink, como Chrome, Edge, Safari e Opera:

<input type="range" min="0" max="100" step="1" value="20">
  <div>
    <div pseudo="-webkit-slider-runnable-track" id="track">
      <div id="thumb">
    </div>
   </div>
  </div>
</input>

Visão geral da entrada do Chrome

E este é o do Firefox:

<input type="range" min="0" max="100" step="1" value="20">
  <div></div>
  <div></div>
  <div></div>
</input>

Visão geral da entrada do Firefox

Há uma terceira implementação para o IE, mas felizmente esse navegador está quase morto e se foi agora!

Essa inconsistência entre os navegadores é o que dificulta a tarefa, pois precisamos fornecer estilos diferentes para cada implementação. Não vou me aprofundar mais nisso, pois o artigo nunca terminaria, mas recomendo fortemente a leitura deste artigo de Ana Tudor para uma exploração mais aprofundada.

A única coisa que você precisa ter em mente é que, qualquer que seja a implementação, sempre temos o “thumb” como componente comum.

Mostrando o elemento polegar

Vou apenas estilizar esse elemento, o que tornará meu controle deslizante de intervalo personalizado fácil de personalizar. Vamos pular direto para o código para ver a mágica em jogo.

Personalizando a entrada

A primeira etapa é redefinir e desabilitar todos os estilos padrão do navegador usando appearance: nonee algumas outras propriedades comuns:

input {
  appearance :none;
  background: none;
  cursor: pointer;
}

Em um cenário mais complicado, podemos precisar adicionar mais código caso outros estilos padrão sejam aplicados ao nosso elemento. Só precisamos ter certeza de que temos um elemento “nu” sem nenhum estilo visual.

Vamos também definir algumas variáveis ​​CSS para que possamos criar facilmente diferentes variações para o controle deslizante de intervalo:

input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/

  width: 400px; /* input width */
  height: var(--s); 
  appearance :none;
  background: none;
  cursor: pointer;
}

Nesta etapa, apenas a miniatura fica visível com seus estilos padrão, como mostra a demonstração do CodePen abaixo.

<input type="range" min="0" max="100" step="1" value="20">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  overflow: hidden;
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Estilizando o Elemento Thumb

Vamos estilizar o elemento polegar. Vamos começar com a configuração básica:

<thumb selector> {
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  appearance: none;
}

O código deve ser auto-explicativo. Nada sofisticado até agora, e obteremos o resultado mostrado abaixo.

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--g:12px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  overflow: hidden;
}

/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  -webkit-appearance: none;
  appearance: none;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  width: var(--s);
  background: none;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  -moz-appearance: none;
  appearance: none;
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Observe o uso de dois seletores diferentes, conforme explicamos na primeira seção:

/* Chrome, Edge, Safari, Opera */
input[type="range" i]::-webkit-slider-thumb { }
/* Firefox */
input[type="range"]::-moz-range-thumb { }

Mas como saber o seletor a ser usado?

Eu simplesmente inspecionei o código da entrada usando as ferramentas de desenvolvedor do navegador para ver o seletor que cada navegador está usando para estilizar o polegar. O artigo que compartilhei anteriormente mostra como manipular as ferramentas do desenvolvedor para obter essas informações.

Adicionando um pouco de mágica com imagem de borda

Agora vamos usar um truque mágico de CSS para completar nosso slider. Envolve o uso de border-image:

border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));

Eu sei que parece assustador, mas vamos dissecar essa linha e você verá que não é tão difícil. O acima é a abreviação para o seguinte:

border-image-source: linear-gradient(90deg,var(--c) 50%,#ababab 0); 
border-image-slice: 1;
border-image-width: 0 100vw;
border-image-outset: 0 calc(100vw + var(--g));

Na página do MDN , lemos:

A border-imagepropriedade CSS desenha uma imagem em torno de um determinado elemento. Ele substitui a borda regular do elemento.

Nossa imagem será um gradiente com duas cores — a principal (definida por --c) e uma cor cinza. Precisamos que a imagem da borda cubra todo o espaço da entrada horizontalmente, então usamos um valor grande para a largura esquerda e direita ( 100vw) enquanto mantemos a parte superior e inferior em ( 0).

Mas o border-image-widthé limitado ao tamanho do elemento. Para superar isso, precisamos também usar um valor grande para border-image-outsetaumentar o espaço disponível para a imagem da borda. De MDN novamente:

A border-image-outsetpropriedade CSS define a distância pela qual a imagem da borda de um elemento é definida de sua caixa de borda.

As partes da imagem da borda que são renderizadas fora da caixa de borda do elemento border-image-outsetnão acionam barras de rolagem de estouro e não capturam eventos do mouse.

Quando você vê o controle deslizante pela primeira vez, parece que estamos aumentando a cor principal à esquerda, mas na realidade estamos deslizando um gradiente fixo que está transbordando nosso elemento.

A demonstração a seguir fornece uma visão geral do que está acontecendo nos bastidores.

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--g:12px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  outline: 2px dashed #000;
}

/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  border-image-source: linear-gradient(90deg,var(--c) 50%,#ababab 0); 
  border-image-slice: 1;
  border-image-width: 0 200px;
  border-image-outset: 0 calc(200px + var(--g));
  -webkit-appearance: none;
  appearance: none;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  width: var(--s);
  background: none;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  -moz-appearance: none;
  appearance: none;
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Arraste o polegar e deslize-o para ver como as coisas estão se movendo. Estou usando um valor pequeno para a largura e o início para que possamos entender facilmente o truque.

Além disso, observe que o início precisa ser maior que a largura para ter a lacuna. Por isso é definido como sendo igual à largura mais o valor do vão.

Ao adicionar overflow: hiddenao elemento de entrada e usar um valor grande, a ilusão é perfeita, conforme mostrado abaixo.

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--g:12px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  outline: 2px dashed #000;
  overflow: hidden;
}

/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  border-image-source: linear-gradient(90deg,var(--c) 50%,#ababab 0); 
  border-image-slice: 1;
  border-image-width: 0 100vw;
  border-image-outset: 0 calc(100vw + var(--g));
  -webkit-appearance: none;
  appearance: none;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  width: var(--s);
  background: none;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  -moz-appearance: none;
  appearance: none;
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

E sobre o border-image-slice? Por que o valor de 1?

Essa propriedade é um pouco complicada, mas obrigatória ao usar border-image. No nosso caso, este valor não é muito relevante e um pequeno valor positivo fará o trabalho. Eu tenho uma resposta detalhada do Stack Overflow se você quiser aprender mais sobre isso.

O último passo é diminuir o tamanho da barra para corresponder ao tamanho que definimos pela variável --l. Para isso, vamos usar clip-path:

clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);

A imagem abaixo fornece uma visão geral dos diferentes pontos para entender a forma do polígono.

Visão geral do polígono de caminho de recorte

É isso! Temos um controle deslizante de intervalo personalizado com algumas linhas de código que você pode controlar facilmente ajustando algumas variáveis.

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--g:12px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  overflow: hidden;
}

/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  border-image: linear-gradient(90deg,var(--c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -webkit-appearance: none;
  appearance: none;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  width: var(--s);
  background: none;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  border-image: linear-gradient(90deg,var(--c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -moz-appearance: none;
  appearance: none;
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Adicionando alguma animação

Que tal uma animação sutil quando interagimos com o controle deslizante? Não precisa de muito código e vai melhorar a UX do slider.

Primeiro, vamos transformar o polegar de um círculo apenas de borda em um círculo completo quando clicarmos nele. Para isso, aumentamos o valor do spread do box-shadow. Lembre-se que usamos box-shadowpara definir a borda do polegar:

box-shadow: 0 0 0 var(--l) inset var(--c);

Atualizamos o var(--l)to var(--s)usando o :activeseletor e o :focus-visible. Este último está relacionado com a navegação pelo teclado e permite obter o mesmo efeito quer usemos o mouse ou o teclado.

O código é o seguinte:

input[type="range" i]::-webkit-slider-thumb {
  box-shadow: 0 0 0 var(--l) inset var(--c);
  transition: .3s;
}

input[type="range" i]::-moz-range-thumb {
  box-shadow: 0 0 0 var(--l) inset var(--c);
  transition: .3s;
}

input:active::-webkit-slider-thumb,
input:focus-visible::-webkit-slider-thumb {
  box-shadow: 0 0 0 var(--s) inset var(--c);
}

input:active::-moz-range-thumb,
input:focus-visible::-moz-range-thumb {
  box-shadow: 0 0 0 var(--s) inset var(--c);
}

É um pouco demorado para uma box-shadowtransição, certo? Podemos otimizá-lo usando uma variável CSS:

input[type="range" i]::-webkit-slider-thumb {
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--c);
  transition: .3s;
}

input[type="range" i]::-moz-range-thumb {
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--c);
  transition: .3s;
}

input:active,
input:focus-visible {
  --_b:  var(--s);
}

Estou expressando o valor do spread usando uma variável e simplesmente atualizando essa variável em :activee :focus-visible.

Também vou adicionar um pouco de animação à cor. Vou deixar um pouco mais escuro em :hover. Para isso, não vou atualizar a cor, mas sim misturá-la com o preto usando a nova color-mix()função. Esse truque nos permite usar a cor principal definida por, --cem vez de definir uma nova cor escura para cada controle deslizante manualmente:

--_c: color-mix(in srgb, var(--c), #000 var(--p,0%));

Estou definindo uma nova variável que substituirá o --cno código. Então, ajustando a porcentagem da cor preta ( #000) usando a variável --p, estou controlando a “escuridão” da cor:

input:focus-visible,
input:hover{
  --p: 25%;
}

Este recurso ainda não é suportado em todos os navegadores, então o uso de um fallback é altamente recomendado:

@supports not (color: color-mix(in srgb,red,red)) {
  input {
    --_c: var(--c); /* if no support we keep the color as defined */
  }
}

Nosso controle deslizante de alcance agora está perfeito!

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--g:12px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  --_c: color-mix(in srgb, var(--c), #000 var(--p,0%));
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  overflow: hidden;
}
input:focus-visible,
input:hover{
  --p: 25%;
}
input:active,
input:focus-visible{
  --_b: var(--s)
}
/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--_c);
  border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -webkit-appearance: none;
  appearance: none;
  transition: .3s;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  width: var(--s);
  background: none;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--_c);
  border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -moz-appearance: none;
  appearance: none;
  transition: .3s;
}
@supports not (color: color-mix(in srgb,red,red)) {
  input {
    --_c: var(--c);
  }
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Conclusão

Chegamos ao fim e não tivemos que lidar com nenhuma implementação complexa relacionada ao navegador! Identificamos o seletor do elemento thumb e, usando alguns truques de CSS, estilizamos todo o controle deslizante de alcance com ele. Não vamos esquecer que fizemos isso usando apenas o <input>elemento, então não precisamos nos preocupar com problemas de acessibilidade, pois mantivemos a funcionalidade nativa. O controle deslizante oferece suporte à navegação pelo teclado sem problemas.

Aqui estão mais exemplos de controles deslizantes usando a mesma técnica. Vou deixar você dissecar o código deles como um exercício.

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--w:20px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;--w: 20px;--h:20px">
input {
  --c: orange; /* active color */
  --l: 8px; /* line thickness*/
  --h: 30px; /* thumb height */
  --w: 10px; /* thumb width */
  
  width: 400px;
  height: var(--h); /* needed for Firefox*/
  --_c: color-mix(in srgb, var(--c), #000 var(--p,0%));
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  overflow: hidden;
}
input:focus-visible,
input:hover{
  --p: 25%;
}

/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--h);
  width: var(--w);
  background: var(--_c);
  border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 100vw;
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -webkit-appearance: none;
  appearance: none;
  transition: .3s;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--h);
  width: var(--w);
  background: var(--_c);
  border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 100vw;
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);
  -webkit-appearance: none;
  appearance: none;
  transition: .3s;
}
@supports not (color: color-mix(in srgb,red,red)) {
  input {
    --_c: var(--c);
  }
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}


<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--w:20px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;--w: 20px;--h:20px">
input {
  --c: orange; /* active color */
  --l: 8px; /* line thickness*/
  --s: 30px; /* thumb size */
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  --_c: color-mix(in srgb, var(--c), #000 var(--p,0%));
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: 
    linear-gradient(-90deg,#ababab 60%,#0000 0) 100%/8% calc(var(--l) - 1px) repeat-x;
  cursor: pointer;
  overflow: hidden;
}
input:focus-visible,
input:hover{
  --p: 25%;
}

/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--_c);
  border-image: linear-gradient(var(--_c) 0 0) 1/0 0 0 100vw/0 0 0 100vw;
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       1px 0,100% 0,100% 100%,1px 100%);
  -webkit-appearance: none;
  appearance: none;
  transition: .3s;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--_c);
  border-image: linear-gradient(var(--_c) 0 0) 1/0 0 0 100vw/0 0 0 100vw;
  clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       1px 0,100% 0,100% 100%,1px 100%);
  -webkit-appearance: none;
  appearance: none;
  transition: .3s;
}
@supports not (color: color-mix(in srgb,red,red)) {
  input {
    --_c: var(--c);
  }
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

Fonte do artigo: https://www.sitepoint.com

#html  #css 

Ruth  Nabimanya

Ruth Nabimanya

1624850863

Azure Data Catalog: A Quick Introduction to Data Handling Service Around

What is Azure Data Catalog?

Azure Data Catalog is a Data Catalog cloud service of Microsoft using a crowdsourced approach. It provides an inventory of data used for discovering and understanding the data sources. Microsoft Azure is a Software as a Service (SaaS) application.

“Build Confidence in Azure Data Catalog even having more than millions of accounts”

**Source: **Gartner, Inc

Azure Data Catalog enhances old investments’ performance, adding metadata and notation around the Azure environment’s data. It informs about the Data sources which we have discovered or which we already have. It expresses documentation and describes the schema of the data source. The data source location and a copy of the metadata are present in the Azure Data Catalog. The user can access it easily when needed, and the indexing of metadata helps discover data through a search.### What is Azure Data Catalog?

Azure Data Catalog is a Data Catalog cloud service of Microsoft using a crowdsourced approach. It provides an inventory of data used for discovering and understanding the data sources. Microsoft Azure is a Software as a Service (SaaS) application.

“Build Confidence in Azure Data Catalog even having more than millions of accounts”

**Source: **Gartner, Inc

Azure Data Catalog enhances old investments’ performance, adding metadata and notation around the Azure environment’s data. It informs about the Data sources which we have discovered or which we already have. It expresses documentation and describes the schema of the data source. The data source location and a copy of the metadata are present in the Azure Data Catalog. The user can access it easily when needed, and the indexing of metadata helps discover data through a search.

#big data engineering #blogs #azure data catalog: a quick introduction to data handling service around #azure data catalog #data handling service around #service

 iOS App Dev

iOS App Dev

1620466520

Your Data Architecture: Simple Best Practices for Your Data Strategy

If you accumulate data on which you base your decision-making as an organization, you should probably think about your data architecture and possible best practices.

If you accumulate data on which you base your decision-making as an organization, you most probably need to think about your data architecture and consider possible best practices. Gaining a competitive edge, remaining customer-centric to the greatest extent possible, and streamlining processes to get on-the-button outcomes can all be traced back to an organization’s capacity to build a future-ready data architecture.

In what follows, we offer a short overview of the overarching capabilities of data architecture. These include user-centricity, elasticity, robustness, and the capacity to ensure the seamless flow of data at all times. Added to these are automation enablement, plus security and data governance considerations. These points from our checklist for what we perceive to be an anticipatory analytics ecosystem.

#big data #data science #big data analytics #data analysis #data architecture #data transformation #data platform #data strategy #cloud data platform #data acquisition