DEV Community

Cover image for TIL - HTML Slider
James Cox
James Cox

Posted on • Updated on

TIL - HTML Slider

#TIL

Yesterday I wrote about HTML's native color picker. Today I learned about HTML's native slider element, which looks like <input type="range">.

Once again I crafted a nifty Codesandbox 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.

The Code

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

<input
  type="range"
  min="0"
  max="100"
  value={firstPercentage}
  onChange={selectfirstPercentage}
/>
Enter fullscreen mode Exit fullscreen mode
  • 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.
// initialize to 0 based on how CSS gradient is defined
const [firstPercentage, setFirstPercentage] = useState(0);

...

const selectfirstPercentage = (e) => {
  setFirstPercentage(e.target.value);
};
Enter fullscreen mode Exit fullscreen mode

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

// 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}
/>
Enter fullscreen mode Exit fullscreen mode

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

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

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

The Entire Component

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>
  );
}
Enter fullscreen mode Exit fullscreen mode

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...

Top comments (0)