<div class='wrap'>
	<input id='r' type='range'/>
</div>
$bg: #3d3d4a;
$fsr: 4;
$p: 39%;
$k: .1;
$t: .5s;
$track-w: 25em;
$track-h: .02*$track-w;
$thumb-d: $k*$track-w;

$chart-d: (1 - 2*$k)*100%;

@mixin track() {
	border: none;
	width: $track-w; height: $track-h;
	border-radius: .5*$track-h;
	background: #343440
}

@mixin thumb() {
	border: none;
	width: $thumb-d; height: $thumb-d;
	border-radius: 50%;
	transform: scale(.7);
	background: #e6323e;
	filter: saturate(.7);
	transition: transform $t linear, filter $t
}

@mixin thumb-focus() {
	transform: none;
	filter: none
}

%thumb-val {
  position: absolute;
  width: $thumb-d; height: $thumb-d;
	opacity: 0;
  color: #fff;
  pointer-events: none;
	transition: opacity $t ease-in-out
}

* { margin: 0 }

body { background: $bg }

.wrap {
	margin: 2em auto;
	width: $track-w;
	font: 2vmin trebuchet ms, arial, sans-serif;
	
	@media (max-width: 500px), 
				 (max-height: 500px) { font-size: 10px }
  @media (min-width: 1600px), 
				 (min-height: 1600px) { font-size: 32px }
	
	&:not(.full) {
		position: relative;
		
		output {
			@extend %thumb-val;
			top: 0;
			transform: translate(calc(var(--val)/100*#{$track-w - $thumb-d}))
		}
	}
	
	&.full {
		position: relative;
		height: $track-w;
		
		[type='range'] {
			display: block;
			transform-origin: 100% 0;
			transform: rotate(-90deg) translatey(-100%);
		}
		
		output {
			width: $chart-d; height: $chart-d;
			border-radius: 50%;
			color: #7a7a7a;
			font-size: $fsr*1em;
			font-weight: 700;
			
			&:before {
				@extend %thumb-val;
				right: 0; bottom: 0;
				transform: translatey(calc(var(--val)/-100*#{$track-w - $thumb-d}));
				line-height: $thumb-d;
				text-align: center;
				font-size: 1em/$fsr;
				font-weight: 200;
				counter-reset: val var(--val);
				content: counter(val)'%'
			}
		}
	}
}

[type='range'] {
	&, &::-webkit-slider-thumb { -webkit-appearance: none }

	padding: 0;
	width: $track-w; height: $thumb-d;
	background: transparent;
	font: inherit;
	cursor: pointer;

	&::-webkit-slider-runnable-track { @include track }
	&::-moz-range-track { @include track }
	&::-ms-track { @include track }

	&::-webkit-slider-thumb {
		margin-top: .5*($track-h - $thumb-d);
		@include thumb
	}
	&::-moz-range-thumb { @include thumb }
	&::-ms-thumb {
		margin-top: 0;
		@include thumb
	}
	
	&::-ms-tooltip { display: none }
	
	+ output {
		display: flex;
		align-items: center;
		justify-content: center;
		background: radial-gradient($bg $p, transparent $p + .5%),
			conic-gradient(#e64c65 calc(var(--val)*1%), #41a8ab 0%);
		
		&:after { content: '%' }
	}
	
	&:focus {
		outline: none;
		
		&::-webkit-slider-thumb { @include thumb-focus }
		&::-moz-range-thumb { @include thumb-focus }
		&::-ms-thumb { @include thumb-focus }
		
		.wrap:not(.full) & + output, 
		.wrap.full & + output:before { opacity: 1 }
	}
}
View Compiled
const _R = document.getElementById('r'), 
			_W = _R.parentNode, 
			_O = document.createElement('output');

let val = null, conic = false;

function update() {
	let newval = +_R.value;

	if(val !== newval) {
		_W.style.setProperty('--val', _O.value = val = newval);
		if(conic) _O.setAttribute('aria-label', `${val}%`)
	}
};

update();

_O.setAttribute('for', _R.id);
_W.appendChild(_O);

if(getComputedStyle(_O).backgroundImage !== 'none') {
	conic = true;
  _W.classList.add('full');
  _O.setAttribute('role', 'img');
	_O.setAttribute('aria-label', `${val}%`)
}

addEventListener('input', update, false);
addEventListener('change', update, false);
View Compiled

External CSS

  1. https://codepen.io/thebabydino/pen/evPbxv.js

External JavaScript

  1. https://codepen.io/thebabydino/pen/evPbxv.js