Skip to content
Open
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"liveServer.settings.port": 5501
}
84 changes: 83 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,83 @@
# js-project-business-site
# 🎵 NeonSound Studios
_A responsive business website project_

## 📖 About the project
NeonSound Studios is a fictional recording studio website created as a **student project**.
The goal was to practice building a **responsive, accessible business site** using only **HTML5, CSS3, and JavaScript**.

The site demonstrates:
- Semantic HTML structure
- Responsive layouts (320px → 1600px)
- Flexbox & CSS Grid usage
- Interactive hamburger menu
- Hero section with video background
- Card grid with featured studios
- Signup form with multiple input types
- Footer with copyright

---

## 🚀 Features
### Navigation & Layout
- Responsive **navigation bar** with desktop links and a mobile hamburger menu
- Hamburger button toggles menu open/close with JavaScript
- Accessible `aria-expanded` state and icon swap (☰ → ✖)

### Hero
- Video background with overlay heading & tagline

### Featured Studios
- **Card grid** layout:
- 1 column on mobile
- 2 columns on tablets
- 4 columns on desktop
- Cards have shadows and hover lift effect

### Signup Form
Form submits with `method="POST"` to [https://httpbin.org/anything](https://httpbin.org/anything).
Includes:
- Text input (name)
- Email input
- Password input (minlength validation)
- Radio button group (role)
- Checkbox (terms required)
- Submit button

### Footer
- Simple centered footer with copyright

---

## 📱 Responsiveness
The design is responsive and functional across viewports **320px–1600px**:
- Flexbox used for header and menus
- CSS Grid used for cards
- Media queries for breakpoints at 640px and 1024px

---

## ✨ Stretch Goals (VG level)
This project includes more than the required 4 stretch goals:
- Card shadows for a “Polaroid” feel
- Cards centered on page
- Focus glow on input fields (`:focus` selector)
- Basic HTML5 form validation (required, minlength, type checks)
- Animated hamburger icon (bars ↔ close X)
- CSS animations (sound-wave EQ animation)

---

## 🛠️ Technologies
- **HTML5** (semantic structure)
- **CSS3** (variables, Flexbox, Grid, media queries, transitions, keyframes)
- **JavaScript (ES6)** for hamburger menu interactivity

---

## 📂 Project Structure
├── README.md
├── hero-music-video.mp4
├── hero-png
├── index.html # main HTML page
├── style.css # styles and responsive design
└── script.js # hamburger menu interactivity
Binary file added hero-music-video.mp4
Binary file not shown.
Binary file added hero.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
188 changes: 188 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
<!DOCTYPE html>
<html lang="sv">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>NeonSound</title>
<!-- Font Awesome for hamburger icon -->
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"
crossorigin="anonymous"
referrerpolicy="no-referrer"
/>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="page">
<!-- Header -->
<header class="site-header">
<div class="brand">
NeonSound
<div class="sound-waves" aria-hidden="true">
<div></div><div></div><div></div><div></div><div></div>
</div>
</div>

<!-- Hamburger menu (mobile) -->
<button
class="hamburger-menu"
aria-controls="primary-nav"
aria-expanded="false"
aria-label="Toggle menu">
<i class="fa-solid fa-bars"></i>
</button>

<!-- Navigation -->
<nav id="primary-nav" class="desktop-nav" aria-label="mainmenu">
<a href="#">Home</a>
<a href="#">Studios</a>
<a href="#">Gear</a>
<a href="#">About us</a>
<a href="#">Contact</a>
</nav>
</header>

<!-- Hero with video/image -->
<section class="hero-container">
<div class="hero-overlay">
<h1>Make records that glow</h1>
<p>Premium recording rooms, world-class gear, same-day bookings.</p>
</div>
<!-- If hero video don't play, show poster/image -->
<video class="hero-video" autoplay muted loop playsinline poster="hero.png">
<source src="hero-music-video.mp4" type="video/mp4" />
</video>
</section>

<!-- Main content -->
<main class="container">
<h2 class="section-title">Featured studios</h2>

<section class="card-grid">
<article class="card">
<img
src="https://plus.unsplash.com/premium_photo-1681628689764-444e8ca06570?w=600&auto=format&fit=crop&q=60"
alt="Live room for recording music" />
<div class="card-body">
<h3>Studio A — Live room</h3>
<p>Perfect for bands and live tracking with stunning room acoustics.</p>
<a class="btn" href="#">Book now</a>
</div>
</article>

<article class="card">
<img
src="https://media.istockphoto.com/id/1990228958/photo/professional-microphone-on-the-stand-recording-studio-with-acoustical-wall-panel.webp?a=1&b=1&s=612x612&w=0&k=20&c=Gj81pWhucUwMZpH_19TpRPjMxQ94rV6ouvU1IX8Uk3Q="
alt="Vocal suite for recording vocals" />
<div class="card-body">
<h3>Studio B — Vocal suite</h3>
<p>Tailored for vocals, VO and topline sessions with zero noise floor.</p>
<a class="btn" href="#">Book now</a>
</div>
</article>

<article class="card">
<img
src="https://plus.unsplash.com/premium_photo-1682124293900-54bea8ca7e9f?w=600&auto=format&fit=crop&q=60"
alt="Mix room for mixing and mastering songs" />
<div class="card-body">
<h3>Studio C — Mix room</h3>
<p>Accurate monitoring for mixing, mastering and sound design.</p>
<a class="btn" href="#">Book now</a>
</div>
</article>

<article class="card">
<img
src="https://images.unsplash.com/photo-1613329671121-5d1cf551cc3f?w=600&auto=format&fit=crop&q=60"
alt="Podcast room" />
<div class="card-body">
<h3>Podcast room</h3>
<p>Plug-and-play podcast production with multitrack capture.</p>
<a class="btn" href="#">Book now</a>
</div>
</article>
</section>
</main>

<!-- Signup Form Section -->
<section id="signup" class="container">
<h2>Sign <span class="text-blue">Up</span> for sessions &amp; news</h2>

<form class="signup-form" action="https://httpbin.org/anything" method="post">
<!-- Full name -->
<label>
<span>Full name</span>
<input
id="fullName"
name="fullName"
type="text"
placeholder="Your name"
autocomplete="name"
required />
</label>

<!-- Email -->
<label>
<span>Email</span>
<input
id="email"
name="email"
type="email"
placeholder="[email protected]"
autocomplete="email"
required />
</label>

<!-- Password -->
<label>
<span>Password</span>
<input
id="password"
name="password"
type="password"
placeholder="Min. 6 characters"
minlength="6"
autocomplete="new-password"
required />
</label>

<!-- Radio group -->
<fieldset class="choice-group">
<legend>What best describes you?</legend>

<label for="role-musician">
<input id="role-musician" type="radio" name="role" value="musician" required />
Musician
</label>

<label for="role-producer">
<input id="role-producer" type="radio" name="role" value="producer" />
Producer
</label>

<label for="role-podcaster">
<input id="role-podcaster" type="radio" name="role" value="podcaster" />
Podcaster
</label>
</fieldset>

<!-- Terms (required) -->
<label class="terms" for="terms">
<input id="terms" type="checkbox" name="terms" required />
<span>I accept the terms and privacy policy</span>
</label>

<!-- Submit -->
<button type="submit" class="send">Sign me up</button>
</form>
</section>

<footer class="site-footer">
<p>© NeonSound Studios</p>
</footer>
</div>
<script src="script.js"></script>
</body>
</html>
22 changes: 22 additions & 0 deletions script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

//hamburger menu
/*finds the button element with class .hamburger,
the <nav> element with the ID primary-nav(main menu) and
finds the <i> element inside the hamburger button (the Font Awesome icon)*/
const hamburgerBtn = document.querySelector('.hamburger-menu');
const nav = document.getElementById('primary-nav');
const icon = hamburgerBtn.querySelector('i');

/*adds a click event listener to the hamburger button
when clicked, it toggles the 'active' class on the nav element to show/hide the menu*/
hamburgerBtn.addEventListener('click', () => {
nav.classList.toggle('active');

// updates the aria-expanded attribute for accessibility
const expanded = hamburgerBtn.getAttribute('aria-expanded') === 'true' || false;
hamburgerBtn.setAttribute('aria-expanded', !expanded);

// Toggles the icon between a hamburger (fa-bars) and a close (fa-xmark) icon
icon.classList.toggle('fa-bars');
icon.classList.toggle('fa-xmark');
});
Loading