Recently, I encountered an iOS Bug when using the RC-Slider component to implement the slider function, that is, when sliding, it often bounced back to the position before sliding, see the link for related issue. So I thought about using the slider effect range Input.
Attributes: Have input element shared attributes, plus Max, min, step, list attributes.
range input
The composition of the:
1, Range Input’s composition differences in various browsers:
To achieve a consistent look across browsers, we first need to understand the differences in performance across browsers.
Let’s take a look at the internal structure of range Input in different browsers:
Chrome:
First check Show user agent shadow DOM in Settings.
Open Element and you’ll find :: :-webkit-slider-runnable-track Matches track ::-webkit-slider-thumb matches thumb
Firefox:
Enter about:config in the search bar to turn on showAllAnonymousContent
When we open the Element panel, we see that the Range Input Element contains three
::-moz-range-track matches the first div ::-moz-range-progress matches the second div ::-moz-range-thumb matches the third div
Edge:
Edge provides the following pseudo-elements to control the style of the slider:
::-ms-fill-lower: filled area ::-ms-fill-upper: unfilled area ::-ms-ticks-before: :-ms-ticks-after: Back and bottom scales ::-ms-thumb: small circles that slide to change the value of the slider ::-ms-track: Groove of the slider :: MS-tooltip: Text displayed when dragging. Note that this element can only be hidden with styles such as display: None.
The structure of Edge is quite complex, we can only access the elements with -ms-* ID, and there are many elements that cannot be accessed.
Second,range input
Components of the browser performance differences
Next, let’s look at how range Input components differ across browsers:
input range
Box-sizing is a content-box in Chrome Firefox Edge, and box-sizing is a content-box in chrome Firefox Edge. Chrome: border-box, other content-box.
In Chrome, Safari, and Edge we need to declare the following CSS styles to cancel the system default styles before we can set the custom styles we want. (For some reason, the sound track is already set by default.)
input[type='range'] { -webkit-appearance: none; &::-webkit-slider-thumb { -webkit-appearance: none; }}Copy the code
track
In Chrome, the track width we set is ignored, so the track width must depend on the range Input width. Using Tranform: scaleX seems to be the only way to make track wider or narrower than its parent slider. But doing so also scales thumb horizontally in Chrome and Edge, since thumb is a child of Track. This is not the case in Firefox, however, because its size is not affected by Track, since track and Thumb are sibling nodes.
thumb
The Thumb slide area for Edge and Firefox is the content area for range Input.
Chrome’s slide area is the content area of Track:
Populated area elements (Progress) :
This element is matched by the :: -moz-range-progress pseudo-element used in Firefox and the ::-ms-fill-lower pseudo-element used in Edge.
As we already know from the input Range structure above, this element is a sibling of the track element in Firefox with a size relative to the Range Input, and a child of the track element in Edge with a size relative to the track element. But there is no pseudo-element in Chrome to match this element. The width of the filling area in edge is the distance between the middle point of thumb and the left boundary of the content of track:
The width of the fill area in Firefox is the distance from the left and right edges of thumb to the left and right edges of the input field to the left edge of the track content, which is inconsistent with other browsers. However, if thumb has a width of 0, the filled area will behave like any other browser. If there must be a thumb size, then you can draw the fill area yourself based on the current value.
To achieve a slider that looks the same in different browsers, you need to set a uniform style under the pseudo-class of each browser. Since the following style Settings are not valid,
input::-webkit-slider-runnable-track,
input::-moz-range-track,
input::-ms-track { /* common styles */ }
Copy the code
So it is recommended to use mixins to write generic styles.
@mixin track() { /* common styles */ }
input {
&: :-webkit-slider-runnable-track { @include track }
&::-moz-range-track { @include track }
&::-ms-track { @include track }
}
Copy the code
application
Common Slider implementation
Now that we’ve analyzed the range Input element, let’s see how we can use it to implement the common slider:
Since chrome does not provide pseudo elements for the fill area, how do you customize the color of the fill area?
How to display multiple colors in a single Track div element is a good example of using linear gradients or multi-backgrounds.
Background-size is used to control the position of the fill area, and this position can be controlled by CSS variables based on the current value of the input, or directly set background-size in the style.
When calculating the fill range, you need to consider the performance of chrome’s fill range mentioned above, as follows
@mixin track {
background: linear-gradient(100deg.#5dd8fb 2%.#5dc1fb 100%)
0/ var(--sx) 100% no-repeat, $track-color;
}
$thumb-w: the width of the thumb
[type='range'] {
--range: calc(var(--max) - var(--min));
--ratio: calc((var(--val) - var(--min))/var(--range));
--sx: calc(.5*#{$thumb-w} + var(--ratio)*(100%- # {$thumb-w}));
}
Copy the code
One thing to note here is that due to chrome’s and Edge’s fill areas, the track height should be smaller than the Thumb height, otherwise the effect may not be as good as you expect.
The online demo
Slider implementation with step property
To achieve this effect, you need to maintain step dot yourself.
HTML structure:
const dots = [-20.0.20.40.60.80];
<div className="input-box">
{dots.map((dot, index) => {
return <div className={`dot dot-The ${index + 1} `} / >;
})}
<input
type="range"
onChange={(event)= > {
setValue(+event.target.value);
}}
min="-20"
max="80"
step="20"
style={{
"--min": -20,
"--max": 80,
"--step": 20,
"--val": value
}}
value={value}
/>
</div>
Copy the code
Step dot style controls:
- Determine the location. The horizontal center point of the step dot is always aligned with the right boundary of the filled region, which was calculated in the previous example.
.input-box {
position: relative;
width: 300px; // The width is the same as input
font-size: 0; // Remove the effect of input line box struts on height
}
.dot {
position: absolute;
top: 50%;
left: 0;
transform: translate(-50%, -50%);
// This uses sass's for loop and the position of the current input valuez value, which you can also calculate in style.
@for $i from 1 through 6 {
&.dot-# {$i} {
--val1: calc((#{$i} - 1) *var(--step) - var(--step));
--ratio1: calc((var(--val1) - var(--min))/ var(--range));
left: calc(.5* # {$thumb-w} + var(--ratio1)*(100%- # {$thumb-w})); }}&.dot-1 {
transform: translate(0, -50%);
left: 0; }}Copy the code
- Increase the cascade level of thumb elements so that they are above dot.
@mixin thumb() {
transform: translateZ(0);
}
Copy the code
- Highlighting the dot
.dot.active {
border: 2px solid #00b9fa;
}
{dots.map((dot, index) => {
const active = value> =dot ? "active":" ";return <div className= {`dot dot-The ${index + 1} ${active} `} / >; })}Copy the code
The online demo
A range control with hash marks
The input element of type=range provides the list attribute to implement the hashed range control, whose value is the ID value of the Details element. Unfortunately, this implementation with attributes is far from ideal, nor is it possible to customize its style. Therefore, to realize a range control with hash tags across browsers, you need to use repeating-Linear-gradient to realize hash tags and label elements to realize tag values.
The demo address
Tooltip display:
Edge is the only browser that provides tooltips via: :-ms-tooltip, but it doesn’t display them
In the DOM, you can’t really style things. So you need to hide it and use the output element to show it.
A site or application can inject the results of a calculation or user action into one of these container elements
The online demo
More practices:
- Type =range input type=range input
The two type=range input boxes are stacked on top of each other, and then only the drag button in the middle of the selection box is superplaced. The drag background bar in the back is hidden directly, so that visually there is a background bar and 2 drag buttons.
- Use type=ragne input + mask to achieve star rating
Please check for details.The article
Implementation diagram:
Compatibility:
Reference:
Developer.mozilla.org/zh-CN/docs/…
Css-tricks.com/sliding-nig…
Juejin. Cn/post / 691945…
www.zhangxinxu.com/wordpress/2…