Learn how to create a scaffolding rent and manufacturing website template using HTML, CSS, and JavaScript.

Table of Contents
Are you looking to build a website for a scaffolding rental or manufacturing business? In this blog, you will learn how to create a simple and professional template using HTML, CSS, and JavaScript. This template can be used for any scaffolding-related service like renting, selling, or manufacturing.
You don’t need to be an expert in coding. Just basic knowledge of web development is enough.
Prerequisites
Before you start, make sure you have the following:
- A code editor like VS Code
- Basic knowledge of HTML, CSS, and JavaScript
- Web browser (Google Chrome or Firefox)
Source Code
Step 1 (HTML Code):
To get started, we will first need to create a basic HTML file. In this file, we will include the main structure for our Scaffolding Manufacturing Template.
After creating the files just paste the below codes into your file. Make sure to save your HTML document with a .html
extension, so that it can be properly viewed in a web browser.
This is the basic structure of our Scaffolding Rent and Manufacturing Template using HTML, and now we can move on to styling it using CSS.
Step 2 (CSS Code):
Once the basic HTML structure of the website is in place, the next step is to add styling to the website using CSS. Below is a section-by-section explanation in simpler terms:
1. Root Variables (:root)
:root {
--primary-color: #ffc107;
--secondary-color: #343a40;
--light-gray: #f8f9fa;
--medium-gray: #6c757d;
--white: #ffffff;
--black: #000000;
}
- These are custom variables to define common colors used throughout the website.
- This makes it easy to change the theme just by updating values in one place.
2. Global Styles (body, headings)
body {
font-family: 'Poppins', sans-serif;
color: var(--secondary-color);
line-height: 1.7;
}
- Sets a clean font, default text color, and better readability with line-height.
h1, h2, h3, h4, h5, h6 {
font-weight: 600;
color: var(--secondary-color);
}
- Makes all headings bold and dark for better visibility.
3. Navbar
.navbar {
transition: background-color 0.3s ease-in-out;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
- Adds a smooth transition and subtle shadow for a polished look.
.navbar-dark .navbar-nav .nav-link {
color: rgba(255, 255, 255, 0.8);
transition: color 0.3s ease;
}
.navbar-dark .navbar-nav .nav-link:hover,
.navbar-dark .navbar-nav .nav-link.active {
color: var(--primary-color);
}
- Navigation links are semi-white, turn yellow on hover or when active.
4. Hero Section
.hero-section {
background: linear-gradient(...), url(...);
background-size: cover;
color: var(--white);
...
}
- A visually striking top section with a background image and dark overlay for better text contrast.
.hero-section h1, p, .btn-primary
- Large white headline, subtitle, and a bold yellow button with hover effects (e.g., shadow, slight lift).
.hero-section .phone-number {
font-size: 1.2rem;
font-weight: 600;
...
}
- Highlights the phone number prominently in yellow below the call-to-action.
5. Section and Titles
.section-bg {
background-color: var(--light-gray);
}
.section-title h2, p {
text-align: center;
margin-bottom: 50px;
}
.section-title::after {
content: '';
width: 50px;
height: 3px;
background: var(--primary-color);
}
- Creates a reusable design for each content section with a heading, subtext, and a colored underline.
6. Icon Boxes (Services/Features)
.icon-box {
background: white;
border-radius: 8px;
box-shadow: ...;
transition: ...;
}
.icon-box:hover {
transform: translateY(-5px);
}
- These are boxes with icons and descriptions (e.g., features, benefits) that lift on hover.
7. Product Items
.product-item {
border-radius: 8px;
box-shadow: ...;
overflow: hidden;
transition: transform 0.3s ease;
}
.product-item:hover {
transform: scale(1.03);
}
- Showcases product cards that slightly zoom on hover for interactivity.
8. Gallery Filters
#gallery-filters li {
display: inline-block;
padding: 8px 15px;
border: 1px solid var(--medium-gray);
}
#gallery-filters li:hover,
#gallery-filters li.filter-active {
background: var(--primary-color);
color: var(--secondary-color);
}
- Allows users to filter gallery items by category using colored buttons.
9. Testimonials
.testimonials .testimonial-item {
text-align: center;
padding: 40px 20px;
}
.testimonial-item img {
border-radius: 50%;
}
- User reviews are displayed with circular images, highlighted quotes, and a stylish layout.
10. Industry Items (partial)
.industry-item {
text-align: center;
background: var(--white);
...
}
- It used to show industry categories served, styled similarly to icon or product boxes.
:root {
--primary-color: #ffc107; /* Yellow */
--secondary-color: #343a40; /* Dark Gray/Black */
--light-gray: #f8f9fa;
--medium-gray: #6c757d;
--white: #ffffff;
--black: #000000;
}
body {
font-family: 'Poppins', sans-serif;
color: var(--secondary-color);
line-height: 1.7;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 600;
color: var(--secondary-color);
}
.navbar {
transition: background-color 0.3s ease-in-out;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.navbar-brand img {
max-height: 50px; /* Adjust as needed */
}
.navbar-dark .navbar-nav .nav-link {
color: rgba(255, 255, 255, 0.8);
transition: color 0.3s ease;
padding: 0.5rem 1rem;
}
.navbar-dark .navbar-nav .nav-link:hover,
.navbar-dark .navbar-nav .nav-link.active {
color: var(--primary-color);
}
.navbar-toggler {
border-color: rgba(255, 255, 255, 0.1);
}
.navbar-toggler-icon {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.8%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
}
.hero-section {
background: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)),
url('https://raw.githubusercontent.com/farazc60/Project-Images/refs/heads/main/scaffolding-templates/scaffolding-hero-section.webp')
no-repeat center center;
background-size: cover;
color: var(--white);
padding: 150px 0;
text-align: center;
min-height: 80vh; /* Ensure it takes significant height */
display: flex;
align-items: center;
justify-content: center;
}
.hero-section h1 {
font-size: 3rem;
font-weight: 700;
margin-bottom: 1rem;
color: var(--white);
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
}
.hero-section p {
font-size: 1.25rem;
margin-bottom: 2rem;
color: rgba(255, 255, 255, 0.9);
}
.hero-section .btn-primary {
background-color: var(--primary-color);
border-color: var(--primary-color);
color: var(--secondary-color);
padding: 12px 30px;
font-size: 1.1rem;
font-weight: 600;
transition: all 0.3s ease;
margin-right: 1rem; /* Space between buttons */
}
.hero-section .btn-primary:hover {
background-color: #e0a800; /* Darker yellow */
border-color: #e0a800;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.hero-section .phone-number {
font-size: 1.2rem;
font-weight: 600;
margin-top: 1.5rem;
display: block; /* Make it block to appear below */
color: var(--primary-color);
}
.hero-section .phone-number i {
margin-right: 8px;
}
section {
padding: 25px 0;
}
.section-bg {
background-color: var(--light-gray);
}
.section-title {
text-align: center;
margin-bottom: 50px;
position: relative;
}
.section-title h2 {
font-size: 2.5rem;
font-weight: 700;
margin-bottom: 15px;
text-transform: uppercase;
color: var(--secondary-color);
}
.section-title p {
color: var(--medium-gray);
max-width: 600px;
margin: 0 auto;
}
.section-title::after {
content: '';
position: absolute;
display: block;
width: 50px;
height: 3px;
background: var(--primary-color);
bottom: -10px;
left: calc(50% - 25px);
}
/* Service & Feature Icons */
.icon-box {
text-align: center;
padding: 30px 20px;
background: var(--white);
border-radius: 8px;
box-shadow: 0 0 30px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease-in-out;
margin-bottom: 30px; /* Add space between boxes */
height: 100%; /* Make boxes equal height in a row */
display: flex;
flex-direction: column;
justify-content: center; /* Center content vertically */
}
.icon-box:hover {
transform: translateY(-5px);
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
}
.icon-box .icon {
margin: 0 auto 20px auto;
width: 64px;
height: 64px;
background: var(--primary-color);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease-in-out;
}
.icon-box .icon i {
color: var(--secondary-color);
font-size: 28px;
}
.icon-box h4 {
font-weight: 600;
margin-bottom: 15px;
font-size: 1.2rem;
}
.icon-box p {
color: var(--medium-gray);
font-size: 0.95rem;
}
.about ul {
list-style: none;
padding: 0;
margin: 0;
}
/* Product Categories & Gallery */
.product-item {
margin-bottom: 30px;
background: var(--white);
border-radius: 8px;
overflow: hidden;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.05);
transition: transform 0.3s ease;
}
.product-item:hover {
transform: scale(1.03);
}
.product-item img {
width: 100%;
height: 250px; /* Fixed height for consistency */
object-fit: contain; /* Ensure image covers the area */
}
.product-item .product-info {
padding: 20px;
text-align: center;
}
.product-item h5 {
font-size: 1.1rem;
font-weight: 600;
margin-bottom: 10px;
}
.product-item p {
font-size: 0.9rem;
color: var(--medium-gray);
}
/* Gallery Filters */
#gallery-filters {
padding: 0;
margin: 0 auto 35px auto;
list-style: none;
text-align: center;
}
#gallery-filters li {
cursor: pointer;
display: inline-block;
padding: 8px 15px;
font-size: 0.9rem;
font-weight: 600;
line-height: 1;
text-transform: uppercase;
color: var(--secondary-color);
margin: 0 4px 10px 4px;
transition: all 0.3s ease-in-out;
border-radius: 4px;
border: 1px solid var(--medium-gray);
}
#gallery-filters li:hover,
#gallery-filters li.filter-active {
color: var(--secondary-color);
background: var(--primary-color);
border-color: var(--primary-color);
}
/* Testimonials Carousel */
.testimonials .carousel-indicators button {
background-color: var(--medium-gray);
width: 12px;
height: 12px;
border-radius: 50%;
margin: 0 5px;
}
.testimonials .carousel-indicators .active {
background-color: var(--primary-color);
}
.testimonial-item {
text-align: center;
padding: 40px 20px;
}
.testimonial-item img {
width: 100px;
border-radius: 50%;
margin: 0 auto 20px auto;
border: 4px solid var(--light-gray);
}
.testimonial-item h5 {
font-weight: bold;
margin-bottom: 5px;
}
.testimonial-item h6 {
color: var(--medium-gray);
font-size: 0.9rem;
margin-bottom: 15px;
}
.testimonial-item .quote-icon-left,
.testimonial-item .quote-icon-right {
color: var(--primary-color);
font-size: 26px;
}
.testimonial-item .quote-icon-left {
display: inline-block;
left: -5px;
position: relative;
}
.testimonial-item .quote-icon-right {
display: inline-block;
right: -5px;
position: relative;
top: 10px;
}
.testimonial-item p {
font-style: italic;
margin: 0 auto 15px auto;
color: var(--medium-gray);
max-width: 700px; /* Limit quote width */
}
/* Industries Served */
.industry-item {
text-align: center;
padding: 20px;
background: var(--white);
border-radius: 8px;
box-shadow: 0 0 15px rgba(0, 0, 0, 0.05);
margin-bottom: 30px;
height: 100%;
}
.industry-item i {
font-size: 36px;
color: var(--primary-color);
margin-bottom: 15px;
display: block;
}
.industry-item h5 {
font-size: 1.1rem;
font-weight: 600;
}
/* FAQ Accordion */
.faq .accordion-button {
font-weight: 600;
color: var(--secondary-color);
}
.faq .accordion-button:focus {
box-shadow: none;
border-color: rgba(0, 0, 0, 0.125);
}
.faq .accordion-button:not(.collapsed) {
color: var(--secondary-color);
background-color: rgba(255, 193, 7, 0.1); /* Light yellow background */
}
.faq .accordion-button::after {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23343a40'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
}
.faq .accordion-button:not(.collapsed)::after {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23343a40'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
transform: rotate(-180deg);
}
.faq .accordion-body {
color: var(--medium-gray);
}
/* Contact Section */
.contact .info-box {
color: var(--secondary-color);
text-align: center;
box-shadow: 0 0 30px rgba(0, 0, 0, 0.08);
padding: 20px 0 30px 0;
border-radius: 8px;
margin-bottom: 30px;
background: var(--white);
}
.contact .info-box i {
font-size: 32px;
color: var(--primary-color);
border-radius: 50%;
padding: 8px;
border: 2px dotted #ffecb3; /* Light yellow dotted border */
margin-bottom: 15px;
}
.contact .info-box h3 {
font-size: 1.2rem;
font-weight: 600;
margin-bottom: 10px;
}
.contact .info-box p {
padding: 0 15px;
line-height: 1.5;
font-size: 0.9rem;
color: var(--medium-gray);
}
.contact .info-box a {
color: var(--medium-gray);
text-decoration: none;
transition: color 0.3s;
}
.contact .info-box a:hover {
color: var(--primary-color);
}
.contact .contact-form {
box-shadow: 0 0 30px rgba(0, 0, 0, 0.08);
padding: 30px;
border-radius: 8px;
background: var(--white);
}
.contact .contact-form .form-control {
border-radius: 4px;
}
.contact .contact-form .form-control:focus {
box-shadow: none;
border-color: var(--primary-color);
}
.contact .contact-form button[type='submit'] {
background: var(--primary-color);
border: 0;
padding: 10px 30px;
color: var(--secondary-color);
transition: 0.4s;
border-radius: 4px;
font-weight: 600;
}
.contact .contact-form button[type='submit']:hover {
background: #e0a800; /* Darker yellow */
}
.contact .map-container {
border-radius: 8px;
overflow: hidden; /* Ensures the map respects the border radius */
box-shadow: 0 0 30px rgba(0, 0, 0, 0.08);
height: 400px; /* Adjust height as needed */
margin-bottom: 30px;
}
.contact .map-container iframe {
border: 0;
width: 100%;
height: 100%;
}
/* Footer */
.footer {
background: var(--secondary-color);
color: rgba(255, 255, 255, 0.7);
font-size: 0.9rem;
padding: 60px 0 30px 0;
}
.footer .footer-top {
padding-bottom: 30px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
margin-bottom: 30px;
}
.footer .footer-logo img {
max-height: 40px; /* Adjust footer logo size */
margin-bottom: 15px;
}
.footer h4 {
font-size: 1rem;
font-weight: bold;
color: var(--white);
position: relative;
padding-bottom: 12px;
margin-bottom: 20px;
}
.footer h4::after {
content: '';
position: absolute;
display: block;
width: 30px;
height: 2px;
background: var(--primary-color);
bottom: 0;
left: 0;
}
.footer .footer-links ul {
list-style: none;
padding: 0;
margin: 0;
}
.footer .footer-links ul li {
padding: 8px 0;
display: flex;
align-items: center;
}
.footer .footer-links ul li:first-child {
padding-top: 0;
}
.footer .footer-links ul a {
color: rgba(255, 255, 255, 0.7);
transition: 0.3s;
display: inline-block;
line-height: 1;
text-decoration: none;
}
.footer .footer-links ul a:hover {
color: var(--primary-color);
}
.footer .footer-links ul i {
margin-right: 8px;
color: var(--primary-color);
font-size: 12px; /* Smaller icon for list items */
}
.footer .footer-contact p {
margin-bottom: 10px;
}
.footer .social-links a {
font-size: 18px;
display: inline-block;
background: rgba(255, 255, 255, 0.1);
color: var(--white);
line-height: 1;
padding: 8px 0;
margin-right: 4px;
border-radius: 50%;
text-align: center;
width: 36px;
height: 36px;
transition: 0.3s;
}
.footer .social-links a:hover {
background: var(--primary-color);
color: var(--secondary-color);
text-decoration: none;
}
.footer .copyright {
text-align: center;
padding-top: 30px;
}
.footer .credits {
padding-top: 10px;
text-align: center;
font-size: 0.8rem;
}
.footer .credits a {
color: var(--primary-color);
text-decoration: none;
}
/* Scroll-to-Top Button */
.scroll-to-top {
position: fixed;
bottom: 20px;
right: 20px;
background-color: var(--primary-color);
color: var(--secondary-color);
width: 40px;
height: 40px;
border-radius: 50%;
text-align: center;
line-height: 40px; /* Vertically center icon */
font-size: 18px;
display: none; /* Hidden by default */
z-index: 1000;
transition: opacity 0.3s ease-in-out, visibility 0.3s ease-in-out;
opacity: 0;
visibility: hidden;
}
.scroll-to-top.visible {
display: block;
opacity: 1;
visibility: visible;
}
.scroll-to-top:hover {
background-color: #e0a800; /* Darker yellow */
color: var(--secondary-color);
}
/* Fixed Action Buttons (Call/WhatsApp) */
.fixed-action-buttons {
position: fixed;
bottom: 20px; /* Adjust vertical position */
right: 70px; /* Position next to scroll-to-top */
z-index: 999;
display: flex;
flex-direction: column; /* Stack vertically */
gap: 10px; /* Space between buttons */
}
.action-button {
display: flex;
align-items: center;
justify-content: center;
width: 50px;
height: 50px;
border-radius: 50%;
color: var(--white);
font-size: 24px;
text-decoration: none;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.action-button:hover {
transform: scale(1.1);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
color: var(--white);
}
.call-button {
background-color: #28a745; /* Green for call */
}
.whatsapp-button {
background-color: #25d366; /* WhatsApp green */
}
/* Responsive Adjustments */
@media (max-width: 991.98px) {
.hero-section {
padding: 100px 0;
min-height: 60vh;
}
.hero-section h1 {
font-size: 2.5rem;
}
.hero-section p {
font-size: 1.1rem;
}
.navbar-nav {
text-align: center;
background-color: var(
--secondary-color
); /* Background for collapsed menu */
padding-bottom: 1rem;
}
.fixed-action-buttons {
bottom: 80px; /* Adjust position above potential bottom nav bars on mobile */
right: 20px; /* Move to the right edge */
flex-direction: row; /* Horizontal on smaller screens */
}
.scroll-to-top {
bottom: 20px;
right: 20px;
}
}
@media (max-width: 767.98px) {
.hero-section {
padding: 80px 0;
text-align: center;
}
.hero-section .btn-primary {
margin-bottom: 1rem; /* Stack buttons */
margin-right: 0;
}
.hero-section .phone-number {
font-size: 1.1rem;
}
.section-title h2 {
font-size: 2rem;
}
.contact .info-box {
margin-bottom: 20px;
}
.footer .footer-top .col-lg-3 {
margin-bottom: 30px; /* Add space between footer columns on mobile */
}
.fixed-action-buttons {
flex-direction: row;
gap: 15px;
}
.action-button {
width: 45px;
height: 45px;
font-size: 20px;
}
}
Step 3 (JavaScript Code):
Finally, we need to create a function in JavaScript. Let's break down the code:
1. DOM Ready Event
document.addEventListener('DOMContentLoaded', () => {
- Waits until the HTML document is fully loaded before running any JavaScript.
2. AOS (Animate On Scroll) Initialization
AOS.init({
duration: 800,
easing: 'ease-in-out',
once: true,
mirror: false
});
- Initializes AOS for scroll animations.
- duration: how long the animation lasts (800ms).
- easing: animation effect.
- once: true: animation happens only once.
- mirror: false: no animation when scrolling back up.
3. Scroll-to-Top Button
const scrollTopButton = document.querySelector('.scroll-to-top');
- Shows or hides the "scroll to top" button based on how far you've scrolled (>100px).
- Adds a smooth scroll effect when clicked.
4. Navbar Active Link Highlighting
let navbarlinks = document.querySelectorAll('#navbarNav .nav-link');
- Highlights the current section's link in the navbar while scrolling.
- Uses a 200px offset to trigger the highlight earlier.
5. Smooth Scroll for Anchor Links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
- Smoothly scrolls to sections when anchor links are clicked.
- Considers the header height to prevent content from being hidden under it.
- Closes the mobile navbar if it's open.
6. Gallery Filtering Using Isotope
let galleryContainer = document.querySelector('.gallery-container');
- Filters gallery items (e.g., images) using Isotope.js.
- Clicking on a filter adds an active class and updates the gallery layout.
7. Gallery Lightbox
const galleryLightbox = GLightbox({
selector: '.gallery-lightbox'
});
- Initializes GLightbox for viewing gallery images in a modal popup.
8. Bootstrap Form Validation
(() => {
'use strict'
- Prevents form submission if validation fails.
- Adds Bootstrap’s .was-validated class to show feedback styles.
9. PHP Email Form Submission Placeholder (Commented Out)
/*
const contactForm = document.querySelector('.php-email-form');
- Placeholder logic for sending contact form data to a PHP backend.
- Simulates form submission with a timeout for demonstration.
document.addEventListener('DOMContentLoaded', () => {
"use strict";
// Initialize AOS
AOS.init({
duration: 800,
easing: 'ease-in-out',
once: true,
mirror: false
});
// Sticky Navbar Shrink Effect (Optional - if needed)
// Add logic here if you want the navbar to change style on scroll
// Scroll-to-Top Button Visibility
const scrollTopButton = document.querySelector('.scroll-to-top');
if (scrollTopButton) {
const toggleScrollTop = function() {
window.scrollY > 100 ? scrollTopButton.classList.add('visible') : scrollTopButton.classList.remove('visible');
}
window.addEventListener('load', toggleScrollTop);
document.addEventListener('scroll', toggleScrollTop);
scrollTopButton.addEventListener('click', (e) => {
e.preventDefault();
window.scrollTo({
top: 0,
behavior: 'smooth'
});
});
}
// Navbar Active State on Scroll
let navbarlinks = document.querySelectorAll('#navbarNav .nav-link');
function navbarlinksActive() {
navbarlinks.forEach(navbarlink => {
if (!navbarlink.hash) return;
let section = document.querySelector(navbarlink.hash);
if (!section) return;
let position = window.scrollY + 200; // Offset
if (position >= section.offsetTop && position <= (section.offsetTop + section.offsetHeight)) {
navbarlink.classList.add('active');
} else {
navbarlink.classList.remove('active');
}
})
}
window.addEventListener('load', navbarlinksActive);
document.addEventListener('scroll', navbarlinksActive);
// Smooth scroll for links with hashes
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
const hash = this.getAttribute('href');
// Only prevent default for actual section links, not empty hashes or just "#"
if (hash && hash !== '#' && document.querySelector(hash)) {
e.preventDefault();
const targetElement = document.querySelector(hash);
if (targetElement) {
const header = document.querySelector('#header');
const headerOffset = header ? header.offsetHeight : 0;
const elementPosition = targetElement.offsetTop;
const offsetPosition = elementPosition - headerOffset;
window.scrollTo({
top: offsetPosition,
behavior: 'smooth'
});
// Close mobile nav if open after clicking a link
const navbarToggler = document.querySelector('.navbar-toggler');
const navbarCollapse = document.querySelector('#navbarNav');
if (navbarToggler && navbarCollapse.classList.contains('show')) {
navbarToggler.click(); // Simulate click to close
}
}
}
});
});
// Gallery Filtering (Isotope)
let galleryContainer = document.querySelector('.gallery-container');
if (galleryContainer) {
let galleryIsotope = new Isotope(galleryContainer, {
itemSelector: '.gallery-item',
layoutMode: 'fitRows'
});
let galleryFilters = document.querySelectorAll('#gallery-filters li');
galleryFilters.forEach(function(el) {
el.addEventListener('click', function() {
galleryFilters.forEach(function(filter) {
filter.classList.remove('filter-active');
});
this.classList.add('filter-active');
galleryIsotope.arrange({
filter: this.getAttribute('data-filter')
});
// Optional: Re-initialize AOS after filtering if needed
// AOS.refresh();
});
});
}
// Gallery Lightbox (GLightbox)
const galleryLightbox = GLightbox({
selector: '.gallery-lightbox'
});
// Bootstrap Form Validation
// Example starter JavaScript for disabling form submissions if there are invalid fields
(() => {
'use strict'
// Fetch all the forms we want to apply custom Bootstrap validation styles to
const forms = document.querySelectorAll('.needs-validation')
// Loop over them and prevent submission
Array.from(forms).forEach(form => {
form.addEventListener('submit', event => {
if (!form.checkValidity()) {
event.preventDefault()
event.stopPropagation()
}
form.classList.add('was-validated')
}, false)
})
})()
// Placeholder for PHP Email Form Submission Logic
// This requires a backend script (e.g., PHP) to actually send the email.
// The .php-email-form class is just a convention here.
// You would typically use Fetch API or XMLHttpRequest to send data to your backend.
/*
const contactForm = document.querySelector('.php-email-form');
if (contactForm) {
contactForm.addEventListener('submit', function(e) {
e.preventDefault(); // Prevent default form submission
// Basic validation check (redundant if using Bootstrap validation, but good practice)
if (!this.checkValidity()) {
this.classList.add('was-validated');
return;
}
let formData = new FormData(this);
let action = this.getAttribute('action'); // Get the backend script URL
// Display loading message
this.querySelector('.loading').classList.add('d-block');
this.querySelector('.error-message').classList.remove('d-block');
this.querySelector('.sent-message').classList.remove('d-block');
// Replace with your actual Fetch API call to the backend
// fetch(action, { method: 'POST', body: formData })
// .then(response => {
// if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
// return response.text(); // Or response.json() if your backend returns JSON
// })
// .then(data => {
// this.querySelector('.loading').classList.remove('d-block');
// if (data.trim() === 'OK') { // Check backend response
// this.querySelector('.sent-message').classList.add('d-block');
// this.reset(); // Clear the form
// this.classList.remove('was-validated');
// } else {
// throw new Error(data || 'Form submission failed');
// }
// })
// .catch((error) => {
// this.querySelector('.loading').classList.remove('d-block');
// this.querySelector('.error-message').innerHTML = error.message || 'An error occurred. Please try again.';
// this.querySelector('.error-message').classList.add('d-block');
// });
// **Remove this simulation section when implementing actual backend**
// Simulate sending for demonstration purposes:
console.log("Form data submitted (simulation):", Object.fromEntries(formData));
setTimeout(() => {
this.querySelector('.loading').classList.remove('d-block');
// Simulate success:
this.querySelector('.sent-message').classList.add('d-block');
this.reset();
this.classList.remove('was-validated');
// Simulate error:
// this.querySelector('.error-message').innerHTML = 'Simulation Error: Could not send.';
// this.querySelector('.error-message').classList.add('d-block');
}, 1500); // Simulate network delay
});
}
*/
});
Final Output:

Conclusion:
You have now created a simple scaffolding rent and manufacturing website template using HTML, CSS, and JavaScript. This design is clean, mobile-friendly, and easy to customize.
You can:
- Add more pages like projects, pricing, or gallery
- Improve with animations using AOS or GSAP
- Connect the contact form to backend services like PHP or Formspree
This template is perfect for small scaffolding businesses who want an online presence without spending too much.
That’s a wrap!
I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.
Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee
And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!
Thanks!
Faraz 😊