TIL - HTML Slider
Tags: html, beginners, tutorial, react
Published: 2021-05-12 16:14:47

# #TIL

Yesterday I wrote about [HTML's native color picker](https://dev.to/jamesncox/html-s-color-picker-4ej3). Today I learned about [HTML's native slider](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/range) element, which looks like `<input type="range">`.

Once again I crafted a nifty [Codesandbox](https://txo4v.csb.app/) to demonstrate how to incorporate a slider into a background gradient generator. 

> While it is mobile responsive, and works as intended here, it's a better UX on a full screen. Click "Open in New Window" in the upper right-hand corner of the embedded Codesandbox below. 

{% codesandbox txo4v %}

## The Code

My `input` element for the first color slider looks like this.

```javascript
<input
  type="range"
  min="0"
  max="100"
  value={firstPercentage}
  onChange={selectfirstPercentage}
/>
```
* `type="range"` is how we define what type of input we want. A slider!
* `min="0"` is the minimum value the slider will allow a user to select.
* `max="100"` is the maximum value the slider will allow a user to select. 
* `value={firstPercentage}` is a variable held in state that gets updated by the next line of code:
* `onChange={selectFirstPercentage}` listens for user input and updates state with `selectFirstPercentage`.

```javascript
// initialize to 0 based on how CSS gradient is defined
const [firstPercentage, setFirstPercentage] = useState(0);

...

const selectfirstPercentage = (e) => {
  setFirstPercentage(e.target.value);
};
```

And the code for the second percentage slider is exactly the same, except everything refers to `secondPercentage` and `setSecondPercentage`.

```javascript
// initialize to 100 based on how CSS gradient is defined
const [secondPercentage, setSecondPercentage] = useState(100);

...

const selectSecondPercentage = (e) => {
  setSecondPercentage(e.target.value);
};

...

<input
  type="range"
  min="0"
  max="100"
  value={firstPercentage}
  onChange={selectfirstPercentage}
/>
```

And I use the slider values of `firstPercentage` and `secondPercentage` to update the `<div>` that holds the actual gradient.

```javascript
<div
  className="gradient-div"
  style={{ background: `linear-gradient(to ${direction}, ${firstColor} ${firstPercentage}%, ${secondColor} ${secondPercentage}%)`}}
/>
```

Pretty cool, right?! And not too difficult to use at all!

## The Entire Component

```javascript
import "./styles.css";
import { useState } from "react";

const directions = [
  { type: "Right" },
  { type: "Top" },
  { type: "Bottom" },
  { type: "Left" }
];

export default function App() {
  const [firstColor, setFirstColor] = useState("#1595d5");
  const [secondColor, setSecondColor] = useState("#eb3dbc");
  const [firstPercentage, setFirstPercentage] = useState(0);
  const [secondPercentage, setSecondPercentage] = useState(100);
  const [selectedDirection, setSelectedDirection] = useState("Right");
  const [direction, setDirection] = useState("right");

  const selectFirstColor = (e) => {
    setFirstColor(e.target.value);
  };

  const selectSecondColor = (e) => {
    setSecondColor(e.target.value);
  };

  const selectfirstPercentage = (e) => {
    setFirstPercentage(e.target.value);
  };

  const selectSecondPercentage = (e) => {
    setSecondPercentage(e.target.value);
  };

  const toggleDirection = (e) => {
    setSelectedDirection(e.target.id);
    setDirection(e.target.value);
  };

  return (
    <div className="App">
      <div className="main-wrapper">
        <h1>Gradient Playground</h1>

        <div className="flex-wrapper">
          <div className="color-select-bg">
            <h2 htmlFor="firstColor">First Color</h2>
            <input
              type="color"
              id="firstColor"
              name="firstColor"
              value={firstColor}
              onChange={selectFirstColor}
            />
            <div className="flex-wrapper">
              <input
                type="range"
                min="0"
                max="100"
                value={firstPercentage}
                onChange={selectfirstPercentage}
              />
              <p>{firstPercentage}%</p>
            </div>
          </div>

          <div className="color-select-bg">
            <h2 htmlFor="secondColor">Second Color</h2>
            <input
              type="color"
              id="secondColor"
              name="secondColor"
              value={secondColor}
              onChange={selectSecondColor}
            />
            <div className="flex-wrapper">
              <input
                type="range"
                min="0"
                max="100"
                value={secondPercentage}
                onChange={selectSecondPercentage}
              />
              <p>{secondPercentage}%</p>
            </div>
          </div>
        </div>

        <h2 htmlFor="secondColor">Gradient Direction</h2>
        <div>
          {directions.map(({ type }) => (
            <button
              key={type}
              id={type}
              value={type.toLowerCase()}
              onClick={toggleDirection}
              className={
                type === selectedDirection
                  ? "selected-direction-btn"
                  : "direction-btn"
              }
            >
              {type}
            </button>
          ))}
        </div>

        <div
          className="gradient-div"
          style={{
            background: `linear-gradient(to ${direction}, ${firstColor} ${firstPercentage}%, ${secondColor} ${secondPercentage}%)`
          }}
        />

        <h2>The CSS</h2>
        <div className="css-wrapper">
          <p className="css">
            background-image: linear-gradient(to {direction}, {firstColor}{" "}
            {firstPercentage}%, {secondColor} {secondPercentage}%);
          </p>
        </div>
      </div>
    </div>
  );
}
```
## Conclusion

HTML gives us so many useful tools that solve what can seem like big problems. Learning how to incorporate those into fun and interactive projects like this gradient playground has been a blast! I hope you learned something like I did, and feel empowered to try this yourself!

Thanks for reading and as always, I welcome feedback, corrections, criticism, whatever!

Until next time...