Stylish range input, Google Chrome only I have an input[type=range] element which is customized using CSS to look more modern. 

I'm unhappy with my CSS because of the need to use position:relative on the wrapping element and position:absolute on an invisible range input.

I'm wondering if I made this logic unnecessarily convoluted. Is there a way to achieve the same presentation in a simpler manner? Maybe just by customize the input itself instead of hiding and emulating it?

Here's a JSFiddle and here is the accompanying CSS and HTML:



&lt;div class="time-progress"&gt;
    &lt;div class="time-elapsed time-label"&gt;
        01:47
    &lt;/div&gt;

    &lt;div class="time-slider"&gt;
        &lt;div class="progress" style="width: 49.537037037037%;"&gt;&lt;/div&gt;
        &lt;input class="time-range" type="range" /&gt;
    &lt;/div&gt;

    &lt;div class="duration time-label"&gt;
        03:36
    &lt;/div&gt;
&lt;/div&gt;

*, *:before, *:after {
    box-sizing: border-box;
}

input:focus, button:focus {
    outline: none 
}

.time-progress {
    display: flex;
    align-items: center;
    width: 300px;
    margin-top: 30px;
    margin-left: 30px;
}

.time-label {
    margin: 0 5px;
}

.time-slider {
    background: #ebebeb;
    height: 3px;
    flex: 1;
    margin: 0 10px;
    position: relative;
}

.progress {
    background: #4ea6ea;
    height: 100%;
}

.time-range {
    bottom: -1px;
    position: absolute;
    width: 100%;
}

input[type=range] {
    -webkit-appearance: none;
    background: transparent;
    height: 1px;
}

input[type=range]::-webkit-slider-thumb {
    -webkit-appearance: none;
    box-shadow: 0 0 5px #666666;
    background: #666666;
    border-radius: 100%;
    height: 10px;
    width: 10px;
}
Your code validates at the HTML and CSS validators, except for one thing:

You need to place a doctype at the top of the page:



You also need to provide head and body elements and place your code in the body tag, like this:

&lt;!doctype html&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;title&gt;Page title&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;!-- Your code here --&gt;
&lt;/body&gt;


I was unable to completely remove the position properties in the CSS, but I was able to remove one.  I also adjusted position of the progress bar as it was not lining up with the input bar nicely.

Here I changed the margin padding:

.time-progress {
    /* ... */
    padding-top: 30px;
    padding-left: 30px;
}


I removed two values from this class:

.time-slider {
    background: #ebebeb;
    height: 3px;
    flex: 1;
}


This is the adjusted .progress class:

.progress {
    background: #4ea6ea;
    height: 100%;
    vertical-align: top;
    position: relative;
}


This is the adjusted .time-range class:

.time-range {
    margin-left: 0px;
    padding: 0px;
    width: 100%;
    vertical-align: top;
}


I changed the progress div to this:

&lt;div class="progress" style="width: 47%;"&gt;&lt;/div&gt;


This prevents the blue bar from overlapping the button at the default position.



*, *:before, *:after {
    box-sizing: border-box;
}

input:focus, button:focus {
    outline: none 
}

.time-progress {
    display: flex;
    align-items: center;
    width: 300px;
    padding-top: 30px;
    padding-left: 30px;
}

.time-label {
    margin: 0 5px;
}

.time-slider {
    background: #ebebeb;
    height: 3px;
    flex: 1;
}

.progress {
    background: #4ea6ea;
    height: 100%;
    margin-top: 0px;
    vertical-align: top;
    position: relative;
}

.time-range {
    margin-top: -2px;
    margin-left: 0px;
    padding: 0px;
    width: 100%;
    vertical-align: top;
}

input[type=range] {
    -webkit-appearance: none;
    background: transparent;
    height: 1px;
}

input[type=range]::-webkit-slider-thumb {
    -webkit-appearance: none;
    box-shadow: 0 0 5px #666666;
    background: #666666;
    border-radius: 100%;
    height: 10px;
    width: 10px;
}
&lt;!doctype html&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;title&gt;Page title&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div class="time-progress"&gt;
        &lt;div class="time-elapsed time-label"&gt;
            01:47
        &lt;/div&gt;

        &lt;div class="time-slider"&gt;
            &lt;div class="progress" style="width: 47%;"&gt;&lt;/div&gt;
            &lt;input class="time-range" type="range" /&gt;
        &lt;/div&gt;

        &lt;div class="duration time-label"&gt;
            03:36
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/body&gt;




Edit: The above is for FireFox, I didn't see the Chrome only section; however, it displays correctly in both FF and Chrome, so you may want to consider using it.  It also displays almost correctly in IE, but you should make the track as tall as you want the button to be in this case because the thumb is designed to be no taller than the bar.

To get rid of the position properties in Chrome, you should change the .time-range class to this:

.time-range {
    width: 100%;
}


Delete the position: relative; and the margin: 0 10px; in the .time-slider class.

Add this line to the input[type-range]::-webkit-slider-thumb property:

margin-top: -21px;




*, *:before, *:after {
    box-sizing: border-box;
}

input:focus, button:focus {
    outline: none 
}

.time-progress {
    display: flex;
    align-items: center;
    width: 300px;
    margin-top: 30px;
    margin-left: 30px;
}

.time-label {
    margin: 0 5px;
}

.time-slider {
    background: #ebebeb;
    height: 3px;
    flex: 1;
}

.progress {
    background: #4ea6ea;
    height: 100%;
}

.time-range {
    width: 100%;
}

input[type=range] {
    -webkit-appearance: none;
    background: transparent;
    height: 1px;
}

input[type=range]::-webkit-slider-thumb {
    -webkit-appearance: none;
    box-shadow: 0 0 5px #666666;
    background: #666666;
    border-radius: 100%;
    height: 10px;
    width: 10px;
    margin-top: -18px;
}
&lt;!doctype html&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;title&gt;Page title&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div class="time-progress"&gt;
        &lt;div class="time-elapsed time-label"&gt;
            01:47
        &lt;/div&gt;

        &lt;div class="time-slider"&gt;
            &lt;input class="time-range" type="range" /&gt;
        &lt;/div&gt;

        &lt;div class="duration time-label"&gt;
            03:36
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/body&gt;