The purpose of this tutorial is to create a slider with a ranged input in Qualtrics. This guide is primarily meant to be copy and pasted from.

This slider works by using a text entry question, hiding the text box so that only the slider is shown, and then recording the answer as a text entry on submission.

One Slider on the page

Example of one slider in Action

Example of one slider in a survey.




Example of one slider in Qualtrics
Example of one slider in Qualtrics (note: this is different than how it will appear in your survey).

1. Question HTML:

<br>
<br>
<center><input class="slider" list="tickmarks" max="97" min="3" id="rangeInput" onchange="" step="1" type="range" value="" />
<div class="sliderticks">
<p>0%</p>
<p>20%</p>
<p>40%</p>
<p>60%</p>
<p>80%</p>
<p>100%</p>
</div>
</center>
<br />
<br />  
<center><span id="currentValue">(The continue arrow will enable after you move the slider to your decision)</span></center>

2. JS Input:

Qualtrics.SurveyEngine.addOnload(function()
{
    jQuery(".InputText").hide() // hide text input box
    
});


Qualtrics.SurveyEngine.addOnReady(function()
{
    that = this;
     function hideEl() {
        that.disableNextButton()
    }   
    hideEl.defer(); // block next button until slider is moved
    var current = jQuery("#currentValue"); // current value of slider
    slider_range = 6 // width of slider-thumb
    currentQID = this.questionId;

  // Function to look for track changes in slider
  // code inspired by https://www.qualtrics.com/community/discussion/5963/dynamic-accessing-slider-value
  
    rangeInput = document.getElementById('rangeInput') // slider
    function SliderChange() {
        // enable next button
        function enableEl() {
          that.enableNextButton()
        }   
        enableEl.defer();
    
        // find lower and upper values
        input = this.value
        lower_val = input - slider_range/2
        upper_val = (parseFloat(input) + slider_range/2);

        // show current value in question
        current.html("Your answer: "+ lower_val + "% - " + upper_val + "%.<br><br>");
    }
  rangeInput.addEventListener('input', SliderChange);
});

Qualtrics.SurveyEngine.addOnPageSubmit(function(type)
{
    // record center of slider thumb on page submission
    jQuery("#" + currentQID + " .InputText").val(input);
});

3. Look and Feel Input (CSS)

This is where the slider(s) are globally styles and provides consistency for the slider across different web-browsers.

.slider {
    -webkit-appearance: none;
    appearance: none;
    width: 90%;
    height: 2em;
    background: #D3D3D3;
    outline: none;
    opacity: 0.7;
    -webkit-transition: .2s;
    transition: opacity .2s;
  }
  
  .sliderticks {
    display: flex;
    width: 93%;
    justify-content: space-between;
    padding: 0 10px;
  }
  
  .sliderticks p {
    position: relative;
    display: flex;
    justify-content: center;
    text-align: center;
    width: 1px;
    background: #D3D3D3;
    height: 10px;
    line-height: 40px;
    margin: 0 0 20px 0;
  }
  
  .slider:hover {
    opacity: 1;
  }
  
  :root {
    --thumb-width: 5.4%;
  }


  .slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: var(--thumb-width);
    height: 2em;
    background: #000000;
    cursor: pointer;
  }
  
  .slider::-moz-range-thumb {
    width: var(--thumb-width);
    height: 2em;
    background: #000000;
    cursor: pointer;
  }
  
  .slider::-ms-thumb {
    width: var(--thumb-width);
    height: 2em;
    background: #000000;
    cursor: pointer;
  }

Marking a spot on a slider

This is a useful trick to use if you want participants to see something like a previous choice or a reference point. This slider is styled slightly different than other sliders in this guide in that 1) there are only two points on the slider axis marked, and 2) that the range is 1.

Example of a slider with a marked redspot in action

Example of a slider with a marked redspot in action.




Example of one slider in Qualtrics
Example of a slider with a marked redspot in Qualtrics (note: this is different than how it will appear in your survey).

1. Question HTML:

<br>
<br>
<center><input class="slider" list="tickmarks" max="100" min="0" id="rangeInput" onchange="" step="1" type="range" value="" />
<div class="sliderticks">
<p>0%<span class="sl">Extremely Unlikely</span></p>
<p>100%<span class="sl" id="sl2">Extremely Likely</span></p>
</div>
</center>
<br />
<br />  
<center><span id="currentValue">(The continue arrow will enable after you move the slider to your decision)</span></center>

2. JS Input:

Qualtrics.SurveyEngine.addOnload(function()
{

    gender = "male"
    avg = 45;
    
    jQuery(".InputText").hide() // hide text input box
    
    console.log("the average" + gender + "guessed" + avg)
    style = document.createElement('style'); // create red spot
    style.innerHTML =  ".slider {background: -webkit-linear-gradient(left,  \
      #D3D3D3 0%, #D3D3D3 " +  (avg-spread) + "%, \
      #ff2828 " +  (avg-spread) + "%, #ff2828 " + (avg+spread) + "%, \
      #D3D3D3 " + (avg+spread) + "%, #D3D3D3 100%)};"

    bub = document.createElement('output'); // create Average Answer text
    bub.addClassName("bubble")
    bub.innerHTML = "Average<br>Answer".fontcolor("red");
    bub.style.left = avg*.9 +"%";
    
    x = jQuery("#"+this.questionId+" .QuestionText")
    x.html(bub.outerHTML + x.html() +  style.outerHTML) // add to HTML


  
});


Qualtrics.SurveyEngine.addOnReady(function()
{
    that = this;
    function hideEl() {
        that.disableNextButton()
    }   
    hideEl.defer(); // block next button until slider is moved
    var current = jQuery("#currentValue"); // current value of slider
    slider_range = 1 // width of slider-thumb
    currentQID = this.questionId;
    rangeInput = document.getElementById('rangeInput') // slider

    // Show the value of the text under the slider
    second_line = "The average " + gender + " guessed " + 
    avg.toString().concat("%").fontcolor("red").bold() + "<br>"

    
    function SliderChange() {
        // enable next button
        function enableEl() {
            that.enableNextButton()
        }   
        enableEl.defer();
    
        // find lower and upper values
        input = this.value
        lower_val = input - slider_range/2
        upper_val = (parseFloat(input) + slider_range/2);

        // show current value in question
        let msg = "The chance of getting " + n_corr + " or more questions right:<br>" + 
           second_line +
           "You have guessed " + input.toString().concat("%").bold() + "<br><br>"
    
        current.html(msg);
    }
  rangeInput.addEventListener('input', SliderChange);
});

Qualtrics.SurveyEngine.addOnPageSubmit(function(type)
{
  // record center of slider thumb on page submission
  jQuery("#" + currentQID + " .InputText").val(input);
});

3. Look and Feel Input (CSS)

  .sl {
    display: inline-flex;
    justify-content: center;
    text-align: center;
    width: 5px;
    margin-top: 35px;
    height: 15px;
    line-height: 20px;
  }

#sl2{
    transform: translateX(-50px);
}

.bubble {
  padding: 4px 12px;
  margin-top: 10px;
  font-size: 12px;
  line-height: 15px;
  text-align: center;
  position: absolute;
}
.bubble::after {
  width: 2px;
  height: -2px;
  top: -0%;
}


.slider {
    -webkit-appearance: none;
    appearance: none;
    background: #D3D3D3; /* needs to get override to show red spot */
    width: 90%;
    height: 2em;
    outline: none;
    opacity: 0.7;
    -webkit-transition: .2s;
    transition: opacity .2s;
  }
  
  .sliderticks {
    display: flex;
    width: 93%;
    justify-content: space-between;
    padding: 0 10px;
  }
  
  .sliderticks p {
    position: relative;
    display: flex;
    justify-content: center;
    text-align: center;
    width: 1px;
    background: #D3D3D3;
    height: 10px;
    line-height: 40px;
    margin: 0 0 20px 0;
  }
  
  .slider:hover {
    opacity: 1;
  }
  
  :root {
    --thumb-width: 0.9%;
  }


  .slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: var(--thumb-width);
    height: 2em;
    background: #000000;
    cursor: pointer;
  }
  
  .slider::-moz-range-thumb {
    width: var(--thumb-width);
    height: 2em;
    background: #000000;
    cursor: pointer;
  }
  
  .slider::-ms-thumb {
    width: var(--thumb-width);
    height: 2em;
    background: #000000;
    cursor: pointer;
  }

Marking Two Spots on a Slider

This is just a slight variation of marking one spot on a slider.

Example of a slider with *two* marked redspots in action

Example of a slider with two marked redspots in action.



JS Input:

Qualtrics.SurveyEngine.addOnload(function()
{

    gender = "both"
    let spread = .9/2

    male_avg = 45;
    female_avg = 65;

    jQuery(".InputText").hide() // hide text input box
    

    style = document.createElement('style'); // create red spot
    bub1 = document.createElement('output'); // create Average Answer text
    bub2 = document.createElement('output'); // create Average Answer text
    
    // find the higher and lower dots to set up the gradient
    if(male_avg > female_avg){
      console.log("the male avg is larger")
      first_avg = female_avg
      second_avg = male_avg
    } else {
      first_avg = male_avg
      second_avg = female_avg
    }

    // red dots
    style.innerHTML =  ".slider {background: -webkit-linear-gradient(left,  \
      #D3D3D3 0%, #D3D3D3 " +  (first_avg-spread) + "%, \
      #ff2828 " +  (first_avg-spread) + "%, #ff2828 " + (first_avg+spread) + "%, \
      #D3D3D3 " + (first_avg+spread) + "%, #D3D3D3 " + (second_avg-spread) + "%, \
      #ff2828 " +  (second_avg-spread) + "%, #ff2828 " + (second_avg+spread) + "%, \
      #D3D3D3 " + (second_avg+spread) + "%, #D3D3D3 100%)};"

    // male text
    bub1.addClassName("bubble")
    bub1.innerHTML = "Avg<br>Male".fontcolor("red");
    bub1.style.left = male_avg*.9 +"%";

    // female text
    bub2.addClassName("bubble")
    bub2.innerHTML = "Avg<br>Female".fontcolor("red");
    bub2.style.left = female_avg*.9 +"%";
    
    x = jQuery("#"+this.questionId+" .QuestionText") // change the html
    x.html(bub1.outerHTML + bub2.outerHTML + x.html() +  style.outerHTML) 

});


Qualtrics.SurveyEngine.addOnReady(function()
{
    that = this;
     function hideEl() {
        that.disableNextButton()
    }   
    hideEl.defer(); // block next button until slider is moved
    var current = jQuery("#currentValue"); // current value of slider
    slider_range = 1 // width of slider-thumb
    currentQID = this.questionId;
    rangeInput = document.getElementById('rangeInput') // slider

    // include red spots in the text below slider
    if (gender == "both"){
      second_line = "The average " + "male" + " guessed " + 
      male_avg.toString().concat("%").fontcolor("red").bold() + 
    "<br>"+ 
   "The average " + "female" + " guessed " + 
      female_avg.toString().concat("%").fontcolor("red").bold() + "<br>"
    } 
    else {
      second_line = "The average " + gender + " guessed " + 
      avg.toString().concat("%").fontcolor("red").bold() + "<br>"
    }
    
    function SliderChange() {
        // enable next button
        function enableEl() {
            that.enableNextButton()
        }   
        enableEl.defer();
    
        // find lower and upper values
        input = this.value
        lower_val = input - slider_range/2
        upper_val = (parseFloat(input) + slider_range/2);

        // show current value in question
        let msg = "The chance of getting " + n_corr + " or more questions right:<br>" + 
           second_line +
           "You have guessed " + input.toString().concat("%").bold() + "<br><br>"
    
        current.html(msg);
    }
  rangeInput.addEventListener('input', SliderChange);
});

Qualtrics.SurveyEngine.addOnPageSubmit(function(type)
{
  // record center of slider thumb on page submission
  jQuery("#" + currentQID + " .InputText").val(input);
});

Giving the slider a custom starting point

We use the rangeInput.value to update the slider, and update the current.html within the broader Qualtrics.SurveyEngine.addOnReady function. Here I set the slider the 13%.

Slider JS (for a single point slider)

Qualtrics.SurveyEngine.addOnload(function()
{
    jQuery(".InputText").hide() // hide text input box
    
});


Qualtrics.SurveyEngine.addOnReady(function()
{
    that = this;
     function hideEl() {
        that.disableNextButton()
    }   
    hideEl.defer(); // block next button until slider is moved
    var current = jQuery("#currentValue"); // current value of slider
      rangeInput = document.getElementById('rangeInput') // slider
    slider_range = 1 // width of slider-thumb
    currentQID = this.questionId;
   
     
      rangeInput.value = 13
    current.html("Your answer: "+ start + "%<br><br>");
    
   
    function SliderChange() {
        // enable next button
        function enableEl() {
          that.enableNextButton()
        }   
        enableEl.defer();
    
        // find lower and upper values
        input = this.value
        lower_val = input - slider_range/2
        upper_val = (parseFloat(input) + slider_range/2);

        // show current value in question
        current.html("Your answer: "+ input + "%<br><br>");
    }
    
    

    
  rangeInput.addEventListener('input', SliderChange);

});

Qualtrics.SurveyEngine.addOnPageSubmit(function(type)
{
    // record center of slider thumb on page submission
    jQuery("#" + currentQID + " .InputText").val(input);
});

Collecting an array of slider points

Note we create a new collect_array array, and add a new collectRange function to keep track of all the previous points.

Slider JS (for a single point slider)

Qualtrics.SurveyEngine.addOnload(function()
{
  jQuery(".InputText").hide() // hide text input box
    collect_array = [];
    
});


Qualtrics.SurveyEngine.addOnReady(function()
{
    that = this;
     function hideEl() {
        that.disableNextButton()
    }   
    hideEl.defer(); // block next button until slider is moved
    var current = jQuery("#currentValue"); // current value of slider
    rangeInput = document.getElementById('rangeInput') // slider
    slider_range = 1 // width of slider-thumb
    currentQID = this.questionId;
   
    function SliderChange() {
        // enable next button
        function enableEl() {
          that.enableNextButton()
        }   
        enableEl.defer();
    
        // find lower and upper values
        input = this.value
        lower_val = input - slider_range/2
        upper_val = (parseFloat(input) + slider_range/2);

        // show current value in question
        current.html("Your answer: "+ input + "%<br><br>");
    }
    
    
    function collectRange() {
        collect_array.push(input)
        var current2 = jQuery("#currentValue2"); // current value of slider

        // show current value in question
        
        current2.html( "Answer recorded as:" + collect_array);
    }
    
function loadSlider() {
    start = Qualtrics.SurveyEngine.getEmbeddedData("slider_1_final_value"); 
    start = parseInt(start)
    rangeInput.value = start
    current.html("Your answer: "+ start + "%<br><br>");

    }
    
    
    
    
    rangeInput.addEventListener('ready', loadSlider);   
    
    
  rangeInput.addEventListener('input', SliderChange);
  rangeInput.addEventListener('change', collectRange);

});

Qualtrics.SurveyEngine.addOnPageSubmit(function(type)
{
    // record center of slider thumb on page submission
    jQuery("#" + currentQID + " .InputText").val(collect_array);
});

Slider Gradient

Example of one slider with a red and blue gradient

Example of one slider with a red and blue gradient.



1. Question HTML:

<br>
<br>
<center><input class="slider" list="tickmarks" max="97" min="3" id="rangeInput" onchange="" step="1" type="range" value="" />
<div class="sliderticks">
<p>0%</p>
<p>20%</p>
<p>40%</p>
<p>60%</p>
<p>80%</p>
<p>100%</p>
</div>
</center>
<br />
<br />  
<center><span id="currentValue">(The continue arrow will enable after you move the slider to your decision)</span></center>

2. JS Input:

Qualtrics.SurveyEngine.addOnload(function()
{
    jQuery(".InputText").hide() // hide text input box

    
});


Qualtrics.SurveyEngine.addOnReady(function()
{
    that = this;
     function hideEl() {
        that.disableNextButton()
    }   
    hideEl.defer(); // block next button until slider is moved
    var current = jQuery("#currentValue"); // current value of slider
    slider_range = 1 // width of slider-thumb
    currentQID = this.questionId;

  // Function to look for track changes in slider
  // code inspired by https://www.qualtrics.com/community/discussion/5963/dynamic-accessing-slider-value
  
    rangeInput = document.getElementById('rangeInput') // slider
    function SliderChange() {
        // enable next button
        function enableEl() {
          that.enableNextButton()
        }   
        enableEl.defer();
    
        // find lower and upper values
        input = this.value
        lower_val = input - slider_range/2
        upper_val = (parseFloat(input) + slider_range/2);

        // show current value in question
        current.html("Your answer: "+ input + "%<br><br>");
    }
    
function adjustSlider(){
  min = this.min;
  max = this.max;
  // Calculate visible width
  val = ((this.value - min) * 100) / (max - min);
  
  // Change these variables to the colors you need
  const fillLeft = "#B90000";
  const fillRight = "#00008B";
  
  this.style.background = "linear-gradient(to right, "+fillLeft+" " + val + "%, "+ fillRight+" "+val+"%";
};
    
    
    
       rangeInput = document.getElementById('rangeInput') // slider

    var min = 0;
    var max = 100;
    var val = ((50 - min) * 100) / (max - min);
   const fillLeft = "#B90000";
   const fillRight = "#00008B";
   rangeInput.style.background = "linear-gradient(to right, "+fillLeft+" " + val + "%, "+ fillRight+" "+val+"%";


    rangeInput.addEventListener('input', SliderChange);
    rangeInput.addEventListener('input', adjustSlider);
    rangeInput.addEventListener('change', collectRange);

});

Qualtrics.SurveyEngine.addOnPageSubmit(function(type)
{
    // record center of slider thumb on page submission
    Qualtrics.SurveyEngine.setEmbeddedData("slider_1_final_value", input); 

});

3. Look and Feel Input (CSS)

.slider {
    -webkit-appearance: none;
    appearance: none;
    width: 90%;
    height: 2em;
    background-color:transparent;
    outline: none;
    opacity: 0.7;
    -webkit-transition: .2s;
    transition: opacity .2s;
  }




  .sliderticks {
    display: flex;
    width: 93%;
    justify-content: space-between;
    padding: 0 10px;
  }
  
  .sliderticks p {
    position: relative;
    display: flex;
    justify-content: center;
    text-align: center;
    width: 1px;
    background: #D3D3D3;
    height: 10px;
    line-height: 40px;
    margin: 0 0 20px 0;
  }
  
  .slider:hover {
    opacity: 1;
  }
  
  :root {
    --thumb-width: 0.9%;
  }


  .slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: var(--thumb-width);
    height: 2em;
    background: #000000;
    cursor: pointer;
  }
  
  .slider::-moz-range-thumb {
    width: var(--thumb-width);
    height: 2em;
    background: #000000;
    cursor: pointer;
  }
  
  .slider::-ms-thumb {
    width: var(--thumb-width);
    height: 2em;
    background: #000000;
    cursor: pointer;
  }

Two Sliders on the Same Page

Example of two sliders in Action

Example of two sliders in Action.




Example of two sliders in Qualtrics
Example of two sliders in Qualtrics (note: this is different than how they’ll appear in your survey).

1a. Question HTML Top Slider

We write the slider in HTML and set the max and min of allowable range. Note that these are the max and min of the center of the slider, (i.e., a slider thumb with a total range of 6, can never advance past 97).

<br>
<br>
<center><input class="slider" id="topSlider" list="tickmarks" max="97" min="3" onchange="" step="1" type="range" value="" />
<div class="sliderticks">
<p>0%</p>
<p>20%</p>
<p>40%</p>
<p>60%</p>
<p>80%</p>
<p>100%</p>
</div>
</center>

<center>
<br />
<br />
<span id="topSliderInput">(The continue arrow will enable after you move the slider to your decision)</span></center>

1b.Question HTML Bottom Slider

<br>
<br>
<center><input class="slider" id="bottomSlider" list="tickmarks" max="97" min="3" onchange="" step="1" type="range" value="" />
<div class="sliderticks">
<p>0%</p>
<p>20%</p>
<p>40%</p>
<p>60%</p>
<p>80%</p>
<p>100%</p>
</div>
</center>

<center><br />
<br />
<span id="bottomSliderInput">(The continue arrow will enable after you move the slider to your decision)</span></center>

2a. JS Input Top Slider

Qualtrics.SurveyEngine.addOnload(function()
{
    jQuery(".InputText").hide() // hide text input box
});


Qualtrics.SurveyEngine.addOnReady(function()
{
    that = this;
     function hideEl() {
        that.disableNextButton()
    }   
    hideEl.defer(); // block next button until slider is moved
    var current = jQuery("#topSliderInput"); // current value of top slider
    slider_range = 6 // width of slider-thumb
    currentQID_top = this.questionId;

  // Function to look for track changes in slider
  // code inspired by https://www.qualtrics.com/community/discussion/5963/dynamic-accessing-slider-value
  
    topSlider = document.getElementById('topSlider')
    function topSliderChange() {
        // both sliders need to be slided in order to activate next button
        function enableEl() {
            that.enableNextButton()
        }   
         
        function changeFunction() {
            enableEl.defer();
        }
        var bottomSlider = document.getElementById('bottomSlider');
        // this will only enable the NextButton if both sliders were changed
        bottomSlider.addEventListener('input', changeFunction);
        
        // find lower and upper values
        input_top = this.value
        lower_val = input_top - slider_range/2
        upper_val = (parseFloat(input_top) + slider_range/2);

        // show current value in question
        current.html("Your answer: "+ lower_val + "% - " + upper_val + "%.<br><br>");
    }
  topSlider.addEventListener('input', topSliderChange);
});


Qualtrics.SurveyEngine.addOnPageSubmit(function(type)
{
    // record center of slider thumb on page submission
        jQuery("#" + currentQID_top + " .InputText").val(input_top);
});

2b. JS Input Bottom Slider

Qualtrics.SurveyEngine.addOnload(function()
{
  jQuery(".InputText").hide() // hide text input

});


Qualtrics.SurveyEngine.addOnReady(function()
{
    that = this;
     function hideEl() {
        that.disableNextButton()
    }   
    hideEl.defer(); // block next button until slider is moved
    slider_range = 6
    var current = jQuery("#bottomSliderInput");
    currentQID_bottom = this.questionId;

  // Function to look for track changes in slider
  // code inspired by https://www.qualtrics.com/community/discussion/5963/dynamic-accessing-slider-value
  
    bottomSlider = document.getElementById('bottomSlider')
    function bottomSliderChange() {
        // both sliders need to be slided in order to activate next button
        function enableEl() {
            that.enableNextButton()
        }   
        
        function changeFunction() {
            enableEl.defer();
        }
        var topSlider = document.getElementById('topSlider');
        topSlider.addEventListener('input', changeFunction);
        
        
        
        
        input_bottom = this.value
        lower_val = input_bottom - slider_range/2
        upper_val = (parseFloat(input_bottom) + slider_range/2);

        current.html("Your answer: "+ lower_val + "% - " + upper_val + "%.<br><br>");
    }
  bottomSlider.addEventListener('input', bottomSliderChange);
});


Qualtrics.SurveyEngine.addOnPageSubmit(function(type)
{
        jQuery("#"+currentQID_bottom+" .InputText").val(input_bottom);
});

3. Look and Feel Input (CSS)

This is where the slider(s) are globally styles and provides consistency for the slider across different web-browsers.

.slider {
    -webkit-appearance: none;
    appearance: none;
    width: 90%;
    height: 2em;
    background: #D3D3D3;
    outline: none;
    opacity: 0.7;
    -webkit-transition: .2s;
    transition: opacity .2s;
  }
  
  .sliderticks {
    display: flex;
    width: 93%;
    justify-content: space-between;
    padding: 0 10px;
  }
  
  .sliderticks p {
    position: relative;
    display: flex;
    justify-content: center;
    text-align: center;
    width: 1px;
    background: #D3D3D3;
    height: 10px;
    line-height: 40px;
    margin: 0 0 20px 0;
  }
  
  .slider:hover {
    opacity: 1;
  }
  
 
  :root {
    --thumb-width: 5.4%;
  }


  .slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: var(--thumb-width);
    height: 2em;
    background: #000000;
    cursor: pointer;
  }
  
  .slider::-moz-range-thumb {
    width: var(--thumb-width);
    height: 2em;
    background: #000000;
    cursor: pointer;
  }
  
  .slider::-ms-thumb {
    width: var(--thumb-width);
    height: 2em;
    background: #000000;
    cursor: pointer;
  }

Two sliders side by side on the same page

Example of two sliders side-by-side in action

Example of two sliders side-by-side in Qualtrics in action.




Example of two sliders side-by-side in Qualtrics
Example of two sliders side-by-side in Qualtrics with an information table (note: this is different than how they’ll appear in your survey).

Often in surveys it makes sense to compare two groups side by side. Likewise it makes sense to have two sliders horizontally instead of vertically. Here I place some information in a table and place the sliders in their own table below.

0. Information Table (Optional)

Here I used an arbitrary example, but this should be easy enough to modify for your own use

<table width="500px" style="width:750px;" height="150" cellspacing="1" cellpadding="1" border="0" align="center">
 <tbody>
  <tr>
   <td style="text-align: center; width: 48%;"><u><span style="font-size:16px;"><strong>Person A</strong></span></u></td>
   <td style="text-align: center; width: 4%;">&nbsp;</td>
   <td style="text-align: center; width: 48%;"><u><span style="font-size:16px;"><strong>Person B</strong></span></u></td>
  </tr>

  <tr>
   <td><span style="font-size:16px;"><span style="color:#2980b9;"><strong>id:</strong></span>&nbsp;${e://Field/left_id}</span></td>
   <td>&nbsp;</td>
   <td><span style="font-size:16px;"><span style="color:#2980b9;"><strong>id:</strong>&nbsp;</span>${e://Field/right_id}</span></td>
  </tr>
  <tr>


  </tr><tr>
   <td><span style="font-size:16px;"><span style="color:#2980b9;"><strong>Race:</strong></span>&nbsp;${e://Field/left_black}</span></td>
   <td>&nbsp;</td>
   <td><span style="font-size:16px;"><span style="color:#2980b9;"><strong>Race:</strong>&nbsp;</span>${e://Field/right_black}</span></td>
  </tr>
  <tr>
   <td><span style="font-size:16px;"><span style="color:#2980b9;"><strong>Gender:</strong></span><strong>&nbsp;</strong>${e://Field/left_male}</span></td>
   <td>&nbsp;</td>
   <td><span style="font-size:16px;"><span style="color:#2980b9;"><strong>Gender:</strong><strong>&nbsp;</strong></span>${e://Field/right_male}</span></td>
  </tr>
  <tr>
   <td><span style="font-size:16px;"><span style="color:#2980b9;"><strong>Christian:</strong>&nbsp;</span>${e://Field/left_christian}</span></td>
   <td>&nbsp;</td>
   <td><span style="font-size:16px;"><span style="color:#2980b9;"><strong>Christian:</strong></span>&nbsp;${e://Field/right_christian}</span></td>
  </tr>
<tr>
   <td><span style="font-size:16px;"><span style="color:#2980b9;"><strong>Above median income:</strong>&nbsp;</span>${e://Field/left_high_income}</span></td>
   <td>&nbsp;</td>
   <td><span style="font-size:16px;"><span style="color:#2980b9;"><strong>Above median income:</strong></span>&nbsp;${e://Field/right_high_income}</span></td>
  </tr>

  <tr>
   <td><span style="font-size:16px;"><span style="color:#2980b9;"><strong>High school age:</strong>&nbsp;</span>${e://Field/left_highschool_age}</span></td>
   <td>&nbsp;</td>
   <td><span style="font-size:16px;"><span style="color:#2980b9;"><strong>High school age:</strong></span>&nbsp;${e://Field/right_highschool_age}</span></td>
  </tr>


  <tr>
   <td><span style="font-size:16px;"><span style="color:#2980b9;"><strong>thirtyone_days:</strong>&nbsp;</span>${e://Field/left_thirtyone_days}</span></td>
   <td>&nbsp;</td>
   <td><span style="font-size:16px;"><span style="color:#2980b9;"><strong>thirtyone_days:</strong></span>&nbsp;${e://Field/right_thirtyone_days}</span></td>
  </tr>
 </tbody>
</table>

1a. Slider HTML Table

<table width="500px" style="width:750px;" height="150" cellspacing="1" cellpadding="1" border="0" text-align:"center" align="center">
 <tbody>


  <tr>
   <td> <input class="slider" id="topSlider" list="tickmarks" max="97" min="3" onchange="" step="1" type="range" value="" />
<div class="sliderticks">
<p>0%</p>
<p>20%</p>
<p>40%</p>
<p>60%</p>
<p>80%</p>
<p>100%</p>
</div>
 </td>
   <td>&nbsp;</td>
   <td><input class="slider" id="bottomSlider" list="tickmarks" max="97" min="3" onchange="" step="1" type="range" value="" />
<div class="sliderticks">
<p>0%</p>
<p>20%</p>
<p>40%</p>
<p>60%</p>
<p>80%</p>
<p>100%</p>
</div>
</td>
  </tr>
  <tr>

<tr>
   <td style="text-align: center"> <span id="topSliderInput">(The continue arrow will enable after you move the slider to your decision)</span></td>
   <td>&nbsp;</td>
   <td style="text-align: center"> <span id="bottomSliderInput">(The continue arrow will enable after you move the slider to your decision)</span> </td>
  </tr>
 </tbody>
</table>
<center>
<br />
<br />

1b. Second Slider Question

&nbsp;

2a. JS Input HTML Table

Qualtrics.SurveyEngine.addOnload(function()
{
    jQuery(".InputText").hide() // hide text input box

});


Qualtrics.SurveyEngine.addOnReady(function()
{
    that = this;
     function hideEl() {
        that.disableNextButton()
    }   
    hideEl.defer(); // block next button until slider is moved
    var current = jQuery("#topSliderInput"); // current value of top slider
    slider_range = 6 // width of slider-thumb
    currentQID_top = this.questionId;

  // Function to look for track changes in slider
  // code inspired by https://www.qualtrics.com/community/discussion/5963/dynamic-accessing-slider-value
  
    topSlider = document.getElementById('topSlider')
    function topSliderChange() {
        // both sliders need to be slided in order to activate next button
        // enable next button
        function enableEl() {
            that.enableNextButton()
        }   
        
        function changeFunction() {
            enableEl.defer();
        }
        var bottomSlider = document.getElementById('bottomSlider');
        // this will only enable the NextButton if both sliders were changed
        bottomSlider.addEventListener('input', changeFunction);
        
        // find lower and upper values
        input_top = this.value
        lower_val = input_top - slider_range/2
        upper_val = (parseFloat(input_top) + slider_range/2);

        // show current value in question
        current.html("Your answer: "+ lower_val + "% - " + upper_val + "%.<br><br>");
    }
  topSlider.addEventListener('input', topSliderChange);
});


Qualtrics.SurveyEngine.addOnPageSubmit(function(type)
{
    // record center of slider thumb on page submission
        jQuery("#" + currentQID_top + " .InputText").val(input_top);
});

2b. JS Second Text Input Question

Qualtrics.SurveyEngine.addOnload(function()
{
  jQuery(".InputText").hide() // hide text input
  
});


Qualtrics.SurveyEngine.addOnReady(function()
{
    that = this;
     function hideEl() {
        that.disableNextButton()
    }   
    hideEl.defer(); // block next button until slider is moved
    slider_range = 6;
    var current = jQuery("#bottomSliderInput");
    currentQID_bottom = this.questionId;

  // Function to look for track changes in slider
  // code inspired by https://www.qualtrics.com/community/discussion/5963/dynamic-accessing-slider-value
  
    bottomSlider = document.getElementById('bottomSlider')
    function bottomSliderChange() {
        // both sliders need to be slided in order to activate next button
        function enableEl() {
            that.enableNextButton()
        }   
        
        function changeFunction() {
            enableEl.defer();
        }
        var topSlider = document.getElementById('topSlider');
        topSlider.addEventListener('input', changeFunction);
        
        
        
        
        input_bottom = this.value
        lower_val = input_bottom - slider_range/2
        upper_val = (parseFloat(input_bottom) + slider_range/2);

        current.html("Your answer: "+ lower_val + "% - " + upper_val + "%.<br><br>");
    }
  bottomSlider.addEventListener('input', bottomSliderChange);
});


Qualtrics.SurveyEngine.addOnPageSubmit(function(type)
{
        jQuery("#"+currentQID_bottom+" .InputText").val(input_bottom);
});

3. Look and Feel Input (CSS)

Note that the CSS in this block is substantially different than the preceding CSS blocks.

.slider {
    -webkit-appearance: none;
    appearance: none;
    width: 25em;
    height: 2em;
    background: #D3D3D3;
    outline: none;
    opacity: 0.7;
    -webkit-transition: .2s;
    transition: opacity .2s;
    margin: 00px 40px 00px 40px;
  }
  
  .sliderticks {
     display: flex;
    width: 22em;
    justify-content: space-between;
    margin: 00px 40px 00px 40px;
  }
  
  .sliderticks p {
    position: relative;
    display: flex;
    justify-content: center;
    text-align: center;
    width: 1px;
    background: #D3D3D3;
    height: 10px;
    line-height: 40px;
    margin: 0 0 20px 0;
  }
  
  .slider:hover {
    opacity: 1;
  }


:root {
  --thumb-width: 5.4%;
}


  .slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: var(--thumb-width);
    height: 2em;
    background: #000000;
    cursor: pointer;
  }
  
  .slider::-moz-range-thumb {
    width: var(--thumb-width);
    height: 2em;
    background: #000000;
    cursor: pointer;
  }
  
  .slider::-ms-thumb {
    width: var(--thumb-width);
    height: 2em;
    background: #000000;
    cursor: pointer;
  }

Three Sliders on the Same Page and higher

This solution should generalize to higher ranges. Note that the first slider has slightly different JS, but the 2nd and 3rd sliders are extremely similar. Here I use the same CSS as in the two slider example.

Note that to generalize to higher amount of sliders the small part of all of the JS needs to change as well.

if (s1 + s2  + s3 == 3){
  changeFunction()
}

1. Question HTML of Sliders

Here id="Slider1" and id="Slider1Input" will need to be incremented for each slider. E.g., to Slider2 and Slider2Input, etc.

<br>
<br>
<center><input class="slider" id="Slider1" list="tickmarks" max="97" min="3" onchange="" step="1" type="range" value="" />
<div class="sliderticks">
<p>0%</p>
<p>20%</p>
<p>40%</p>
<p>60%</p>
<p>80%</p>
<p>100%</p>
</div>
</center>

<center>
<br />
<br />
<span id="Slider1Input">(The continue arrow will enable after you move the slider to your decision)</span></center>

2a. JS Input of Slider 1

Qualtrics.SurveyEngine.addOnload(function()
{
    s1 = false
    s2 = false
    s3 = false
    jQuery(".InputText").hide() // hide text input box
});


Qualtrics.SurveyEngine.addOnReady(function()
{
    that = this;
     function hideEl() {
        that.disableNextButton()
    }   
    hideEl.defer(); // block next button until slider is moved
    var current = jQuery("#Slider1Input"); // current value of top slider
    slider_range = 6 // width of slider-thumb
    currentQID_1 = this.questionId;

  // Function to look for track changes in slider
  // code inspired by https://www.qualtrics.com/community/discussion/5963/dynamic-accessing-slider-value
  
    slider1 = document.getElementById('Slider1')
    function s1Change() {
        s1 = true
        // both sliders need to be slided in order to activate next button
        function enableEl() {
            that.enableNextButton()
        }   
       

        function changeFunction() {
            enableEl.defer();
        }
        
        if (s1 + s2  + s3 == 3){
            changeFunction()
        }

        // find lower and upper values
        input_1 = this.value
        lower_val = input_1 - slider_range/2
        upper_val = (parseFloat(input_1) + slider_range/2);

        // show current value in question
        current.html("Your answer: "+ lower_val + "% - " + upper_val + "%.<br><br>");
    }
  Slider1.addEventListener('input', s1Change);
});


Qualtrics.SurveyEngine.addOnPageSubmit(function(type)
{
    // record center of slider thumb on page submission
        jQuery("#" + currentQID_1 + " .InputText").val(input_1);
});

2b. JS Input of Slider 2

Qualtrics.SurveyEngine.addOnReady(function()
{
    slider_range = 6
    var current = jQuery("#Slider2Input");
    currentQID_2 = this.questionId;

  // Function to look for track changes in slider
  // code inspired by https://www.qualtrics.com/community/discussion/5963/dynamic-accessing-slider-value
  
    Slider2 = document.getElementById('Slider2')
    function s2Change() {
        s2 = true
        // both sliders need to be slided in order to activate next button
        function enableEl() {
            that.enableNextButton()
        }   
        
        function changeFunction() {
            enableEl.defer();
        }
        
        if (s1 + s2 + s3 == 3){
            changeFunction()
        }
        
        
        
        
        input_2 = this.value
        lower_val = input_2 - slider_range/2
        upper_val = (parseFloat(input_2) + slider_range/2);

        current.html("Your answer: "+ lower_val + "% - " + upper_val + "%.<br><br>");
    }
  Slider2.addEventListener('input', s2Change);
});


Qualtrics.SurveyEngine.addOnPageSubmit(function(type)
{
        jQuery("#" + currentQID_2 +" .InputText").val(input_2);
});

This part is basically identical to the JS of Slider 2. I include this just for convience.

2c. JS Input of Slider 3

Qualtrics.SurveyEngine.addOnReady(function()
{
    slider_range = 6
    var current = jQuery("#Slider3Input");
    currentQID_3 = this.questionId;

  // Function to look for track changes in slider
  // code inspired by https://www.qualtrics.com/community/discussion/5963/dynamic-accessing-slider-value
  
    Slider3 = document.getElementById('Slider3')
    function s3Change() {
        s3 = true
        // both sliders need to be slided in order to activate next button
        function enableEl() {
            that.enableNextButton()
        }   
        
        function changeFunction() {
            enableEl.defer();
        }
        
        if (s1 + s2 + s3 == 3){
            changeFunction()
        }
        
        
        
        
        input_3 = this.value
        lower_val = input_3 - slider_range/2
        upper_val = (parseFloat(input_3) + slider_range/2);

        current.html("Your answer: "+ lower_val + "% - " + upper_val + "%.<br><br>");
    }
  Slider3.addEventListener('input', s3Change);
});


Qualtrics.SurveyEngine.addOnPageSubmit(function(type)
{
        jQuery("#" + currentQID_3 +" .InputText").val(input_3);
});

What about different ranges?

In the above examples I kept the range at 6 (-3/+3). However if the slider ranges changes, the slider thumb should change appropriately too. Because the slider is always 90% of the width of the screen the way you calculate the thumb should be 90 * slider_range / 100. At range 6 this is 5.4% as you should see in the thumb CSS below. Likewise, a slider with range 10, the slider thumb with range 10, should have 9% thumbs.

However a slider with a different range also needs to have the upper and lower bound changed as well. Because most sliders have a range > 1, we cannot have the literal center of the slider can never reach 0 and 100 which is why we need to set the max and min in the HTML.

Below I show a table of several popular potential slider ranges. Note that if the slider range is changed all of the values in a given row need to be updated.

slider_range (JS) –thumb-width (css) slider max (html) slider min (html)
1 0.9% 99.5 0.5
3 2.7% 98.5 1.5
4 3.6% 98.0 2.0
5 4.5% 97.5 2.5
6 5.4% 97.0 3.0
7 6.3% 96.5 3.5
10 9% 95.0 5.0
20 18% 90.0 10.0
25 22.5% 87.5 12.5