Range Slider React hover, pressed and focus - javascript

I have a range slider made with React(Babel) and CSS. I am trying to figure out how to add hover, active and focus effects(Changing the color of the thumb and left side of the slider). I have tried directly adding :hover to input[type='range']::-webkit-slider-thumb but that doesn't work. I believe my main issue is stemming from the fact that the left part of the slider is styled with a box-shadow but I haven't found any other ways to handle this in documentation or Googling. Any help or suggestions are appreciated!
HTML:
<div id="root"></div>
CSS:
input[type='range'] {
-webkit-appearance: none;
background-color: #ddd;
height: 10px;
overflow: hidden;
width: 300px;
border-radius: 5px;
outline: none;
}
input[type='range']::-webkit-slider-runnable-track {
-webkit-appearance: none;
height: 10px;
}
input[type='range']::-webkit-slider-thumb {
-webkit-appearance: none;
background: #333;
border-radius: 50%;
box-shadow: -205px 0 0 200px red;
cursor: pointer;
height: 10px;
width: 10px;
border: 0;
}
input[type='range']::-moz-range-thumb {
background: #333;
border-radius: 50%;
box-shadow: -1005px 0 0 1000px red;
cursor: pointer;
height: 10px;
width: 10px;
border: 0;
}
input[type="range"]::-moz-range-track {
background-color: #ddd;
}
input[type="range"]::-moz-range-progress {
background-color: red;
height: 10px
}
input[type="range"]::-ms-fill-upper {
background-color: #ddd;
}
input[type="range"]::-ms-fill-lower {
background-color: red;
}
JavaScript(Babel)
class VolumeSlider extends React.Component {
constructor() {
super();
this.state = {
value: 12.5
};
}
onUpdate(e) {
this.setState({
value: e.target.value
});
}
render() {
return (
<div className="mb1">
<input
className="c-input--range"
list="tickmarks"
max={100}
onChange={(e) => this.onUpdate(e)}
step={0.1}
type="range"
value={this.state.value}
/>
<div>
<label className="c-label">{this.state.value}</label>
</div>
</div>
);
}
}
ReactDOM.render(
<div>
<VolumeSlider />
</div>,
document.getElementById("root")
);
Code also provided in CodePen below. Thank you!
https://codepen.io/kcandle/pen/KKMrZKo

You want to assign variables for the colors of the box-shadow
input[type='range']::-webkit-slider-thumb {
-webkit-appearance: none;
--slider-thumb-background-color: #000;
background: var(--slider-thumb-background-color);
border-radius: 50%;
--box-shadow-color: orange;
box-shadow: -205px 0 0 200px var(--box-shadow-color);
cursor: pointer;
height: 10px;
width: 10px;
--border-color: orange;
border: 3px solid var(--border-color);
}
input[type='range']::-webkit-slider-thumb:hover {
--slider-thumb-background-color: grey;
--box-shadow-color: red;
--border-color: red;
}
input[type='range']::-webkit-slider-thumb:active {
--slider-thumb-background-color: white;
--box-shadow-color: blue;
--border-color: blue;
}

Related

How to change onClick button in knockoutjs

I have a html with some css:
<label class="label-checkbox">
<input type="checkbox" data-bind="click: clickedMultipleServicesButton, checked: checkedMultipleServicesButton, css: {checked: true}">
<span style="font-size:14px !important">Test Button</span>
</label>
<style>
label.label-checkbox {
cursor: pointer;
}
label.label-checkbox input {
position: absolute;
top: 0;
left: 0;
visibility: hidden;
pointer-events: none;
}
label.label-checkbox span {
padding: 8px 11px;
border: 1px solid #ccc;
display: inline-block;
color: #ffffff;
border-radius: 6px;
margin: 7px;
background: #253965;
user-select: none;
}
label.label-checkbox input:checked + span {
box-shadow: inset 1px 2px 5px #777;
transform: translateY(1px);
background: #ffd800;
}
</style>
It works when I remove data-bindings. On click it colors the blue button a yellow one and opposite.
But however, when I add data-binding: click it doesnt work anymore.
I assume that I need to dynamically attach css classes on click event?
Desired behavior:
I want to have data-bind="click: someFunction" but when I click, to have css behavior, and to have function that will catch when is the button checked, and when it is not.
Yes I'm not sure how to manipulate pseudo-classes in the knockout but you can dynamically add and remove CSS class:
<label class="label-checkbox" >
<input type="checkbox" data-bind="click: clickedMultipleServicesButton, css: checkedMultipleServicesButton() && 'checked'"/>
<span style="font-size:14px !important">Test Button</span>
</label>
<style>
label.label-checkbox {
cursor: pointer;
}
label.label-checkbox input {
position: absolute;
top: 0;
left: 0;
visibility: hidden;
pointer-events: none;
}
label.label-checkbox span {
padding: 8px 11px;
border: 1px solid #ccc;
display: inline-block;
color: #ffffff;
border-radius: 6px;
margin: 7px;
background: #253965;
user-select: none;
}
label.label-checkbox input.checked + span {
box-shadow: inset 1px 2px 5px #777;
transform: translateY(1px);
background: #ffd800;
}
</style>
note that I turned your input:checked into input.checked.
Code in the view model:
self.checkedMultipleServicesButton = ko.observable(false);
self.clickedMultipleServicesButton = function (e) {
self.checkedMultipleServicesButton(!self.checkedMultipleServicesButton());
}

How to customize Input slider to make volume bar

I'm trying to make volume bar with input slider with styled-components.
I could find many useful information but cannot find about how to customize valued area.
For example, if I set volume as 80, default html input range color from 0 to 80 blue. I want to change this color but couldn't find any information about it. When I set -webkit-appearance: none; I could find it becomes transparent but I just want to change colors of it. (Not the background. I know I can do that with background).
edit) This is my code
const StyledTrackVolumeSlide = styled.input`
width: 100%;
// -webkit-appearance: none; I know this code will reset default css
background: #555;
height: 0.25em;
outline: none;
&::-webkit-slider-thumb {
-webkit-appearance: none;
}
I tried these properties, but could not find one with the blue valued background color. And also cannot find in chrome dev tools. Tried all the stuffs from here
&::-webkit-slider-thumb{
}
&:focus{
}
&::-ms-track{
}
Is there any possible way to customize input slider's valued color with plain CSS?
Check out this tool: https://toughengineer.github.io/demo/slider-styler
Among other things it allows to style progress indication.
To make the slider vertical you'll have to use CSS transform, though.
Here is an example:
for (let e of document.querySelectorAll('input[type="range"].slider-progress')) {
e.style.setProperty('--value', e.value);
e.style.setProperty('--min', e.min == '' ? '0' : e.min);
e.style.setProperty('--max', e.max == '' ? '100' : e.max);
e.addEventListener('input', () => e.style.setProperty('--value', e.value));
}
/*generated with Input range slider CSS style generator (version 20201223)
https://toughengineer.github.io/demo/slider-styler*/
input[type=range].styled-slider {
height: 2.2em;
-webkit-appearance: none;
}
/*progress support*/
input[type=range].styled-slider.slider-progress {
--range: calc(var(--max) - var(--min));
--ratio: calc((var(--value) - var(--min)) / var(--range));
--sx: calc(0.5 * 2em + var(--ratio) * (100% - 2em));
}
input[type=range].styled-slider:focus {
outline: none;
}
/*webkit*/
input[type=range].styled-slider::-webkit-slider-thumb {
width: 2em;
height: 2em;
border-radius: 1em;
background: #007cf8;
border: none;
box-shadow: 0 0 2px black;
margin-top: calc(max((1em - 1px - 1px) * 0.5,0px) - 2em * 0.5);
-webkit-appearance: none;
}
input[type=range].styled-slider::-webkit-slider-runnable-track {
height: 1em;
border-radius: 0.5em;
background: #efefef;
border: 1px solid #b2b2b2;
box-shadow: none;
}
input[type=range].styled-slider::-webkit-slider-thumb:hover {
background: #0061c3;
}
input[type=range].styled-slider:hover::-webkit-slider-runnable-track {
background: #e5e5e5;
border-color: #9a9a9a;
}
input[type=range].styled-slider::-webkit-slider-thumb:active {
background: #2f98f9;
}
input[type=range].styled-slider:active::-webkit-slider-runnable-track {
background: #f5f5f5;
border-color: #c1c1c1;
}
input[type=range].styled-slider.slider-progress::-webkit-slider-runnable-track {
background: linear-gradient(#007cf8,#007cf8) 0/var(--sx) 100% no-repeat, #efefef;
}
input[type=range].styled-slider.slider-progress:hover::-webkit-slider-runnable-track {
background: linear-gradient(#0061c3,#0061c3) 0/var(--sx) 100% no-repeat, #e5e5e5;
}
input[type=range].styled-slider.slider-progress:active::-webkit-slider-runnable-track {
background: linear-gradient(#2f98f9,#2f98f9) 0/var(--sx) 100% no-repeat, #f5f5f5;
}
/*mozilla*/
input[type=range].styled-slider::-moz-range-thumb {
width: 2em;
height: 2em;
border-radius: 1em;
background: #007cf8;
border: none;
box-shadow: 0 0 2px black;
}
input[type=range].styled-slider::-moz-range-track {
height: max(calc(1em - 1px - 1px),0px);
border-radius: 0.5em;
background: #efefef;
border: 1px solid #b2b2b2;
box-shadow: none;
}
input[type=range].styled-slider::-moz-range-thumb:hover {
background: #0061c3;
}
input[type=range].styled-slider:hover::-moz-range-track {
background: #e5e5e5;
border-color: #9a9a9a;
}
input[type=range].styled-slider::-moz-range-thumb:active {
background: #2f98f9;
}
input[type=range].styled-slider:active::-moz-range-track {
background: #f5f5f5;
border-color: #c1c1c1;
}
input[type=range].styled-slider.slider-progress::-moz-range-track {
background: linear-gradient(#007cf8,#007cf8) 0/var(--sx) 100% no-repeat, #efefef;
}
input[type=range].styled-slider.slider-progress:hover::-moz-range-track {
background: linear-gradient(#0061c3,#0061c3) 0/var(--sx) 100% no-repeat, #e5e5e5;
}
input[type=range].styled-slider.slider-progress:active::-moz-range-track {
background: linear-gradient(#2f98f9,#2f98f9) 0/var(--sx) 100% no-repeat, #f5f5f5;
}
/*ms*/
input[type=range].styled-slider::-ms-fill-upper {
background: transparent;
border-color: transparent;
}
input[type=range].styled-slider::-ms-fill-lower {
background: transparent;
border-color: transparent;
}
input[type=range].styled-slider::-ms-thumb {
width: 2em;
height: 2em;
border-radius: 1em;
background: #007cf8;
border: none;
box-shadow: 0 0 2px black;
margin-top: 0;
box-sizing: border-box;
}
input[type=range].styled-slider::-ms-track {
height: 1em;
border-radius: 0.5em;
background: #efefef;
border: 1px solid #b2b2b2;
box-shadow: none;
box-sizing: border-box;
}
input[type=range].styled-slider::-ms-thumb:hover {
background: #0061c3;
}
input[type=range].styled-slider:hover::-ms-track {
background: #e5e5e5;
border-color: #9a9a9a;
}
input[type=range].styled-slider::-ms-thumb:active {
background: #2f98f9;
}
input[type=range].styled-slider:active::-ms-track {
background: #f5f5f5;
border-color: #c1c1c1;
}
input[type=range].styled-slider.slider-progress::-ms-fill-lower {
height: max(calc(1em - 1px - 1px),0px);
border-radius: 0.5em 0 0 0.5em;
margin: -1px 0 -1px -1px;
background: #007cf8;
border: 1px solid #b2b2b2;
border-right-width: 0;
}
input[type=range].styled-slider.slider-progress:hover::-ms-fill-lower {
background: #0061c3;
border-color: #9a9a9a;
}
input[type=range].styled-slider.slider-progress:active::-ms-fill-lower {
background: #2f98f9;
border-color: #c1c1c1;
}
<input type="range" class="styled-slider slider-progress" style="width: 25em;" />
<br />
<!--this div is needed to cut off all that's not needed, you have to specify width explicitly-->
<div style="display: inline-block; width: 2.2em; overflow: hidden;">
<!--this div catches the size of the child block-->
<div style="display: inline-block;">
<!--this div sizes itself to the width of the <input> and makes itself square, also rotates contents-->
<div style="display: inline-block; height: 0; padding: 0 0 100% 0; transform: rotate(-90deg);">
<!--style <input> as usual as if it is horizontal-->
<input type="range" class="styled-slider slider-progress" style="width: 10em;" />
</div>
</div>
</div>
more content to the right of the vertical slider
"default html input range color" doesn't exist, the element is rendered by your browser.
You must specify -webkit-appearance: none; (depends browser), for telling to the browser "don't design the input, I take care of that".
another tutorial
Sadly you must recreate input element, you can't just override color.

Enable only one masonry tile open at a time

I have a masonry layout (using the library from here), that when a user clicks a tile, only one tile should be able to expand at a time. If the user clicks another tile, the previously opened tile should close. How can I check for any previously opened tiles, close them, and then open the newly selected tile?
// external js: masonry.pkgd.js
var grid = document.querySelector('.grid');
var msnry = new Masonry( grid);
grid.addEventListener( 'click', function( event ) {
// don't proceed if item was not clicked on
if ( !matchesSelector( event.target, '.grid-item' ) ) {
return;
}
// change size of item via class
event.target.classList.toggle('grid-item--gigante');
// trigger layout
msnry.layout();
});
.grid {
background: #eee;
width: 1200px;
margin: 0 auto;
}
.grid-holder {
background: #fff;
margin: 0 auto;
display: block;
}
.grid-item {
width: 375px;
height: 375px;
margin-bottom: 4%;
float: left;
border: 1px solid #ddd;
margin-right: 10px;
background-color: #eee;
box-shadow: 2px 2px 2px 2px #eee;
}
.grid-item--gigante {
max-width: 600px;
min-width: 100px;
width: 63%;
min-height: 375px;
height: auto;
margin-left: 8px;
background-color: rgba(215, 210, 203, 0.3) !important;
color: #666;
border: 1px solid #ddd;
padding: 0.5% 8% 2.5% 5%;
z-index: 2; /* above other items */
}
.grid-item:hover {
background: #a2c;
border-color: white;
cursor: pointer;
}
<script src="https://masonry.desandro.com/masonry.pkgd.js"></script>
<div class="grid">
<div class="grid-holder">
<div class="grid-item">Jim</div>
<div class="grid-item">Joe</div>
<div class="grid-item">John</div>
<div class="grid-item">James</div>
<div class="grid-item">Jack</div>
<div class="grid-item">Joseph</div>
</div>
</div>
You need to keep a reference to previously enlarged grid item.
Whenever the click event occurs, check if current event target is equal to previously enlarged grid item or not. If it is not, remove .grid-item--gigante class from previously enlarged grid item and update the reference to previously enlarged grid item to now point to event.target.
P.S. removed some CSS to make the example code snippet easy to understand.
var grid = document.querySelector('.grid');
var msnry = new Masonry(grid);
var previouslyEnlarged;
grid.addEventListener('click', function(event) {
if ( !matchesSelector( event.target, '.grid-item' ) ) {
return;
}
if (previouslyEnlarged == event.target) {
return;
} else if (previouslyEnlarged) {
previouslyEnlarged.classList.remove('grid-item--gigante');
}
previouslyEnlarged = event.target;
event.target.classList.toggle('grid-item--gigante');
msnry.layout();
});
.grid-holder {
background: #fff;
margin: 0 auto;
display: block;
}
.grid-item {
width: 50px;
height: 50px;
margin-bottom: 4%;
float: left;
border: 1px solid #ddd;
margin-right: 10px;
background-color: #eee;
box-shadow: 2px 2px 2px 2px #eee;
}
.grid-item--gigante {
width: 100px;
height: 100px;
margin-left: 8px;
background-color: rgba(215, 210, 203, 0.3) !important;
color: #666;
border: 1px solid #ddd;
padding: 0.5% 8% 2.5% 5%;
z-index: 2;
}
.grid-item:hover {
background: #a2c;
border-color: white;
cursor: pointer;
}
<script src="https://masonry.desandro.com/masonry.pkgd.js"></script>
<div class="grid">
<div class="grid-holder">
<div class="grid-item">Jim</div>
<div class="grid-item">Joe</div>
<div class="grid-item">John</div>
<div class="grid-item">James</div>
<div class="grid-item">Jack</div>
<div class="grid-item">Joseph</div>
</div>
</div>

Vertically align div with another div [duplicate]

This question already has answers here:
CSS vertical alignment of inline/inline-block elements
(4 answers)
Closed 5 years ago.
divs out of alignment
These are inline-block divs that are dynamically added with varying lengths of text.
I tried setting the same height for divs, setting the same line-height for the texts and also padded texts so their lengths are the same, but theses divs are still mis-aligned.
Is there a css trick or JS hack for this? Thanks.
Scss:
.cards-container {
border: 1px solid white;
margin: auto;
margin-top: 2em;
width: 80%;
.transition-wrapper {
border: 1px solid yellow;
display: inline-block;
margin: 0.2em;
width: $card-width + 10;
height: $card-height + 10;
.card-wrapper {
position: relative;
border: 1px solid grey;
border-radius: 2px;
width: $card-width;
height: $card-height;
margin: auto;
top: 50%;
transform: translateY(-$card-height / 2);
.stock-card {
text-align: center;
border-left: 3px solid $hacker-green;
border-top-left-radius: 1px;
border-bottom-left-radius: 1px;
width: $card-width;
height: $card-height * .975;
transition: all 0.3s ease;
color: white;
&:hover {
border-left: 5px solid red;
border-top-left-radius: 1px;
border-bottom-left-radius: 2px;
}
.stock-symbol-wrapper {
border: 1px solid blue;
height: $card-height * .975 * (1/4);
}
.stock-name-wrapper {
border: 1px solid red;
height: $card-height * .975 * (3/4);
}
}
.stock-card > * {
vertical-align: middle;
}
.icon {
position: absolute;
top: 0;
right: 0;
&:hover {
cursor: pointer;
}
}
}
}
}
Jsx
<div className='cards-container'>
{stockInfo.map((si, i) => {
const sym = si[0];
const name = si[1];
return (<div className='transition-wrapper' onMouseEnter={(evt) => {registerCardSymbol(evt); toggleIcon()}}
onMouseLeave={(evt) => {deregisterCardSymbol(evt); toggleIconOff()}} id={sym} key={i} >
<Transition animation='fade up' duration={300} transitionOnMount={true}>
<div className='card-wrapper'>
<div className='stock-card' id={sym} >
<div className='stock-symbol-wrapper'>{sym}</div>
<div className='stock-name-wrapper'>{name}</div>
{icon && (cardSymbol === sym) ? <Icon onClick={(evt) => {removeStock(evt); /*registerCardSymbol(evt); toggleIcon()*/}}
id={sym} className='icon' color='grey' name='delete'></Icon> : ''}
</div>
</div>
</Transition>
</div>)
})}
</div>
Use vertical-align: top to align inline-blocks along their top border (by default they are aligned along their baseline, which is the last line of text in there).

how to fill background on sliding the range slider

function myValue(val) {
document.getElementById('inputVal').innerHTML=val;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 10px;
cursor: pointer;
background: red;
border-radius: 1.3px;
border: 0.2px solid #010101;
}
input[type=range]::-webkit-slider-thumb {
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
border: 1px solid #000000;
height: 36px;
width: 16px;
border-radius: 3px;
background: #e7ffff;
cursor: pointer;
-webkit-appearance: none;
margin-top: -5px;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 8.4px;
cursor: pointer;
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
background: #3071a9;
border-radius: 1.3px;
border: 0.2px solid #010101;
}
<html>
<head>
</head>
<body>
<div>
<input type = "range" min = "10" max = "100" step = "1" onchange="myValue(this.value);" oninput="myValue(this.value)">
<div id = "inputVal"></div>
</div>
<body>
</html>
I am using simple input range by html. i can modify track and thumb But i want to fill color of track on moving thumb in forward direction and remove color on moving backside. How i can do this ?
You could use the JQuery Slider to get the same result.
CSS:
#red {
float: left;
clear: left;
width: 300px;
margin: 15px;
}
#red .ui-slider-range { background: #ef2929; }
HTML:
<body >
<div id="red"></div>
<div id="va"></div>
</body>
JS JQUERY:
function getval()
{
document.getElementById("va").innerHTML = $( "#red" ).slider( "option", "value" );
}
$(function() {
$( "#red").slider({
orientation: "horizontal",
range: "min",
max: 100,
value: 10,
slide : getval
});
});
JSFiddle: https://jsfiddle.net/6h49upte/
Also refer to the JQuery Slider API and examples its easy to implement. Check out the supported version of Jquery too.
To my knowlege you can only do this in Internet Explorer:
input[type="range"]::-ms-fill-lower {
background: blue;
}
input[type="range"]::-ms-fill-upper {
background: red;
}
<input type="range" min="10" max="100" step="1">

Categories