Public id: Front-end detective

How to customize the style of the native Input range slider has always been a question in my mind. In general, it is easy to beautify to this extent

Why is it easy? Because these are all pseudo-elements that can be modified

::-webkit-slider-container {/* You can modify some of the container styles */} ::-webkit-slider-runnable-track {/* You can modify some of the track styles */} ::-webkit-slider-thumb {/* You can modify several styles of the slider */}Copy the code

However, there is no style that has been slid, if you want to define the following style, simple CSS may not be able to implement

Note: Firefox has a separate pseudo class that can be modified; this article discusses the Chrome implementation

First, my implementation ideas

Since there are no special pseudo-elements that can change the color of the part that has been slid, and only the slider is movable, is it possible to work on the slider?

Let’s say I have a rectangle to the left of the slider that follows the slider,

When the rectangle is long enough to completely cover the track on the left, is it visible that the left part has slipped over? The image is shown below (left semi-transparent shows the outside of the slider)

Tried the idea of pseudo-elements, like this

::-webkit-slider-thumb::after{/* I want to draw a long enough rectangle */}Copy the code

Unfortunately, you can’t reproduce pseudo-elements in pseudo-elements.

So, how do you draw a rectangle outside of an element?

Draw a graph outside the element using border-image

What are some ways to draw outside of an element? After thinking about it, there are box-shadow and outline, but it seems not suitable for this situation. What we need to draw is a controllable rectangle, and neither of these two methods can control the shape well. Is there any other way?

Also is there! I just read an article by Zhang Xinxu two days ago: the undervalued border-image attribute, one of which is to build images outside of elements and not occupy any space. Let’s try and draw a rectangle with a width of 99vw (just enough to cover the slider) as follows

::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background-color: #f44336;
    border: 1px solid transparent;
    margin-top: -8px;
    border-image: linear-gradient(#f44336.#f44336) 0 fill / 8 20 8 0 / 0 0 0 99vw; /* Draws a rectangle outside the element */
}
Copy the code

Results the following

A few points to note:

  1. Border-image must be specified for this parameter to take effectborder, and this is set toborder: 1px solid transparent;
  2. Rectangles are drawn with a linear gradientlinear-gradient(#f44336,#f44336)
  3. Border – the image8 20 8 0saidborder-image-width, the distance from top, right, bottom and left. Since the size of the slider itself is 20 * 20, the height can be determined to be 4 (20-8-8), and the position is the leftmost of the slider itself (20 from the right).
  4. Border – the image0 0 0 99vwsaidborder-image-outsetExpand the size, in this case, to the left99vwThe distance from the

The next step is to hide the outside with Overflow: Hidden

::-webkit-slider-container {/* Other styles */ overflow: hidden; }Copy the code

The full code can be accessed: Input range (codepen.io)

The complete code is attached below (Codepen seems to be a bit unstable lately)

[type="range"] {
    -webkit-appearance: none;
    appearance: none;
    margin: 0;
    outline: 0;
    background-color: transparent;
    width: 500px;
}
[type="range"]::-webkit-slider-runnable-track {
    height: 4px;
    background: #eee;
}
[type="range" i]::-webkit-slider-container {
    height: 20px;
    overflow: hidden;
}
[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background-color: #f44336;
    border: 1px solid transparent;
    margin-top: -8px;
    border-image: linear-gradient(#f44336.#f44336) 0 fill / 8 20 8 0 / 0px 0px 0 2000px;
}
Copy the code

Third, there are some limitations

The above implementation cost is actually very low, compared to the normal implementation basis, only 1 more line for drawing the rectangle outside the element.

border-image: linear-gradient(#f44336.#f44336) 0 fill / 8 20 8 0 / 0px 0px 0 2000px;
Copy the code

However, since the edges of the slider are “one-size-fits-all” by clipping out the extra parts beyond their hiding, this approach is not possible if the slider is required to have rounded corners

If you have any good ideas, please leave a comment

Four, a brief summary

As for the attribute “border-image-outset”, I have seen it on MDN before, but I think it is not very useful but I have not met the suitable application scenarios. Here is a brief summary:

  1. The slider has three pseudo-elements for customizing containers, tracks, and sliders
  2. Pseudo-elements can no longer be nested in pseudo-elements
  3. Outside the element, there are three methods to draw box-shadow, outline and border-image
  4. Border-image can use images in any format, including CSS gradients
  5. Rounded corners cannot be achieved in this scheme

Of course, these ideas are only “partial”, like Firefox fully support custom style, unfortunately desktop is still Chrome, can only slowly look forward to Chrome behind the update. Finally, if you think it’s good and helpful, please like, bookmark and retweet ❤❤❤