To build our page configurator, we’ll combine old-school CSS techniques with modern CSS features like custom properties and container queries.
Without further ado, let’s take a look at the final project. Click the setting icon to the left of the screen to access the controls panel:
Begin by defining a toggle button and the panel configurator. Inside the panel, we’ll place five form wrappers—we’ll go over each of them later.
Here’s the starting markup:
1 |
|
2 |
class="fa-solid fa-screwdriver-wrench" aria-hidden="true">
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
Purely for stylistic reasons, we’ll include the Font Awesome icon library in our project.
By default, the configurator panel will sit off-screen. As soon as we click the button, it’ll glide smoothly from the left side.
Here are the related styles:
1 |
/*CUSTOM VARIABLES HERE*/
|
2 |
|
3 |
.btn-toggle-panel, |
4 |
.panel { |
5 |
position: fixed; |
6 |
left: 10px; |
7 |
z-index: 1; |
8 |
color: var(--vampire-black); |
9 |
background: var(--anti-flash-white); |
10 |
}
|
11 |
|
12 |
.btn-toggle-panel { |
13 |
top: 10px; |
14 |
font-size: 18px; |
15 |
width: 54px; |
16 |
height: 54px; |
17 |
border-radius: 50%; |
18 |
}
|
19 |
|
20 |
.panel { |
21 |
top: 70px; |
22 |
font-size: 16px; |
23 |
line-height: normal; |
24 |
padding: 30px 20px; |
25 |
border-radius: 30px; |
26 |
transform: translateX(calc(-100% - 10px)); |
27 |
transition: transform 0.4s; |
28 |
}
|
29 |
|
30 |
.panel.show { |
31 |
transform: none; |
32 |
}
|
And the associated JavaScript code:
1 |
const togglePanelBtn = document.querySelector(".btn-toggle-panel"); |
2 |
const panel = document.querySelector(".panel"); |
3 |
|
4 |
togglePanelBtn.addEventListener("click", function () { |
5 |
panel.classList.toggle("show"); |
6 |
});
|
Let’s now discuss in more detail what customization options our configurator will allow.
For simplicity, we’ll skip most of the CSS stuff and show only the essential parts.
By default, the project will use the Arial font family. However, we can opt for one of the following Google Fonts:
Note that we won’t download all fonts together but upon request by following the Google Fonts API. That’s why you’ll see an instant flickering happen the first time you select a new font. You can check the downloaded font files in your browser’s Network tab.
The HTML part:
1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
The JavaScript part:
1 |
const html = document.documentElement; |
2 |
const fontFamilySelect = document.querySelector('[name="family"]'); |
3 |
const fontSizeInput = document.querySelector('[type="number"]'); |
4 |
|
5 |
fontFamilySelect.addEventListener("input", function (e) { |
6 |
const value = e.target.value; |
7 |
if ("Arial" === value) { |
8 |
html.style.setProperty("--font-family", value); |
9 |
return; |
10 |
}
|
11 |
const link = document.createElement("link"); |
12 |
link.rel = "stylesheet"; |
13 |
link.href = `https://fonts.googleapis.com/css2?family=${value.replaceAll( |
14 |
" ", |
15 |
"+" |
16 |
)}:wght@400;700&display=swap`; |
17 |
document.head.appendChild(link); |
18 |
html.style.setProperty("--font-family", value); |
19 |
});
|
The base font size will be 18px. We can decrease or increase it via buttons or typing inside the target input. At any point, the base font size cannot be less than 18px or greater than 36px.
Notice that we define an initial size in the root element, and then, using the rem units, we apply the desired font size across the target elements.
The HTML part:
The JavaScript part:
1 |
const html = document.documentElement; |
2 |
const fontFamilySelect = document.querySelector('[name="family"]'); |
3 |
const fontSizeInput = document.querySelector('[type="number"]'); |
4 |
const fontSizeBtns = document.querySelectorAll(".btn-font-size"); |
5 |
let selectedFontSize = fontSizeInput.value; |
6 |
|
7 |
fontSizeBtns.forEach(function (btn) { |
8 |
btn.addEventListener("click", function (e) { |
9 |
const inputValue = Number(fontSizeInput.value); |
10 |
if ( |
11 |
e.target.classList.contains("btn-decrease") || |
12 |
e.target.parentElement.classList.contains("btn-decrease") |
13 |
) { |
14 |
if (fontSizeInput.value <= 10) return; |
15 |
fontSizeInput.value--; |
16 |
} else { |
17 |
if (fontSizeInput.value >= 20) return; |
18 |
fontSizeInput.value++; |
19 |
}
|
20 |
selectedFontSize = fontSizeInput.value; |
21 |
html.style.setProperty("--font-size", `${selectedFontSize}px`); |
22 |
});
|
23 |
});
|
24 |
|
25 |
fontSizeInput.addEventListener("change", function () { |
26 |
const value = this.value; |
27 |
if (value < 10 || value > 20) { |
28 |
this.value = selectedFontSize; |
29 |
} else { |
30 |
selectedFontSize = value; |
31 |
}
|
32 |
html.style.setProperty("--font-size", `${selectedFontSize}px`); |
33 |
});
|
The default page background color will be white, while the text color will be black. Thanks to the input
element of type color
, we can easily apply a new look to our page.
The HTML part:
The JavaScript part:
1 |
const html = document.documentElement; |
2 |
const colorInputs = document.querySelectorAll('[type="color"]'); |
3 |
|
4 |
colorInputs.forEach(function (input) { |
5 |
input.addEventListener("input", function () { |
6 |
html.style.setProperty(`--${this.id}`, this.value); |
7 |
});
|
8 |
});
|
By default, all images won’t have any effects. However, we can opt for one of the following:
Notice the use of the container style queries to apply the requested style. This is a pretty new CSS feature with almost 75% support during this writing.
Of course, you can implement a fallback solution for wider browser support.
The HTML part:
1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
The CSS part:
1 |
@container style(--type: grayscale) { |
2 |
img { |
3 |
filter: grayscale(1); |
4 |
}
|
5 |
}
|
6 |
|
7 |
@container style(--type: blur) { |
8 |
img { |
9 |
filter: blur(3px); |
10 |
}
|
11 |
}
|
12 |
|
13 |
@container style(--type: rounded) { |
14 |
img { |
15 |
border-radius: 50px; |
16 |
}
|
17 |
}
|
The JavaScript part:
1 |
const html = document.documentElement; |
2 |
const imageStyleSelect = document.querySelector('[name="image-style"]'); |
3 |
|
4 |
imageStyleSelect.addEventListener("input", function (e) { |
5 |
html.style.setProperty("--type", e.target.value); |
6 |
});
|
That’s all, folks! I hope this page configurator has inspired you to build something similar in your projects. Feel free to extend by adding more features like a reset button or the ability to copy to the clipboard the selected options for easier reuse.
If you have any questions or need something extra, comment in the demo area.
Let’s look again at our creation:
As always, thanks a lot for reading!