118

I would like to display an <input type="range" /> slider control vertically. I'm only concerned with browsers that support the range slider control.

I've found some comments and references that seem to indicate that setting the height greater than the width will cause the browser to change the orientation automatically, but in my testing, that only works in Opera used to work in Opera, but not anymore. How can I orient an HTML5 range slider vertically?

gilly3
  • 87,962
  • 25
  • 144
  • 176

6 Answers6

182

First, set height greater than width. In theory, this is all you should need. The HTML5 Spec suggests as much:

... the UA determined the orientation of the control from the ratio of the style-sheet-specified height and width properties.

Opera had it implemented this way, but Opera is now using WebKit Blink. As of today, no browser implements a vertical slider based solely on height being greater than width. And now that suggestion is under review by WHATWG.

Regardless, setting height greater than width is needed to get the layout right between browsers. Applying left and right padding will also help with layout and positioning.

For Chrome, use -webkit-appearance: slider-vertical.

For IE, use writing-mode: bt-lr.

For Firefox, add an orient="vertical" attribute to the html. Pity that they did it this way. Visual styles should be controlled via CSS, not HTML.

input[type=range][orient=vertical]
{
    writing-mode: bt-lr; /* IE */
    -webkit-appearance: slider-vertical; /* Chromium */
    width: 8px;
    height: 175px;
    padding: 0 5px;
}
<input type="range" orient="vertical" />

Disclaimers:

This solution is based on current browser implementations of as yet still undefined or unfinalized CSS properties. If you intend to use it in your code, be prepared to make code adjustments as newer browser versions are released and WHATWG recommendations are completed. Subscribe to this github issue to get updates when they finally decide on a CSS attribute to officially control slide orientation.

MDN contains a warning about using -webkit-appearance on the web:

Note: If you wish to use this property on websites, you should test it very carefully. Although it is supported in most modern browsers, its implementation varies. In older browsers, even the keyword none does not have the same effect on all form elements across different browsers, and some do not support it at all. The differences are smaller in the newest browsers.

Despite these warnings, this answer is now nearly 9 years old, and the advice remains largely unchanged.

gilly3
  • 87,962
  • 25
  • 144
  • 176
  • 2
    +1 for the disclaimer about `-webkit-appearance` - I didn't know that. It changes everything. – Robin Winslow Mar 14 '14 at 23:43
  • Input element with type="range" in IE is very sensitive to width/height/display values. When using Bootstrap some of these values may be inadvertently overwritten (especially if you don't use blanket css as in the answer). For one of my vertical ranges I use css like this: .vert { -ms-writing-mode: bt-lr; /* IE */ -webkit-appearance: slider-vertical; /* WebKit */ height: 210px; width: 20px !important; padding: 0 5px; display: inline-block !important; } – mp31415 Nov 07 '14 at 17:59
  • 1
    I'm definitely not a fan of `!important`. It's always better to strengthen your selector. Instead of just `.vert`, use something like `input[type=range].vert`. – gilly3 Nov 07 '14 at 20:33
  • This works, but the downside is that you can't use custom colors, shapes, ...etc for the range item. Think rotating will be the best for me. – Jongwoo Lee Jul 08 '21 at 01:29
  • well, I have a problem with using this solution, I browsed this page in Opera and it works fine, but when I use " " in a practice webpage and open it in Opera it still appears horizontal, tried changing width and height, not working either , not even when used together. as of now I don't know how to use this, although I have been stuck in what is just a practice project, still it is pretty frustrating not to be able to get the code work. – Hitman2847 May 09 '22 at 12:01
  • @Hitman2847 - Are you including the CSS? If you can provide a link (to jsfiddle, or something), I'm happy to take a look. – gilly3 May 09 '22 at 18:11
  • @gilly3 I did not, I will try it but in the meantime I archived and uploaded the files on MEGA.nz : https://mega.nz/file/P9sEyIzY#a2wZpRym0pxmXHvXJoSHkFwL3_k6aLfFN_gY032T9Jg – Hitman2847 May 10 '22 at 07:38
  • @Hitman2847 - The CSS in my answer is not optional. If you didn't include the CSS, it won't work. – gilly3 May 11 '22 at 21:20
  • right thanks, I know JS, and HTML , but since I don't know CSS I couldn't use it, I will study CSS and then try this and get back here, thanks again – Hitman2847 May 22 '22 at 13:04
  • Progress report, Dec 2022: almost no progress. You can use appearance: instead of -webkit-appearance: ... that's about it. Firefox still requires orient=vertical, safari&chrome appearance: slider-vertical. Each ignore the other. – OsamaBinLogin Dec 28 '22 at 21:36
  • PS: none of these work anymore: https://brennaobrien.com/blog/2014/05/style-input-type-range-in-every-browser.html – OsamaBinLogin Dec 28 '22 at 21:40
94

You can do this with css transforms, though be careful with container height/width. Also you may need to position it lower:

input[type="range"] {
   position: absolute;
   top: 40%;
   transform: rotate(270deg);
}
<input type="range"/>

or the 3d transform equivalent:

input[type="range"] {
   transform: rotateZ(270deg);
}

You can also use this to switch the direction of the slide by setting it to 180deg or 90deg for horizontal or vertical respectively.

MaxPRafferty
  • 4,819
  • 4
  • 32
  • 39
  • 2
    Note you need to make it 270 if you want it to correspond with higher values you go up and lower values you go down. Edited your answer. – aug Jan 13 '15 at 20:23
  • 1
    I prefer this approach as it supports custom css styling. With the other approach, custom styling makes the slider act funny – Kim T Mar 28 '15 at 16:54
  • 2
    This is simple but brilliant – Christopher M. Jul 29 '16 at 06:18
  • 1
    Instead of position: absolute you might use display: inline-block; with transform-origin. – Denis Giffeler Jan 03 '20 at 13:03
  • @DenisGiffeler the position absolute isn't really part of this solution, it's just a convenient way to make the SO example display correctly. There are many ways to accomplish the positioning depending on your use case. – MaxPRafferty Jan 03 '20 at 21:36
32

Without changing the position to absolute, see below. This supports all recent browsers as well.

.vranger {
  margin-top: 50px;
   transform: rotate(270deg);
  -moz-transform: rotate(270deg); /*do same for other browsers if required*/
}
<input type="range" class="vranger"/>

for very old browsers, you can use -sand-transform: rotate(10deg); from CSS sandpaper

or use

prefix selector such as -ms-transform: rotate(270deg); for IE9

Ifeanyi Chukwu
  • 3,187
  • 3
  • 28
  • 32
  • 3
    also include something like `transform-origin: center left;` to have slider be left-justified not center-justified. – DragonLord Mar 31 '20 at 16:34
3

.container {
    border: 3px solid #eee;
    margin: 10px;
    padding: 10px;
    float: left;
    text-align: center;
    max-width: 20%
}

input[type=range].range {
    cursor: pointer;
    width: 100px !important;
    -webkit-appearance: none;
    z-index: 200;
    width: 50px;
    border: 1px solid #e6e6e6;
    background-color: #e6e6e6;
    background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#e6e6e6), to(#d2d2d2));
    background-image: -webkit-linear-gradient(right, #e6e6e6, #d2d2d2);
    background-image: -moz-linear-gradient(right, #e6e6e6, #d2d2d2);
    background-image: -ms-linear-gradient(right, #e6e6e6, #d2d2d2);
    background-image: -o-linear-gradient(right, #e6e6e6, #d2d2d2)
}

input[type=range].range:focus {
    border: 0 !important;
    outline: 0 !important
}

input[type=range].range::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 10px;
    height: 10px;
    background-color: #555;
    background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#4ddbff), to(#0cf));
    background-image: -webkit-linear-gradient(right, #4ddbff, #0cf);
    background-image: -moz-linear-gradient(right, #4ddbff, #0cf);
    background-image: -ms-linear-gradient(right, #4ddbff, #0cf);
    background-image: -o-linear-gradient(right, #4ddbff, #0cf)
}

input[type=range].round {
    -webkit-border-radius: 20px;
    -moz-border-radius: 20px;
    border-radius: 20px
}

input[type=range].round::-webkit-slider-thumb {
    -webkit-border-radius: 5px;
    -moz-border-radius: 5px;
    -o-border-radius: 5px
}

.vertical-lowest-first {
    -webkit-transform: rotate(90deg);
    -moz-transform: rotate(90deg);
    -o-transform: rotate(90deg);
    -ms-transform: rotate(90deg);
    transform: rotate(90deg)
}

.vertical-heighest-first {
    -webkit-transform: rotate(270deg);
    -moz-transform: rotate(270deg);
    -o-transform: rotate(270deg);
    -ms-transform: rotate(270deg);
    transform: rotate(270deg)
}
<div class="container" style="margin-left: 0px">
    <br><br>
    <input class="range vertical-lowest-first" type="range" min="0" max="1" step="0.1" value="1">
    <br><br><br>
</div>

<div class="container">
    <br><br>
    <input class="range vertical-heighest-first" type="range" min="0" max="1" step="0.1" value="1">
    <br><br><br>
</div>


<div class="container">
    <br><br>
    <input class="range vertical-lowest-first round" type="range" min="0" max="1" step="0.1" value="1">
    <br><br><br>
</div>


<div class="container" style="margin-right: 0px">
    <br><br>
    <input class="range vertical-heighest-first round" type="range" min="0" max="1" step="0.1" value="1">
    <br><br><br>
</div>

Source: http://twiggle-web-design.com/tutorials/Custom-Vertical-Input-Range-CSS3.html

Mahdi Bashirpour
  • 17,147
  • 12
  • 117
  • 144
3

Its very simple. I had implemented using -webkit-appearance: slider-vertical, It worked in chrome, Firefox, Edge

<input type="range">
input[type=range]{
    writing-mode: bt-lr; /* IE */
    -webkit-appearance: slider-vertical; /* WebKit */
    width: 50px;
    height: 200px;
    padding: 0 24px;
    outline: none;
    background:transparent;
}
Ashiq Dey
  • 309
  • 5
  • 18
  • I still needed orient="vertical" on the input tag. Just a heads up! – Tom Feb 19 '21 at 10:17
  • @Tom Which browser? – ˈvɔlə Oct 25 '21 at 15:39
  • 1
    @WΩLLE-ˈvɔlə It was a while ago, so I can't fully remember now, but I think it was Safari. I completely ignore IE these days if I can, so I think it must have been that. – Tom Oct 26 '21 at 19:26
1

window.onload = function(){
var slider = document.getElementById("sss");
 var  result = document.getElementById("final");
slider.oninput = function(){
    result.innerHTML = slider.value ;
}
}
.slider{
    width: 100vw;
    height: 100vh;
   
    display: flex;
    justify-content: center;
    align-items: center;
}

.slider .container-slider{
    width: 600px;
    display: flex;
    justify-content: center;
    align-items: center;
    transform: rotate(90deg)
}

.slider .container-slider input[type="range"]{
    width: 60%;
    -webkit-appearance: none;
    background-color: blue;
    height: 7px;
    border-radius: 5px;;
    outline: none;
    margin: 0 20px
    
}

.slider .container-slider input[type="range"]::-webkit-slider-thumb{
    -webkit-appearance: none;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background-color: red;
}



.slider .container-slider input[type="range"]::-webkit-slider-thumb:hover{

box-shadow: 0px 0px 10px rgba(255,255,255,.3),
            0px 0px 15px rgba(255,255,255,.4),
            0px 0px 20px rgba(255,255,255,.5),
            0px 0px 25px rgba(255,255,255,.6),
            0px 0px 30px rgba(255,255,255,.7)

}


.slider .container-slider .val {
    width: 60px;
    height: 40px;
    background-color: #ACB6E5;
    display: flex;
    justify-content: center;
    align-items: center;
    font-family: consolas;
    font-weight: 700;
    font-size: 20px;
    letter-spacing: 1.3px;
    transform: rotate(-90deg)
}

.slider .container-slider .val::before{
    content: "";
    position: absolute;
    width: 0;
    height: 0;
    display: block;
    border: 20px solid transparent;
    border-bottom-color: #ACB6E5;
    top: -30px;
}
<div class="slider">
  <div class="container-slider">
    <input type="range" min="0" max="100" step="1" value="" id="sss">
    <div class="val" id="final">0</div>
  </div>
</div>
Vijay Dwivedi
  • 172
  • 2
  • 12
  • 3
    Please don't post only code as an answer, but also provide an explanation of what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes. – Ran Marciano Feb 12 '21 at 08:36