A gradient is a blend of two or more colors that transition smoothly from one to another. Gradients add modern aesthetics to backgrounds, text, buttons, etc.
In CSS, gradients are added as a value of the background
property. For example, a simple gradient might look like this:
1 |
background: linear-gradient(to right, red, pink); |
Here, we are creating a linear gradient that transitions from red to pink horizontally. You can also set an angle to control the direction of the gradient. Check out this example:
1 |
background: linear-gradient(45deg, red, pink); |
Here, the gradient transitions from red to pink at a 45-degree angle. To learn more about manipulating gradients with CSS, here’s a quick guide:
What we’re creating in this tutorial
In this tutorial, you will use JavaScript and learn how to create a tool that produces all kinds of CSS gradients. Here are the features of the gradient tool:
- A preview element to show the current gradient.
- An option to choose between linear or radial gradients.
- The ability to add and remove colors from the gradient.
- An option to add an angle to the linear gradient.
- Ability to copy the generated gradient code.
By the end of the tutorial, you will have something like this:
HTML: Create the interface
Our gradient tool will have a fairly minimal interface, the markup for which looks like this:
1 |
<div class="container"> |
2 |
<h1>Gradient Generator</h1> |
3 |
<div class="preview"></div> |
4 |
|
5 |
<div class="gradient-type"> |
6 |
<label>
|
7 |
<input type="radio" name="gradient-type" value="linear" checked> Linear |
8 |
</label>
|
9 |
<label>
|
10 |
<input type="radio" name="gradient-type" value="radial"> Radial |
11 |
</label>
|
12 |
</div>
|
13 |
|
14 |
<div class="color-control"> |
15 |
<div class="color-list"> |
16 |
<!-- colors added here -->
|
17 |
</div>
|
18 |
<div class="add-color"> |
19 |
<button class="add-color-btn">+</button> |
20 |
</div>
|
21 |
</div>
|
22 |
<div class="slider-wrapper "> |
23 |
<div class="slider-content"> |
24 |
<span>0°</span> |
25 |
<span id="angle-value">45°</span> |
26 |
<span>360°</span> |
27 |
</div>
|
28 |
<input class="slider" type="range" id="angle" min="0" max="360" value="45" /> |
29 |
</div>
|
30 |
|
31 |
<pre id="output"></pre> |
32 |
<input type="text" name="" class="css-output"> |
33 |
|
34 |
<button class="copy-css"> |
35 |
Copy CSS |
36 |
</button>
|
37 |
</div>
|
CSS: Styling the gradient generator
Let’s style our gradient tool. Below are the styles for the body, container, preview and color stop elements:
1 |
body { |
2 |
display: flex; |
3 |
flex-direction: column; |
4 |
align-items: center; |
5 |
min-height: 100vh; |
6 |
padding: 20px; |
7 |
font-family: "DM Mono", monospace; |
8 |
|
9 |
}
|
10 |
.container { |
11 |
width: 80%; |
12 |
max-width: 600px; |
13 |
display: flex; |
14 |
gap: 20px; |
15 |
flex-direction: column; |
16 |
align-items: center; |
17 |
border-radius: 20px; |
18 |
border: #f3ecec solid 1px; |
19 |
padding: 40px 80px; |
20 |
}
|
21 |
.preview { |
22 |
width: 100%; |
23 |
height: 200px; |
24 |
border-radius: 8px; |
25 |
}
|
26 |
.color-control { |
27 |
display: flex; |
28 |
gap: 25px; |
29 |
padding: 20px; |
30 |
border-radius: 8px; |
31 |
}
|
32 |
.color-list { |
33 |
display: flex; |
34 |
flex-wrap: wrap; |
35 |
gap: 10px; |
36 |
margin-bottom: 15px; |
37 |
}
|
38 |
.color-list input[type="color"] { |
39 |
width: 48px; |
40 |
height: 48px; |
41 |
border: none; |
42 |
border-radius: 8px; |
43 |
padding: 4px; |
44 |
cursor: pointer; |
45 |
}
|
46 |
|
47 |
.color-stop .add-color { |
48 |
width: 60px; |
49 |
height: 60px; |
50 |
}
|
51 |
|
52 |
.add-color-btn { |
53 |
width: 48px; |
54 |
height: 48px; |
55 |
border: none; |
56 |
border-radius: 8px; |
57 |
padding: 4px; |
58 |
cursor: pointer; |
59 |
}
|
Remove color button
To remove a color from the gradient, a delete icon will appear when hovering over any color picker element.
Here are the styles for that:
1 |
.color-stop { |
2 |
position: relative; |
3 |
}
|
4 |
.color-stop:hover .fa-solid.fa-trash-can { |
5 |
opacity: 1; |
6 |
}
|
7 |
|
8 |
.fa-solid.fa-trash-can { |
9 |
position: absolute; |
10 |
opacity: 0; |
11 |
top: -35%; |
12 |
left: calc(100% - 20px); |
13 |
transform: none; |
14 |
background: transparent; |
15 |
font-size: 24px; |
16 |
cursor: pointer; |
17 |
color: red; |
18 |
transition: all 0.3s ease-in-out; |
19 |
}
|
Range input
Range input elements can look and behave differently across browsers. To ensure a consistent appearance, it’s important to customize the CSS to ensure the same experience across multiple browsers. Here are the styles for the range slider element
1 |
.slider-wrapper { |
2 |
display: flex; |
3 |
align-items: center; |
4 |
flex-direction: column; |
5 |
gap: 10px; |
6 |
font-family: Arial, sans-serif; |
7 |
width: 100%; |
8 |
}
|
9 |
.slider-wrapper input[type="range"] { |
10 |
-webkit-appearance: none; |
11 |
appearance: none; |
12 |
width: 100%; |
13 |
height: 10px; |
14 |
background: #e5e7eb; |
15 |
border-radius: 2px; |
16 |
outline: none; |
17 |
cursor: pointer; |
18 |
}
|
19 |
|
20 |
.slider-wrapper input[type="range"]::-webkit-slider-thumb { |
21 |
-webkit-appearance: none; |
22 |
appearance: none; |
23 |
width: 25px; |
24 |
height: 25px; |
25 |
border-radius: 5px; |
26 |
background: #119cec; |
27 |
cursor: pointer; |
28 |
}
|
29 |
|
30 |
.slider-wrapper input[type="range"]::-moz-range-thumb { |
31 |
-webkit-appearance: none; |
32 |
appearance: none; |
33 |
width: 25px; |
34 |
height: 25px; |
35 |
border-radius: 5px; |
36 |
background: #119cec; |
37 |
cursor: pointer; |
38 |
}
|
39 |
|
40 |
.slider-content { |
41 |
display: flex; |
42 |
justify-content: space-between; |
43 |
width: 100%; |
44 |
}
|
Remaining styles
The rest of the styles will look like this:
1 |
.slider-content { |
2 |
display: flex; |
3 |
justify-content: space-between; |
4 |
width: 100%; |
5 |
}
|
6 |
|
7 |
#output { |
8 |
color: #000; |
9 |
width: 100%; |
10 |
height: 80px; |
11 |
padding: 15px; |
12 |
border: 1px solid #e7e2e2; |
13 |
border-radius: 12px; |
14 |
}
|
15 |
|
16 |
.css-output { |
17 |
display: none; |
18 |
}
|
19 |
|
20 |
.copy-css { |
21 |
color: #fff; |
22 |
width: 100%; |
23 |
font-size: 1.2rem; |
24 |
width: 100%; |
25 |
height: 45px; |
26 |
background-color: #119cec; |
27 |
border-radius: 8px; |
28 |
font-weight: 800; |
29 |
border: none; |
30 |
}
|
31 |
pre { |
32 |
white-space: pre-wrap; |
33 |
word-wrap: break-word; |
34 |
}
|
JavaScript: Construct gradient
The first step as always is to get all the elements that need manipulation.
1 |
const slider = document.getElementById("angle"); |
2 |
const sliderValue = document.getElementById("angle-value"); |
3 |
const addColorBtn = document.querySelector(".add-color-btn"); |
4 |
const gradientTypeInputs = document.querySelectorAll('input[name="gradient-type"]'); |
5 |
const sliderContainer = document.querySelector('.slider-wrapper'); |
Let’s define the colors for the initial gradient preview.
1 |
let colors = ['#d81848', '#fd26ae', '#0c43c6']; |
The colors
array will serve as the source of truth for all the gradient colors. All gradients will be generated based on the colors in this array, so we will be adding and removing colors from it .
To add a a gradient to the preview element, apply a gradient transition using the colors from the colors
array.
1 |
const updateGradient = () => { |
2 |
let gradientString; |
3 |
const angle = document.getElementById("angle").value; |
4 |
const gradientType = document.querySelector('input[name="gradient-type"]:checked').value; |
5 |
console.log(gradientType); |
6 |
|
7 |
if (gradientType === 'linear') { |
8 |
gradientString = `linear-gradient(${angle}deg, ${colors.join(", ")})`; |
9 |
} else { |
10 |
gradientString = `radial-gradient(circle, ${colors.join(", ")})`; |
11 |
}
|
12 |
|
13 |
const gradientPreview = document.querySelector(".preview"); |
14 |
gradientPreview.style.background = gradientString; |
15 |
document.getElementById( |
16 |
"output" |
17 |
).textContent = `.gradient {\n background: ${gradientString};\n}`; |
18 |
};
|
Here, we are setting the background of the preview container to either a linear
or radial
background depending on the user selection. We are also updating the output to show the code used to generate the gradient.
By default, the linear gradient will be shown because the linear option is checked in the HTML. Additionally, the angle will default to the slider’s default value (45 degrees).
The generated CSS will look like this:
1 |
.gradient {background: linear-gradient(45deg, #d81848, #fd26ae, #0c43c6);} |
Updating values
To ensure the gradient type is updated when the user selects the radial option, let’s add event listeners to the gradient type inputs (input[name="gradient-type"]
). This will ensure the generated gradient and code respond to user actions.
1 |
gradientTypeInputs.forEach(input => { |
2 |
input.addEventListener('change', () => { |
3 |
updateGradient(); |
4 |
});
|
5 |
});
|
The next feature is to hide the range slider when the radial gradient option is selected.
1 |
function toggleAngleSlider() { |
2 |
const gradientType = document.querySelector('input[name="gradient-type"]:checked').value; |
3 |
sliderContainer.style.display = gradientType === 'linear' ? 'block' : 'none'; |
4 |
}
|
The toggleAngleSlider()
function will be called every time there is a change in gradient selection.
1 |
gradientTypeInputs.forEach(input => { |
2 |
input.addEventListener('change', () => { |
3 |
updateGradient(); |
4 |
toggleAngleSlider(); |
5 |
});
|
6 |
});
|
Update gradient on user selection
We now have a predefined gradient, but we want to allow the user to make their gradient by selecting custom colors. To achieve this, we will display the colors in the colors
array as color picker elements.
1 |
function initializeGradient() { |
2 |
const colorList = document.querySelector(".color-list"); |
3 |
colorList.innerHTML = ""; |
4 |
colors.forEach((color, index) => { |
5 |
const colorStop = document.createElement("div"); |
6 |
colorStop.className = "color-stop"; |
7 |
|
8 |
const colorInput = document.createElement("input"); |
9 |
colorInput.type = "color"; |
10 |
colorInput.className = "color-input"; |
11 |
colorInput.value = color; |
12 |
colorInput.dataset.index = index; |
13 |
colorInput.addEventListener("input", (e) => |
14 |
updateColor(e.target.dataset.index, e.target.value) |
15 |
);
|
16 |
|
17 |
const removeButton = document.createElement("i"); |
18 |
removeButton.className = "fa-solid fa-trash-can"; |
19 |
|
20 |
colorStop.appendChild(colorInput); |
21 |
colorStop.appendChild(removeButton); |
22 |
colorList.appendChild(colorStop); |
23 |
});
|
The main purpose of this function is to dynamically create color picker elements in the UI based on the colors array. For each color in the array, we are creating a native <input type="color">
element allowing users to select custom gradient colors.
In addition to creating color pickers, we have also added a remove icon to each input element to ensure a color can be removed from the gradient.
We have also attached an event listener that listens for any changes in each color picker element. When an input change occurs, the updateColor()
function is invoked. Add the updateColor()
function.
1 |
function updateColor(index, color) { |
2 |
colors[index] = color; |
3 |
updateGradient(); |
4 |
}
|
This function will get the current index and update the color at that index to the newly selected color; This ensures the gradient is updated to reflect the selected colors.
Now, the user can choose custom colors for their gradient.
Add and remove colors from a gradient
Next to the color pickers, there’s a + button for adding new colors.
To enable its functionality, we need to add an event listener to the button so that when the button is clicked, it will trigger the addition of a new color to the colors
array.
1 |
function addColorStop() { |
2 |
if (colors.length >= 6) { |
3 |
alert("Maximum 6 colors allowed!"); |
4 |
return; |
5 |
}
|
6 |
colors.push("#ffffff"); |
7 |
initializeGradient(); |
8 |
}
|
To remove a color from the gradient, we simply remove it from the array and reinitialize the gradient. Reinitializing the gradient will create a new gradient using the updated colors
array.
1 |
function removeColorStop(index) { |
2 |
if (colors.length > 2) { |
3 |
colors.splice(index, 1); |
4 |
initializeGradient(); |
5 |
} else { |
6 |
alert("Minimum 2 colors required!"); |
7 |
}
|
8 |
}
|
As you can see, when adding and removing colors to the gradient, we also need to ensure the user can’t add more than 6 colors and that there must be at least 2 colors to create a gradient.
Copy generated gradient code
The last feature is to add the ability to copy the generated code. We will add an event listener to the copy CSS button. When a user clicks the button the generated code will be copied to the clipboard.
1 |
const copyCssBtn = document.querySelector(".copy-css"); |
2 |
copyCssBtn.addEventListener("click", () => { |
3 |
const gradientCode = document.getElementById("output") |
4 |
|
5 |
navigator.clipboard |
6 |
.writeText(gradientCode.textContent) |
7 |
.then(() => alert("CSS copied to clipboard!")) |
8 |
.catch((err) => console.error("Failed to copy: ", err)); |
9 |
});
|
10 |
})
|
Here is the final demo! Have fun creating your gradients
Conclusion
We have created a (pretty epic) fully functional gradient tool. Now you can add your own eye catching gradients to your designs!