Construct an internet site web page configurator with CSS & JavaScript

To construct our web page configurator, we’ll mix old-school CSS methods with trendy CSS options like customized properties and container queries.
What We’re Constructing
With out additional ado, let’s check out the ultimate challenge. Click on the setting icon to the left of the display screen to entry the controls panel:
1. Start with the panel markup
Start by defining a toggle button and the panel configurator. Contained in the panel, we’ll place 5 kind wrappers—we’ll go over every of them later.
Right here’s the beginning markup:
1 | |
2 | class=“fa-solid fa-screwdriver-wrench” aria-hidden=“true”> |
3 | |
4 | |
5 | class=“panel”> |
6 | class=“control-wrapper”>… |
7 | class=“control-wrapper”>… |
8 | class=“control-wrapper”>… |
9 | class=“control-wrapper”>… |
10 | class=“control-wrapper”>… |
11 |
Purely for stylistic causes, we’ll embody the Font Superior icon library in our challenge.
2. Toggle the panel
By default, the configurator panel will sit off-screen. As quickly as we click on the button, it’ll glide easily from the left aspect.
Listed below are the associated kinds:
1 | /*CUSTOM VARIABLES HERE*/ |
2 | |
3 | .btn-toggle-panel, |
4 | .panel { |
5 | place: mounted; |
6 | left: 10px; |
7 | z-index: 1; |
8 | colour: var(–vampire-black); |
9 | background: var(–anti-flash-white); |
10 | } |
11 | |
12 | .btn-toggle-panel { |
13 | prime: 10px; |
14 | font-size: 18px; |
15 | width: 54px; |
16 | top: 54px; |
17 | border-radius: 50%; |
18 | } |
19 | |
20 | .panel { |
21 | prime: 70px; |
22 | font-size: 16px; |
23 | line-height: regular; |
24 | padding: 30px 20px; |
25 | border-radius: 30px; |
26 | rework: translateX(calc(-100% – 10px)); |
27 | transition: rework 0.4s; |
28 | } |
29 | |
30 | .panel.present { |
31 | rework: none; |
32 | } |
And the related JavaScript code:
1 | const togglePanelBtn = doc.querySelector(“.btn-toggle-panel“); |
2 | const panel = doc.querySelector(“.panel“); |
3 | |
4 | togglePanelBtn.addEventListener(“click on“, operate () { |
5 | panel.classList.toggle(“present“); |
6 | }); |
3. Web page customizations
Let’s now talk about in additional element what customization choices our configurator will permit.
For simplicity, we’ll skip many of the CSS stuff and present solely the important elements.
Font-Household
By default, the challenge will use the Arial font household. Nonetheless, we are able to go for one of many following Google Fonts:
- Fira Sans
- Inter
- Lato
- Montserrat
- Raleway
- Roboto
- Ubuntu
Notice that we received’t obtain all fonts collectively however upon request by following the Google Fonts API. That’s why you’ll see an on the spot flickering occur the primary time you choose a brand new font. You may verify the downloaded font information in your browser’s Community tab.
The HTML half:
1 | class=“control-wrapper”> |
2 | |
3 | class=“internal”> |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 |
The JavaScript half:
1 | const html = doc.documentElement; |
2 | const fontFamilySelect = doc.querySelector(‘[name=”family”]‘); |
3 | const fontSizeInput = doc.querySelector(‘[type=”number”]‘); |
4 | |
5 | fontFamilySelect.addEventListener(“enter“, operate (e) { |
6 | const worth = e.goal.worth; |
7 | if (“Arial“ === worth) { |
8 | html.model.setProperty(“–font-family“, worth); |
9 | return; |
10 | } |
11 | const hyperlink = doc.createElement(“hyperlink“); |
12 | hyperlink.rel = “stylesheet“; |
13 | hyperlink.href = `https://fonts.googleapis.com/css2?household=${worth.replaceAll( |
14 | “ “, |
15 | “+“ |
16 | )}:wght@400;700&show=swap`; |
17 | doc.head.appendChild(hyperlink); |
18 | html.model.setProperty(“–font-family“, worth); |
19 | }); |
Font Measurement
The bottom font measurement will likely be 18px. We will lower or enhance it through buttons or typing contained in the goal enter. At any level, the bottom font measurement can’t be lower than 18px or larger than 36px.
Discover that we outline an preliminary measurement within the root aspect, after which, utilizing the rem models, we apply the specified font measurement throughout the goal parts.
The HTML half:
1 | class=“control-wrapper”> |
2 | |
3 | class=“internal”> |
4 | |
5 | class=“fa-solid fa-minus” aria-hidden=“true”> |
6 | |
7 | |
8 | |
9 | class=“fa-solid fa-plus” aria-hidden=“true”> |
10 | |
11 | |
12 |
The JavaScript half:
1 | const html = doc.documentElement; |
2 | const fontFamilySelect = doc.querySelector(‘[name=”family”]‘); |
3 | const fontSizeInput = doc.querySelector(‘[type=”number”]‘); |
4 | const fontSizeBtns = doc.querySelectorAll(“.btn-font-size“); |
5 | let selectedFontSize = fontSizeInput.worth; |
6 | |
7 | fontSizeBtns.forEach(operate (btn) { |
8 | btn.addEventListener(“click on“, operate (e) { |
9 | const inputValue = Quantity(fontSizeInput.worth); |
10 | if ( |
11 | e.goal.classList.accommodates(“btn-decrease“) || |
12 | e.goal.parentElement.classList.accommodates(“btn-decrease“) |
13 | ) { |
14 | if (fontSizeInput.worth <= 10) return; |
15 | fontSizeInput.worth—; |
16 | } else { |
17 | if (fontSizeInput.worth >= 20) return; |
18 | fontSizeInput.worth++; |
19 | } |
20 | selectedFontSize = fontSizeInput.worth; |
21 | html.model.setProperty(“–font-size“, `${selectedFontSize}px`); |
22 | }); |
23 | }); |
24 | |
25 | fontSizeInput.addEventListener(“change“, operate () { |
26 | const worth = this.worth; |
27 | if (worth < 10 || worth > 20) { |
28 | this.worth = selectedFontSize; |
29 | } else { |
30 | selectedFontSize = worth; |
31 | } |
32 | html.model.setProperty(“–font-size“, `${selectedFontSize}px`); |
33 | }); |
Colours
The default web page background colour will likely be white, whereas the textual content colour will likely be black. Because of the enter aspect of sort colour, we are able to simply apply a brand new look to our web page.
The HTML half:
1 | class=“control-wrapper”> |
2 | |
3 | class=“internal”> |
4 | |
5 | |
6 | |
7 | |
8 | class=“control-wrapper”> |
9 | |
10 | class=“internal”> |
11 | |
12 | |
13 |
The JavaScript half:
1 | const html = doc.documentElement; |
2 | const colorInputs = doc.querySelectorAll(‘[type=”color”]‘); |
3 | |
4 | colorInputs.forEach(operate (enter) { |
5 | enter.addEventListener(“enter“, operate () { |
6 | html.model.setProperty(`–${this.id}`, this.worth); |
7 | }); |
8 | }); |
Picture Results
By default, all photographs received’t have any results. Nonetheless, we are able to go for one of many following:
Discover using the container model queries to use the requested model. This is a fairly new CSS characteristic with virtually 75% help throughout this writing.
In fact, you’ll be able to implement a fallback resolution for wider browser help.
The HTML half:
1 | class=“control-wrapper”> |
2 | |
3 | class=“internal”> |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 |
The CSS half:
1 | @container model(–type: grayscale) { |
2 | img { |
3 | filter: grayscale(1); |
4 | } |
5 | } |
6 | |
7 | @container model(–type: blur) { |
8 | img { |
9 | filter: blur(3px); |
10 | } |
11 | } |
12 | |
13 | @container model(–type: rounded) { |
14 | img { |
15 | border-radius: 50px; |
16 | } |
17 | } |
The JavaScript half:
1 | const html = doc.documentElement; |
2 | const imageStyleSelect = doc.querySelector(‘[name=”image-style”]‘); |
3 | |
4 | imageStyleSelect.addEventListener(“enter“, operate (e) { |
5 | html.model.setProperty(“–type“, e.goal.worth); |
6 | }); |
Conclusion
That’s all, of us! I hope this web page configurator has impressed you to construct one thing related in your initiatives. Be happy to increase by including extra options like a reset button or the power to repeat to the clipboard the chosen choices for simpler reuse.
When you have any questions or want one thing further, remark within the demo space.
Let’s look once more at our creation:
As at all times, thanks so much for studying!