A professional website helps a business introduce its services, showcase its work, and make it easy for potential customers to get in touch. In this project, you will create a responsive business website template using HTML5, CSS3, and JavaScript. This one-page website brings essential business information into a clean, easy-to-navigate layout that adapts to mobile, tablet, and desktop screens.
The project uses separate HTML, CSS, and JavaScript files, making the code easier to understand and customize. You can adapt the template for a consulting company, digital agency, startup, or local business.
What you will build
You will build a responsive one-page business website with a modern design and practical interactive features. The template includes:
A sticky header with responsive mobile navigation.
A hero section with a headline and call-to-action buttons.
An about section for introducing the business.
A service grid highlighting six business offerings.
A section explaining the company’s key strengths.
Project cards for showcasing sample work.
Sample testimonials and an interactive FAQ accordion.
Contact details and a contact form with frontend validation.
A back-to-top button and subtle scroll animations.
A footer with useful links and an automatically updated copyright year.
The project is organized into three separate files: index.html for the page structure, style.css for the design and responsive layouts, and script.js for interactive behavior. The contact form is a frontend demo and requires a backend or form service to deliver enquiries.
HTML source
<!doctype html>
<html lang="en"><head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Northstar is a sample business consulting studio helping ambitious teams build clear strategies, stronger brands, and better digital experiences.">
<meta name="theme-color" content="#17213b">
<title>Northstar — Strategy, design & digital growth</title>
</head>
<body id="top">
<a class="skip-link" href="#main">Skip to content</a>
<header class="site-header">
<div class="container header-inner">
<a class="logo" href="#top" aria-label="Northstar home">
<span aria-hidden="true">✳</span>
northstar<span class="logo-dot">.</span>
</a>
<button class="menu-toggle" type="button" aria-expanded="false" aria-controls="primary-nav" hidden="">
Menu <span aria-hidden="true">☰</span>
</button>
<nav id="primary-nav" aria-label="Primary navigation">
<a href="#about">About</a>
<a href="#services">Services</a>
<a href="#work">Our work</a>
<a href="#faq">FAQ</a>
<a class="button button-small" href="#contact">
Get a Quote <span aria-hidden="true">↗</span>
</a>
</nav>
</div>
</header>
<main id="main" tabindex="-1">
<section class="hero section" aria-labelledby="hero-title">
<div class="container two-column">
<div class="hero-copy">
<p class="eyebrow">A clearer direction. A stronger business.</p>
<h1 id="hero-title">
Big ambitions.<br><span>Practical next steps.</span>
</h1>
<p class="lead">
We turn complex business challenges into clear strategies,
thoughtful brands, and digital experiences that move you forward.
</p>
<div class="button-row">
<a class="button" href="#contact">
Let’s talk about your goals <span aria-hidden="true">↗</span>
</a>
<a class="button button-outline" href="#work">Explore our work</a>
</div>
<p class="hero-note">
Strategy meets creativity. People come first.
</p>
</div>
<div class="hero-visual">
<!-- Photo from Pixabay. -->
<img src="https://cdn.pixabay.com/photo/2015/01/09/11/08/startup-594090_1280.jpg" alt="Consultants collaborating around a table on a business strategy" width="1200" height="1000" fetchpriority="high">
<div class="image-caption">
<span class="status-dot" aria-hidden="true"></span>
Good ideas. Clear direction. Shared momentum.
</div>
</div>
</div>
</section>
<section class="highlights" aria-label="Our working principles">
<div class="container highlight-grid">
<div>
<strong>Clarity first</strong>
<span>A shared plan from day one</span>
</div>
<div>
<strong>Built together</strong>
<span>Your team, actively involved</span>
</div>
<div>
<strong>Progress you can see</strong>
<span>Clear milestones and reporting</span>
</div>
<div>
<strong>Ready for what’s next</strong>
<span>Tools your team can keep using</span>
</div>
</div>
</section>
<section class="section" id="about" aria-labelledby="about-title">
<div class="container two-column">
<!-- Photo from Pixabay. -->
<img class="section-image reveal" src="https://cdn.pixabay.com/photo/2018/03/27/21/43/startup-3267505_1280.jpg" alt="Team reviewing ideas and planning priorities during a workshop" width="1000" height="900" loading="lazy" decoding="async">
<div class="reveal">
<p class="eyebrow">A partner, not just a provider</p>
<h2 id="about-title">Thoughtful thinking.<br>Hands-on delivery.</h2>
<p>
Northstar is a fictional independent consulting and digital studio
built around a simple idea: the best work makes your next decision easier.
</p>
<p>
From finding your position in the market to improving the way
customers experience your business, we connect the big picture
with the details that matter.
</p>
<ul class="strengths">
<li>Senior-level thinking, direct collaboration</li>
<li>Clear scope, honest conversations, useful outcomes</li>
<li>Practical handover that builds your team’s confidence</li>
</ul>
<a class="text-link" href="#contact">
Meet your next project partner <span aria-hidden="true">↗</span>
</a>
</div>
</div>
</section>
<section class="section section-tint" id="services" aria-labelledby="services-title">
<div class="container">
<div class="section-heading reveal">
<p class="eyebrow">How we help</p>
<h2 id="services-title">
The right expertise.<br>Exactly where you need it.
</h2>
<p>
Focused support for a single challenge, or an integrated team for
your next chapter.
</p>
</div>
<div class="card-grid services-grid">
<article class="card reveal">
<span class="icon" aria-hidden="true">◎</span>
<h3>Business strategy</h3>
<p>
Translate your ambitions into focused priorities, a practical
roadmap, and measures of meaningful progress.
</p>
</article>
<article class="card reveal">
<span class="icon" aria-hidden="true">◇</span>
<h3>Brand & positioning</h3>
<p>
Define what makes you different and express it through a
distinctive identity and a consistent voice.
</p>
</article>
<article class="card reveal">
<span class="icon" aria-hidden="true">▤</span>
<h3>Website design</h3>
<p>
Create accessible, responsive websites that explain your value
and make the next step feel effortless.
</p>
</article>
<article class="card reveal">
<span class="icon" aria-hidden="true">↗</span>
<h3>Digital marketing</h3>
<p>
Build a considered content and campaign plan around the audiences
and channels that matter to your business.
</p>
</article>
<article class="card reveal">
<span class="icon" aria-hidden="true">⚙</span>
<h3>Operations consulting</h3>
<p>
Simplify workflows, clarify ownership, and give your team more
room to focus on high-value work.
</p>
</article>
<article class="card reveal">
<span class="icon" aria-hidden="true">▥</span>
<h3>Research & insights</h3>
<p>
Turn customer interviews, market research, and performance data
into decisions you can explain and act on.
</p>
</article>
</div>
</div>
</section>
<section class="section" aria-labelledby="why-title">
<div class="container">
<div class="section-heading reveal">
<p class="eyebrow">The Northstar approach</p>
<h2 id="why-title">
Good work starts with a better partnership.
</h2>
</div>
<div class="reasons-grid">
<article class="reason reveal">
<span class="number">01 /</span>
<h3>We listen before we solve</h3>
<p>
We take time to understand your customers, constraints, and goals
before recommending a direction.
</p>
</article>
<article class="reason reveal">
<span class="number">02 /</span>
<h3>You always know where things stand</h3>
<p>
Agreed milestones, regular updates, and clear feedback keep the
project moving with fewer surprises.
</p>
</article>
<article class="reason reveal">
<span class="number">03 /</span>
<h3>Strategy connects to execution</h3>
<p>
The people shaping your plan stay close to delivery, so the
details reflect the original intent.
</p>
</article>
<article class="reason reveal">
<span class="number">04 /</span>
<h3>We build for your independence</h3>
<p>
You leave with useful documentation, practical tools, and the
confidence to carry the work forward.
</p>
</article>
</div>
</div>
</section>
<section class="section section-tint" id="work" aria-labelledby="work-title">
<div class="container">
<div class="section-heading reveal">
<p class="eyebrow">Ideas put into practice</p>
<h2 id="work-title">A look at what’s possible.</h2>
<p>
Illustrative projects created for this template. These are fictional
examples, not client case studies.
</p>
</div>
<div class="card-grid">
<article class="project card reveal">
<!-- Photo from Pixabay. -->
<img src="https://cdn.pixabay.com/photo/2019/07/14/16/27/pen-4337521_1280.jpg" alt="Pen, notebook, phone, and laptop arranged on a creative workspace" width="900" height="600" loading="lazy" decoding="async">
<div class="project-copy">
<p class="eyebrow">Sample project · Brand strategy</p>
<h3>A fresh direction for Fieldwork</h3>
<p>
A positioning and visual identity concept for an independent
workspace, centered on community and everyday creativity.
</p>
</div>
</article>
<article class="project card reveal">
<!-- Photo from Pixabay. -->
<img src="https://cdn.pixabay.com/photo/2021/06/22/06/21/laptop-6355279_1280.jpg" alt="Laptop and keyboard arranged in a modern digital workspace" width="900" height="600" loading="lazy" decoding="async">
<div class="project-copy">
<p class="eyebrow">Sample project · Digital experience</p>
<h3>A clearer welcome for Haven</h3>
<p>
A service website concept that helps a growing advisory firm
explain its expertise and guide visitors to the right conversation.
</p>
</div>
</article>
<article class="project card reveal">
<!-- Photo from Pixabay. -->
<img src="https://cdn.pixabay.com/photo/2020/02/24/16/06/whiteboard-4876651_1280.jpg" alt="Business brainstorming sketch showing teamwork, growth, and creative ideas" width="900" height="600" loading="lazy" decoding="async">
<div class="project-copy">
<p class="eyebrow">Sample project · Business consulting</p>
<h3>Making room for Grove to grow</h3>
<p>
A workshop and operating roadmap concept that brings team
responsibilities, customer priorities, and delivery plans into focus.
</p>
</div>
</article>
</div>
</div>
</section>
<section class="section" aria-labelledby="testimonials-title">
<div class="container">
<div class="section-heading reveal">
<p class="eyebrow">What a great partnership feels like</p>
<h2 id="testimonials-title">Built on trust. Shaped together.</h2>
<p>
Sample testimonials for layout demonstration only. All people,
businesses, and quotes below are fictional.
</p>
</div>
<div class="card-grid">
<figure class="card quote reveal">
<figcaption>
<span class="sample-label">Sample testimonial</span>
<strong>Maya Chen</strong>
<span>Founder, Fieldwork</span>
</figcaption>
<blockquote>
<p>
“They helped us put words to what made our business different.
For the first time, our team had a direction we could all explain.”
</p>
</blockquote>
</figure>
<figure class="card quote reveal">
<figcaption>
<span class="sample-label">Sample testimonial</span>
<strong>Daniel Reed</strong>
<span>Managing Director, Haven</span>
</figcaption>
<blockquote>
<p>
“The process was clear from the start. Every conversation moved
us toward a website that felt like us and worked for our customers.”
</p>
</blockquote>
</figure>
<figure class="card quote reveal">
<figcaption>
<span class="sample-label">Sample testimonial</span>
<strong>Amara Okafor</strong>
<span>Operations Lead, Grove</span>
</figcaption>
<blockquote>
<p>
“We finished with more than a presentation. We had a practical
plan, clear responsibilities, and the confidence to take the next step.”
</p>
</blockquote>
</figure>
</div>
</div>
</section>
<section class="section section-tint" id="faq" aria-labelledby="faq-title">
<div class="container faq-layout">
<div class="reveal">
<p class="eyebrow">A few useful answers</p>
<h2 id="faq-title">Before we get started.</h2>
<p>
Still have something on your mind?
<a href="#contact">Let’s talk.</a>
</p>
</div>
<div class="faq-list reveal">
<details>
<summary>What kinds of businesses do you work with?</summary>
<p>
Our sample service offering is designed for small businesses,
growing teams, and established organizations looking for a clearer
strategy or a stronger digital presence.
</p>
</details>
<details>
<summary>How does a project get started?</summary>
<p>
We begin with a conversation about your goals, audience, timeline,
and budget. From there, we prepare a proposed scope with
deliverables, milestones, and responsibilities.
</p>
</details>
<details>
<summary>How long does a typical project take?</summary>
<p>
A focused strategy engagement might take a few weeks; a full brand
and website project may take several months. The schedule depends
on scope, content readiness, and feedback.
</p>
</details>
<details>
<summary>How do you price your services?</summary>
<p>
Pricing is based on the work required and the agreed deliverables.
A written proposal sets out the fees, payment schedule, and any
optional extras before work begins.
</p>
</details>
<details>
<summary>Can you support us after launch?</summary>
<p>
Ongoing support can be scoped around your needs, from periodic
strategy reviews to website updates and campaign planning.
Handover and training can also be included.
</p>
</details>
</div>
</div>
</section>
<section class="section" id="contact" aria-labelledby="contact-title">
<div class="container two-column contact-layout">
<div class="reveal">
<p class="eyebrow">Your next chapter starts here</p>
<h2 id="contact-title">Let’s make your next move a good one.</h2>
<p>
Tell us what you’re working toward and where you could use a fresh perspective.
</p>
<address>
<div>
<strong>Email</strong>
<a href="mailto:hello@example.com">hello@example.com</a>
</div>
<div>
<strong>Working style</strong>
<span>Remote collaboration, wherever you work.</span>
</div>
<div>
<strong>Availability</strong>
<span>Monday–Friday, 9:00–17:00 in your chosen timezone.</span>
</div>
</address>
<p class="small">
Template contact details — replace before publishing.
</p>
</div>
<form id="contact-form" class="contact-form card reveal" aria-describedby="form-notice">
<p id="form-notice" class="form-notice">
<strong>Demo form:</strong> Nothing is sent or stored.
Sending enquiries requires a backend or form service.
Please do not enter sensitive information.
</p>
<div class="field">
<label for="name">Name <span>(required)</span></label>
<input id="name" name="name" autocomplete="name" required="" maxlength="100" aria-describedby="name-error">
<span class="field-error" id="name-error"></span>
</div>
<div class="field">
<label for="email">Email <span>(required)</span></label>
<input id="email" name="email" type="email" autocomplete="email" required="" maxlength="254" aria-describedby="email-error">
<span class="field-error" id="email-error"></span>
</div>
<div class="field">
<label for="service">Service <span>(required)</span></label>
<select id="service" name="service" required="" aria-describedby="service-error">
<option value="">Choose a service</option>
<option>Business strategy</option>
<option>Brand & positioning</option>
<option>Website design</option>
<option>Digital marketing</option>
<option>Operations consulting</option>
<option>Research & insights</option>
<option>Help me decide</option>
</select>
<span class="field-error" id="service-error"></span>
</div>
<div class="field">
<label for="message">
Tell us about your project <span>(required)</span>
</label>
<textarea id="message" name="message" rows="5" required="" minlength="20" maxlength="3000" aria-describedby="message-hint message-error"></textarea>
<small id="message-hint">
20–3,000 characters. A little context helps.
</small>
<span class="field-error" id="message-error"></span>
</div>
<button class="button" type="submit" disabled="">
Check enquiry <span aria-hidden="true">↗</span>
</button>
<p id="form-status" class="form-status" role="status" aria-live="polite" aria-atomic="true"></p>
<noscript>
<p>
This demonstration needs JavaScript for field feedback.
Nothing will be sent.
</p>
</noscript>
</form>
</div>
</section>
</main>
<footer class="site-footer">
<div class="container">
<div class="footer-grid">
<div>
<a class="logo" href="#top">
<span aria-hidden="true">✳</span> northstar.
</a>
<p>
Clear thinking. Thoughtful design.<br>
A practical partner for your next chapter.
</p>
<p class="small">Fictional business website template.</p>
</div>
<nav aria-label="Footer navigation">
<strong>Explore</strong>
<a href="#about">About us</a>
<a href="#services">Services</a>
<a href="#work">Our work</a>
<a href="#contact">Contact</a>
</nav>
<nav aria-label="Social links">
<strong>Connect</strong>
<!-- REPLACE: example.com URLs with real social profile URLs. -->
<a href="https://example.com/linkedin">LinkedIn ↗</a>
<a href="https://example.com/instagram">Instagram ↗</a>
<a href="https://example.com/facebook">Facebook ↗</a>
<span class="small">Sample social links</span>
</nav>
</div>
<div class="footer-bottom">
<p>
© <span id="copyright-year">2026</span> Northstar.
All rights reserved.
</p>
<a href="#top">Back to the beginning ↑</a>
</div>
</div>
</footer>
<a class="back-to-top" href="#top" aria-label="Back to top" hidden="">↑</a>
</body></html>
CSS source
:root {
--navy: #17213b;
--muted: #536078;
--indigo: #4843cf;
--indigo-dark: #3530a5;
--tint: #f5f6fb;
--line: #dfe3ed;
--white: #fff;
--radius: 18px;
--shadow: 0 12px 35px rgb(23 33 59 / 6%);
}
/* Base */
* {
box-sizing: border-box;
}
html {
scroll-padding-top: 110px;
}
body {
margin: 0;
color: var(--navy);
background: var(--white);
font-family: Inter, ui-sans-serif, system-ui, -apple-system,
BlinkMacSystemFont, "Segoe UI", sans-serif;
line-height: 1.7;
}
img {
display: block;
max-width: 100%;
height: auto;
background: #e4e7f0;
color: var(--navy);
}
a {
color: var(--indigo);
text-underline-offset: 4px;
}
button,
input,
select,
textarea {
font: inherit;
}
button,
a,
input,
select,
textarea {
-webkit-tap-highlight-color: transparent;
}
button {
cursor: pointer;
}
a,
button {
touch-action: manipulation;
}
a:focus-visible,
button:focus-visible,
summary:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
outline: 3px solid #7c62e8;
outline-offset: 5px;
}
h1,
h2,
h3,
p,
figure,
blockquote {
margin: 0;
}
h1,
h2,
h3 {
line-height: 1.15;
letter-spacing: -.035em;
}
h1 {
font-size: clamp(2.6rem, 6vw, 5rem);
font-weight: 750;
}
h2 {
font-size: clamp(2rem, 4vw, 3.1rem);
max-width: 760px;
}
h3 {
font-size: 1.2rem;
letter-spacing: -.02em;
}
p {
color: var(--muted);
}
p + p {
margin-top: 1rem;
}
[hidden] {
display: none !important;
}
/* Shared layout */
.container {
width: min(1120px, calc(100% - 40px));
margin-inline: auto;
min-width: 0;
}
.section {
padding-block: 76px;
}
.section-tint {
background: var(--tint);
}
.two-column {
display: grid;
gap: 40px;
align-items: center;
}
.two-column > * {
min-width: 0;
}
.eyebrow {
text-transform: uppercase;
font-size: .73rem;
letter-spacing: .14em;
font-weight: 750;
color: var(--indigo);
margin-bottom: 18px;
}
.section-heading {
max-width: 720px;
margin-bottom: 36px;
}
.section-heading > p:last-child,
h2 + p {
margin-top: 20px;
}
.button-row {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-top: 30px;
}
.button {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 16px;
min-height: 50px;
padding: 13px 22px;
border: 1px solid var(--indigo);
border-radius: 8px;
background: var(--indigo);
color: var(--white);
font-weight: 650;
font-size: .9rem;
text-decoration: none;
transition: background .2s, transform .2s;
}
.button:hover {
background: var(--indigo-dark);
transform: translateY(-2px);
}
.button-outline {
background: transparent;
color: var(--navy);
border-color: #c9cedd;
}
.button-outline:hover {
background: #edf0f9;
}
.button-small {
min-height: 44px;
padding: 10px 18px;
}
.button:disabled {
opacity: .6;
cursor: not-allowed;
transform: none;
}
.text-link {
display: inline-block;
padding-block: 12px;
font-weight: 650;
}
.small,
small {
font-size: .8rem;
}
.skip-link {
position: fixed;
top: 8px;
left: 16px;
z-index: 100;
transform: translateY(-160%);
padding: 12px 20px;
background: var(--navy);
color: white;
border-radius: 6px;
}
.skip-link:focus {
transform: translateY(0);
}
/* Header */
.site-header {
position: sticky;
top: 0;
z-index: 20;
background: rgb(255 255 255 / 97%);
border-bottom: 1px solid var(--line);
}
.header-inner {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 14px;
padding-block: 18px;
}
.logo {
display: inline-flex;
gap: 7px;
align-items: center;
color: var(--navy);
font-size: 1.55rem;
font-weight: 800;
letter-spacing: -.06em;
text-decoration: none;
white-space: nowrap;
}
.logo > span:first-child,
.logo-dot {
color: var(--indigo);
}
#primary-nav {
display: flex;
flex-wrap: wrap;
gap: 8px 20px;
align-items: center;
width: 100%;
}
#primary-nav > a:not(.button) {
color: var(--navy);
font-size: .9rem;
text-decoration: none;
padding-block: 10px;
}
#primary-nav > a:hover {
text-decoration: underline;
}
.menu-toggle {
min-height: 44px;
padding: 8px 12px;
border: 1px solid var(--line);
border-radius: 6px;
background: white;
color: var(--navy);
}
.menu-toggle span {
margin-left: 8px;
}
/* Hero and highlights */
.hero {
padding-top: 54px;
}
.hero h1 span {
color: var(--indigo);
}
.lead {
font-size: 1.1rem;
max-width: 560px;
margin-top: 24px;
}
.hero-note {
font-size: .8rem;
margin-top: 22px;
}
.hero-visual {
position: relative;
padding-bottom: 16px;
}
.hero-visual img {
width: 100%;
aspect-ratio: 6 / 5;
object-fit: cover;
border-radius: 24px 24px 70px 24px;
}
.image-caption {
position: absolute;
bottom: 0;
left: 12px;
right: 12px;
display: flex;
gap: 10px;
align-items: center;
padding: 15px 18px;
background: white;
border: 1px solid var(--line);
border-radius: 10px;
box-shadow: var(--shadow);
font-size: .76rem;
font-weight: 600;
}
.status-dot {
width: 9px;
height: 9px;
flex-shrink: 0;
background: var(--indigo);
border-radius: 50%;
}
.highlights {
border-block: 1px solid var(--line);
background: var(--tint);
padding-block: 30px;
}
.highlight-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 24px;
}
.highlight-grid strong,
.highlight-grid span {
display: block;
}
.highlight-grid strong {
font-size: .95rem;
}
.highlight-grid span {
font-size: .8rem;
color: var(--muted);
margin-top: 5px;
}
/* About */
.section-image {
width: 100%;
aspect-ratio: 10 / 9;
object-fit: cover;
border-radius: var(--radius);
}
.strengths {
list-style: none;
padding: 0;
margin: 24px 0 12px;
}
.strengths li {
position: relative;
padding-left: 27px;
margin-block: 12px;
font-size: .92rem;
}
.strengths li::before {
content: "✓";
position: absolute;
left: 0;
color: var(--indigo);
font-weight: 800;
}
/* Services, reasons, projects, testimonials */
.card-grid {
display: grid;
gap: 22px;
}
.card {
background: white;
border: 1px solid var(--line);
border-radius: var(--radius);
padding: 28px;
box-shadow: var(--shadow);
min-width: 0;
}
.card h3 {
margin-bottom: 14px;
}
.card p {
font-size: .93rem;
}
.icon {
display: grid;
place-items: center;
width: 46px;
height: 46px;
border-radius: 12px;
background: #eeedfc;
color: var(--indigo);
font-size: 1.7rem;
margin-bottom: 26px;
}
.reasons-grid {
display: grid;
gap: 32px;
}
.reason {
border-top: 1px solid var(--line);
padding-top: 24px;
}
.number {
display: block;
color: var(--indigo);
font-size: .85rem;
font-weight: 700;
margin-bottom: 22px;
}
.reason h3 {
margin-bottom: 14px;
}
.reason p {
font-size: .92rem;
}
.project {
padding: 0;
overflow: hidden;
}
.project img {
width: 100%;
aspect-ratio: 3 / 2;
object-fit: cover;
}
.project-copy {
padding: 25px;
}
.project .eyebrow {
font-size: .65rem;
margin-bottom: 14px;
}
.quote {
display: flex;
flex-direction: column;
gap: 22px;
}
.quote figcaption {
display: grid;
line-height: 1.6;
font-size: .85rem;
}
.quote figcaption > span:last-child {
color: var(--muted);
}
.sample-label {
font-size: .67rem;
text-transform: uppercase;
letter-spacing: .1em;
color: var(--indigo);
margin-bottom: 14px;
}
.quote blockquote p {
font-size: 1rem;
color: var(--navy);
}
/* FAQ */
.faq-layout {
display: grid;
gap: 36px;
}
.faq-list {
border-top: 1px solid var(--line);
}
details {
border-bottom: 1px solid var(--line);
padding: 20px 0;
}
summary {
cursor: pointer;
font-weight: 650;
min-height: 44px;
padding: 8px 30px 8px 0;
position: relative;
list-style: none;
line-height: 1.5;
}
summary::-webkit-details-marker {
display: none;
}
summary::after {
content: "+";
position: absolute;
right: 5px;
top: 6px;
color: var(--indigo);
font-size: 1.3rem;
}
details[open] summary::after {
content: "−";
}
details p {
padding: 12px 24px 8px 0;
font-size: .92rem;
}
/* Contact */
address {
font-style: normal;
margin-top: 30px;
}
address > div {
display: grid;
gap: 4px;
margin-block: 20px;
}
address strong {
font-size: .85rem;
}
address span,
address a {
font-size: .95rem;
overflow-wrap: anywhere;
}
.contact-layout {
align-items: start;
}
.contact-form {
padding: 24px;
}
.form-notice {
font-size: .8rem !important;
padding: 15px;
background: var(--tint);
border-radius: 8px;
margin-bottom: 24px;
}
.field {
display: grid;
gap: 7px;
margin-bottom: 18px;
}
label {
font-size: .85rem;
font-weight: 650;
}
label span {
font-weight: 400;
color: var(--muted);
}
input,
select,
textarea {
width: 100%;
min-width: 0;
min-height: 48px;
border: 1px solid #aeb6c8;
border-radius: 7px;
padding: 11px 13px;
color: var(--navy);
background: white;
}
textarea {
resize: vertical;
}
input[aria-invalid="true"],
select[aria-invalid="true"],
textarea[aria-invalid="true"] {
border: 2px solid #aa233b;
}
.field-error {
color: #a11c34;
font-size: .8rem;
}
.field-error:empty {
display: none;
}
.field small {
color: var(--muted);
}
.form-status {
font-size: .88rem;
margin-top: 15px;
overflow-wrap: anywhere;
}
.form-status:empty {
display: none;
}
/* Footer */
.site-footer {
padding: 55px 0 22px;
background: var(--navy);
color: white;
}
.site-footer .logo {
color: white;
}
.site-footer p,
.site-footer .small {
color: #c5cbd9;
}
.site-footer p {
margin-top: 16px;
font-size: .9rem;
}
.footer-grid {
display: grid;
gap: 30px;
}
.footer-grid nav {
display: grid;
align-content: start;
gap: 6px;
}
.site-footer a:not(.logo) {
color: #e4e7f1;
font-size: .85rem;
min-height: 36px;
display: inline-flex;
align-items: center;
}
.footer-grid strong {
font-size: .85rem;
margin-bottom: 10px;
}
.footer-bottom {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
gap: 12px;
border-top: 1px solid #3d465b;
padding-top: 22px;
margin-top: 40px;
}
.footer-bottom p {
margin: 0;
font-size: .77rem;
}
.back-to-top {
position: fixed;
right: 20px;
bottom: 20px;
width: 46px;
height: 46px;
display: grid;
place-items: center;
background: var(--indigo);
color: white;
border: 2px solid white;
border-radius: 50%;
box-shadow: var(--shadow);
text-decoration: none;
z-index: 15;
}
/* Content stays visible if JavaScript is unavailable. */
.reveal {
opacity: 1;
transform: none;
}
/* Tablet */
@media (min-width: 640px) {
.container {
width: min(1120px, calc(100% - 64px));
}
.card-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.reasons-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.footer-grid {
grid-template-columns: 2fr 1fr 1fr;
}
.contact-form {
padding: 32px;
}
}
/* Desktop */
@media (min-width: 900px) {
.section {
padding-block: 100px;
}
.two-column {
grid-template-columns: 1.05fr 1fr;
gap: 64px;
}
.header-inner {
flex-wrap: nowrap;
}
#primary-nav {
width: auto;
gap: 28px;
}
.menu-toggle {
display: none;
}
.hero {
padding-block: 75px 85px;
}
.hero .two-column {
gap: 50px;
}
.highlight-grid {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
.highlight-grid > div + div {
border-left: 1px solid var(--line);
padding-left: 24px;
}
.card-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.reasons-grid {
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 28px;
}
.faq-layout {
grid-template-columns: 1fr 1.4fr;
gap: 80px;
}
.contact-layout {
gap: 90px;
}
}
/* Motion preferences */
@media (prefers-reduced-motion: no-preference) {
html {
scroll-behavior: smooth;
}
.reveal.is-pending {
opacity: 0;
transform: translateY(18px);
}
.reveal {
transition: opacity .55s ease, transform .55s ease;
}
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
scroll-behavior: auto !important;
transition: none !important;
animation: none !important;
}
}
JavaScript source
"use strict";
const motionPreference = window.matchMedia(
"(prefers-reduced-motion: reduce)"
);
const desktop = window.matchMedia("(min-width: 900px)");
const menuButton = document.querySelector(".menu-toggle");
const navigation = document.querySelector("#primary-nav");
let menuOpen = false;
/* Mobile navigation */
function setMenu(open, restoreFocus = false) {
menuOpen = open && !desktop.matches;
menuButton.setAttribute("aria-expanded", String(menuOpen));
menuButton.hidden = desktop.matches;
navigation.hidden = !desktop.matches && !menuOpen;
if (restoreFocus) menuButton.focus();
}
setMenu(false);
desktop.addEventListener("change", () => {
const active = document.activeElement;
const focusWouldHide =
!desktop.matches && navigation.contains(active);
setMenu(false);
if (focusWouldHide) {
menuButton.focus();
} else if (desktop.matches && active === menuButton) {
navigation.querySelector("a").focus();
}
});
menuButton.addEventListener("click", () => {
setMenu(!menuOpen);
});
document.addEventListener("keydown", (event) => {
if (event.key === "Escape" && menuOpen) {
setMenu(false, true);
}
});
document.addEventListener("click", (event) => {
if (menuOpen && !event.target.closest(".site-header")) {
setMenu(false);
}
});
/* Smooth navigation, destination focus, and normal anchor history */
document.querySelectorAll('a[href^="#"]').forEach((link) => {
link.addEventListener("click", (event) => {
if (
event.ctrlKey ||
event.metaKey ||
event.shiftKey ||
event.altKey
) {
return;
}
const target = document.getElementById(
link.getAttribute("href").slice(1)
);
if (!target) return;
event.preventDefault();
setMenu(false);
if (!target.hasAttribute("tabindex")) {
target.setAttribute("tabindex", "-1");
target.addEventListener(
"blur",
() => target.removeAttribute("tabindex"),
{ once: true }
);
}
target.focus({ preventScroll: true });
target.scrollIntoView({
behavior: motionPreference.matches ? "instant" : "smooth",
block: "start"
});
if (location.hash !== link.hash) {
history.pushState(null, "", link.hash);
}
});
});
/*
* Native details/summary supplies keyboard interaction and expanded state.
* JavaScript keeps at most one FAQ answer open.
*/
const faqs = document.querySelectorAll(".faq-list details");
faqs.forEach((item) => {
item.addEventListener("toggle", () => {
if (item.open) {
faqs.forEach((other) => {
if (other !== item) other.open = false;
});
}
});
});
/* Frontend-only form validation */
const form = document.querySelector("#contact-form");
const fields = [...form.querySelectorAll("input, select, textarea")];
const formStatus = document.querySelector("#form-status");
let attempted = false;
// JavaScript provides the field-level messages instead of browser popups.
form.noValidate = true;
function validate(field) {
const value = field.value.trim();
let message = "";
if (!value) {
message = {
name: "Please enter your name.",
email: "Please enter your email address.",
service: "Please choose a service.",
message: "Please describe your project."
}[field.id];
} else if (
field.id === "email" &&
field.validity.typeMismatch
) {
message =
"Enter a valid email address, such as name@example.com.";
} else if (
field.id === "message" &&
value.length < 20
) {
message =
"Please add at least 20 characters of project detail.";
} else if (
field.maxLength > 0 &&
value.length > field.maxLength
) {
message =
`Please use no more than ${field.maxLength} characters.`;
}
document.getElementById(
`${field.id}-error`
).textContent = message;
field.setAttribute("aria-invalid", String(Boolean(message)));
return !message;
}
fields.forEach((field) => {
field.addEventListener("blur", () => {
if (attempted || field.value) validate(field);
});
field.addEventListener("input", () => {
formStatus.textContent = "";
if (
attempted ||
field.getAttribute("aria-invalid") === "true"
) {
validate(field);
}
});
field.addEventListener("change", () => {
if (attempted) validate(field);
});
});
form.addEventListener("submit", (event) => {
event.preventDefault();
attempted = true;
const results = fields.map(validate);
const firstInvalid = results.indexOf(false);
if (firstInvalid !== -1) {
const count = results.filter((valid) => !valid).length;
formStatus.textContent =
`Please correct ${count} ` +
`${count === 1 ? "field" : "fields"} ` +
"before checking your enquiry.";
fields[firstInvalid].focus();
return;
}
// No network request, storage, or false delivery confirmation.
formStatus.textContent =
"Your entries pass the demo checks. Nothing has been sent or stored. " +
"Connect a backend or form service to deliver enquiries.";
});
// Enable submission only after the demo handler is attached.
form.querySelector('button[type="submit"]').disabled = false;
/* Copyright year */
document.querySelector("#copyright-year").textContent =
new Date().getFullYear();
/* Back to top */
const backToTop = document.querySelector(".back-to-top");
function updateBackToTop() {
// Keep a focused control available until focus moves elsewhere.
backToTop.hidden =
window.scrollY < 600 &&
document.activeElement !== backToTop;
}
window.addEventListener("scroll", updateBackToTop, {
passive: true
});
backToTop.addEventListener("blur", updateBackToTop);
updateBackToTop();
/* Subtle entrances, with progressive enhancement */
const reveals = document.querySelectorAll(".reveal");
let entranceObserver;
function configureEntrances() {
entranceObserver?.disconnect();
reveals.forEach((element) => {
element.classList.remove("is-pending");
});
if (
motionPreference.matches ||
!("IntersectionObserver" in window)
) {
return;
}
entranceObserver = new IntersectionObserver(
(entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.remove("is-pending");
observer.unobserve(entry.target);
}
});
},
{ threshold: 0.08 }
);
reveals.forEach((element) => {
// Do not hide content already visible when JavaScript runs.
if (
element.getBoundingClientRect().top > window.innerHeight
) {
element.classList.add("is-pending");
entranceObserver.observe(element);
}
});
}
configureEntrances();
motionPreference.addEventListener("change", configureEntrances);
How it works
The project is organized into three separate files: index.html for the page structure, style.css for the design and responsive layouts, and script.js for interactive behavior. The contact form is a frontend demo and requires a backend or form service to deliver enquiries.
Try a change
Choose Edit code, make a small change, then press Run to preview it.
Use the source Copy buttons, choose Edit code to open the editor, or Download ZIP to save the project after a six-second countdown.

Discussion (0)
Leave a comment