最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to show the value of Range Slider on the thumb of the Slider? - Stack Overflow

programmeradmin1浏览0评论

This is an odd request; However, what would be the best method to display the value of an HTML5 range-slider on the thumb of the slider?! the thumb will be animated onLoad so it must follow the thumb; moreover, this will be displayed for iPad

EXAMPLE:

<input class="range-consideration" type="range" name="points" min="1" max="10" ng-model="rangeConsiderations">

This is an odd request; However, what would be the best method to display the value of an HTML5 range-slider on the thumb of the slider?! the thumb will be animated onLoad so it must follow the thumb; moreover, this will be displayed for iPad

EXAMPLE:

<input class="range-consideration" type="range" name="points" min="1" max="10" ng-model="rangeConsiderations">
Share Improve this question edited Nov 20, 2017 at 17:44 Erol Aliyev 652 silver badges8 bronze badges asked May 26, 2014 at 8:06 John AbrahamJohn Abraham 18.8k36 gold badges132 silver badges240 bronze badges 0
Add a comment  | 

6 Answers 6

Reset to default 4

I too have had a lot of trouble figuring out a way to display the value of a range slider on its thumb. When working this out, I thought of three methods:

1. Combining multiple pseudo-elements

(Spoiler: Doesn't work - Read BoltClock's comment on the accepted answer of this thread)

  • CSS:
  • body {
      --thumbNumber: "5"; // updates on slider input via JavaScript function
    }
    
    #slider {
      -webkit-appearance: none;
      outline: none;
      width: 400px;
      height: 3px;
      background-color: #555;
    }
    
    #slider::-webkit-slider-thumb {
      -webkit-appearance: none;
      width: 30px;
      height: 30px;
      cursor: pointer;
      background: #5a5;
    }
    
    #slider::-webkit-slider-thumb::before { // doesn't work (refer to above link)
      content: var(--thumbNumber);
    }
    

  • HTML:
  • <body>
      <input type="range" id="slider" value="5" min="1" max="10" />
    </body>
    

  • JavaScript:
  • window.onload = function () {
        var slider = document.getElementById("slider");
        slider.addEventListener("input", function () {
            document.body.style.setProperty("--thumbNumber", "'" + this.value + "'");
        });
        // whenever this element receives input, change the value of --thumbNumber to this element's value
    }
    

    I thought I was pretty clever by using CSS variables to avoid the problem of not being able to directly change the properties of a pseudo-element in JavaScript. I learned, however, that this approach cannot work because you cannot use more than one pseudo-element selector in the same selection. (Refer to above link).

    2. Dynamically changing the thumb's content property with JavaScript

    This method is very similar to the previous one. The only difference is in the CSS. (Spoiler: This method also didn't work)

  • CSS:
  • #slider::-webkit-slider-thumb {
      content: var(--thumbNumber);
    }
    

    The JavaScript is the exact same as before. The idea is that the event listener attached to the slider element listens for input events, and reacts by changing the value of the CSS variable --thumbNumber. This causes the content property of the thumb to update and display the change. This doesn't work, however, because CSS doesn't seem to let you change the content property of the thumb.

    3. Using CSS Variables and... images...

    This is basically as bad as it gets when it comes to dirty solutions. This is completely unscalable, but it's only a little bit godawful when working with less than 10 numbers on an input range.

    For this example, I made 10 png files in photoshop in about 10 minutes. Each file is a 30px by 30px image of a number on a transparent background. Their filenames are 1.png, 2.png, 3.png, and so on until 10.png. Each file is stored in a folder called png. This folder is located in the same folder as the html document.

  • CSS:
  • body {
      --sliderImage: url("png/5.png");
    }
    
    #slider::-webkit-slider-thumb {
      background-image: var(--sliderImage);
    }
    

  • JavaScript:
  • window.onload = function () {
        var slider = document.getElementById("slider");
        slider.addEventListener("input", function () {
            document.body.style.setProperty("--sliderImage", "url('png/" + this.value + ".png')");
        });
    }
    

    This example is obviously terrible in so many ways, but it's all I've been able to try that has worked.

    Basically, this makes it so that when the slider element receives input, the value of the CSS variable --sliderImage is changed to, for example, url('png/6.png') when the slider thumb is dragged onto the value 6. This causes the background-image property of the thumb to update to a picture that correctly represents the value of the slider.

    I am still searching for and trying to come up with an actual, reasonable answer to this problem. It puzzles me how such a seemingly simple task can, in reality, be very layered and difficult. I'll edit my answer as soon as I figure it out.

    You cannot display value in the thumb but you can attach a bubble to the thumb which will contain and display the value as you slide. Refer to this detailed article Show slider value.

    Here's a demo.

    1. You create a div that will follow the handle.
    2. Then, every time the handle is moved/changed (onslide/onchange), put the value of the handler to the div and also modify the current position of the div the same with the handle so that it will follow the handle.

    or maybe, if possible, on onchange method of the slider get the id of the handle and just put

      $('#handle').text($(this).val());
    

    I'm just giving you ideas here. I'm sure there will be better answers.

    Webkit allows you to target the thumb with css :

    .range-consideration::-webkit-slider-thumb::before {
        content: "test";
    }
    

    That will print test on the thumb. However, using attr(value) doesn't seem to work, so I don't know how to show the value. Maybe you can find a way by playing with css variables and changing it with javascript.

    The equivalent for other browsers are ::-moz-range-thumb and ::-ms-thumb.


    EDIT : This is really (really !) a dirty way, but it works and it's doable as long as you have a relatively limited range of values.

    HTML :

    <input class="range-consideration" type="range" min="1" max="10" value="3" onchange="this.setAttribute('value', this.value);" />
    

    CSS :

    .range-consideration[value="1"]::-webkit-slider-thumb::before { content: "1"; color: black; }
    .range-consideration[value="2"]::-webkit-slider-thumb::before { content: "2"; color: black; }
    .range-consideration[value="3"]::-webkit-slider-thumb::before { content: "3"; color: black; }
    .range-consideration[value="4"]::-webkit-slider-thumb::before { content: "4"; color: black; }
    .range-consideration[value="5"]::-webkit-slider-thumb::before { content: "5"; color: black; }
    .range-consideration[value="6"]::-webkit-slider-thumb::before { content: "6"; color: black; }
    .range-consideration[value="7"]::-webkit-slider-thumb::before { content: "7"; color: black; }
    .range-consideration[value="8"]::-webkit-slider-thumb::before { content: "8"; color: black; }
    .range-consideration[value="9"]::-webkit-slider-thumb::before { content: "9"; color: black; }
    .range-consideration[value="10"]::-webkit-slider-thumb::before { content: "10"; color: black; }
    

    This "workaround" has lots and lots of lipstick on it... but it is possible with a automated derivation of Sebastien C. answer http://codepen.io/anon/pen/xbQoLj

    $(document).ready(function() {
        var $daFoo = $('#foo');
    
        var rule = "<style>";
        // get mix & max of the slider
        for(var i= parseInt($daFoo.attr("min")); i<= parseInt($daFoo.attr("max"));  i++)
            // for each value possible in this SINGLE!! slider - push a rule
            rule += 'input[type=range][data-value="' + i + '"]::-webkit-slider-thumb::after { content: "' + i + '"; }';    
        $('head').append(rule + "</style>");
    
      $daFoo.on('input', function() { $daFoo.attr('data-value', $daFoo.val()) });
    });
    

    I found one method which works good. I used react. For this need styled-components library https://styled-components.com/ (or any other way to get pseudo-element in jsx file). Also we will use svg image for background-image in pseudo-element and show there amount above where is slider-thumb.

    Here you can prepare your svg image https://yoksel.github.io/url-encoder/ or you can use my <svg xmlns='http://www.w3.org/2000/svg' height='40' width='20'><circle cx='6' cy='20' r='6' fill='black'/><text x='2' y='12' fill='black'>2</text></svg> Put it in https://yoksel.github.io/url-encoder/ and change that you need.

    for getting input value use useState and send it as props in styled.input

    import { useState } from "react";
    import styled from "styled-components";
    
    const RangeInput = styled.input`
      -webkit-appearance: none;
      height: 2px;
      background: black;
      width: 260px;
    
      &::-webkit-slider-thumb {
        -webkit-appearance: none;
        height: 40px;
        width: 20px;
        cursor: pointer;
        background-image: ${(props) =>
          `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='40' width='20'%3E%3Ccircle cx='6' cy='20' r='6' fill='black'/%3E%3Ctext x='${
            props.amount >= 10 ? -1 : 2
          }' y='12' fill='black'%3E${props.amount}%3C/text%3E%3C/svg%3E");`};
      }
    `;
    
    export const CalculateRangeInput = () => {
      const [amount, setAmount] = useState("2");
      return (
        <RangeInput
          onChange={(e) => setAmount(e.target.value)}
          defaultValue={2}
          amount={Number(amount)}
          type="range"
        />
      );
    };
    

    result which i got through this way:

    发布评论

    评论列表(0)

    1. 暂无评论