diff --git a/Notebook.md b/Notebook.md index 1841f12..2773015 100644 --- a/Notebook.md +++ b/Notebook.md @@ -710,3 +710,7 @@ We have already done some of the work for this with our dynamic scrolling. **The plan** We are going to create additional _background_ layers that will be layered on top of the actual background. We will update our JavaScript scroll event listener to control the scroll speed of each of these layers. Finally we will use CSS to ensure the layers are styled correctly to get our parallax effect. + +First I tried adding additional layers to the body however this proved difficult to control the position on various screen sizes. + + diff --git a/site.html b/site.html index b037c01..7850f56 100644 --- a/site.html +++ b/site.html @@ -233,15 +233,16 @@ - -
-
-
-
-

I made this website! Copyright Jesse M. Ellis 2024 😊

-
-
-
+
+
+
+
+
+
+

I made this website! Copyright Jesse M. Ellis 2024 😊

+
+
+
diff --git a/site.js b/site.js index 02a620e..aaf9df6 100644 --- a/site.js +++ b/site.js @@ -15,15 +15,17 @@ document.addEventListener("DOMContentLoaded", () => { const titleBox = document.querySelector(".title-box"); const aboutSection = document.querySelector("#about"); const contactSection = document.querySelector("#contact"); + const creditsSection = document.querySelector("#credits"); + const parallaxlayer1 = document.querySelector(".layer-1"); + const parallaxlayer2 = document.querySelector(".layer-2"); + const parallaxlayer3 = document.querySelector(".layer-3"); + const scrollY = window.scrollY; const aboutTop = aboutSection.getBoundingClientRect().top + scrollY; const contactTop = contactSection.getBoundingClientRect().top + scrollY; + const sectionTop = creditsSection.offsetTop; const slowScrollRate = 0.5; - - // Get viewport height for parallax background offsets - const viewportHeight = window.innerHeight; - - // Move title-box if it's above the viewport and not yet touching about-section + if (scrollY < aboutTop) { const opacity1 = scrollY / aboutTop; titleBox.style.transform = `translateY(${scrollY * slowScrollRate}px)`; @@ -32,33 +34,18 @@ document.addEventListener("DOMContentLoaded", () => { titleBox.style.transform = "translateY(0)"; titleBox.style.opacity = 0; } - - // Adjust navbar opacity when below the contact section - const contactBottom = contactTop + contactSection.offsetHeight; - if (scrollY > contactBottom) { - // Calculate opacity based on how far below the contact section we are - const fadeDistance = 100; - const distanceBelow = scrollY - contactBottom; - const opacity2 = Math.max(1 - distanceBelow / fadeDistance, 0); - navBar.style.opacity = opacity2; + + if (scrollY > contactTop) { + const opacity2 = (scrollY - contactTop) / (document.body.scrollHeight - contactTop); + navBar.style.opacity = Math.max(1 - opacity2, 0.5); } else { navBar.style.opacity = 1; } - - // Parallax background scroll rates - const body = document.body; - const bridgeScrollRate = 0.4; - const treesScrollRate = 0.5; - const castleScrollRate = 0.7; - const cloudsScrollRate = 0.9; - - body.style.backgroundPosition = ` - left ${scrollY * bridgeScrollRate + viewportHeight * 3.05}px, - left ${scrollY * treesScrollRate + viewportHeight * 2.55}px, - left ${scrollY * castleScrollRate + viewportHeight * 1.5}px, - left ${scrollY * cloudsScrollRate + viewportHeight * 0.4}px, - left 0px - `; + + const relativeScrollY = sectionTop - scrollY; + parallaxlayer1.style.transform = `translateY(${relativeScrollY * 0.2}px)`; + parallaxlayer2.style.transform = `translateY(${relativeScrollY * 0.4}px)`; + parallaxlayer3.style.transform = `translateY(${relativeScrollY * 0.6}px)`; }); // Function to load text from a file into an html component @@ -120,12 +107,10 @@ document.addEventListener("DOMContentLoaded", () => { document .getElementById("contact-form") .addEventListener("submit", async function (event) { - // Take control of form submission event.preventDefault(); const form = event.target; const formData = new FormData(form); try { - // Submit the form data using the Fetch API and catch response const response = await fetch(form.action, { method: form.method, body: formData, @@ -134,15 +119,12 @@ document.addEventListener("DOMContentLoaded", () => { }, }); if (response.ok) { - // Success! give user a message alert("Thank you! Your message has been sent."); - form.reset(); // Clear the form + form.reset(); } else { - // Fail :( give user a message alert("Oops! There was a problem submitting your form."); } } catch (error) { - // Log any errors console.error("Error:", error); alert( "There was a problem submitting your form. Please try again later." diff --git a/style.css b/style.css index c90d65b..c36dc2f 100644 --- a/style.css +++ b/style.css @@ -1,20 +1,17 @@ body { margin: 0; font-family: Arial, sans-serif; - background-image: url("../images/Bridge.png"), url("../images/Trees.png"), - url("../images/Castle.png"), url("../images/Clouds.png"), - url("../images/Moon.png"); - background-size: auto, auto, auto, auto, cover; - background-repeat: no-repeat, no-repeat, no-repeat, no-repeat, no-repeat; - background-attachment: scroll, scroll, scroll, scroll, fixed; - background-position: left 300vh, left 300vh, left 300vh, left 350vh, left top; + background-image: url("../images/Moon.png"); + background-size: cover; + background-position: left; + background-repeat: no-repeat; + background-attachment: fixed; min-width: 768px; } .page-container { max-width: 1440px; margin: 0 auto; - padding: 0 1rem; } .navbar { @@ -79,25 +76,7 @@ body { align-items: center; } -.page-bottom-section { - height: 90vh; - margin-top: 3rem; -} -.credits-section { - display: flex; - justify-content: center; - align-items: center; -} - -.credits-box { - display: flex; - background: rgba(0, 0, 0, 1); - border-radius: 100px; - width: 400px; - padding: 10px; - margin-bottom: 2rem; -} .title-box { display: flex; @@ -410,6 +389,10 @@ button:hover { /* Contact Form */ +.contact-section { + overflow: visible; +} + .contact-box { margin-top: 10rem; background: rgba(0, 0, 0, 0.8); @@ -472,6 +455,60 @@ button[type="reset"] { color: white; } +/* Credits Section - parallax background */ + +.credits-section { + position: relative; + display: flex; + height: 100vh; + min-width: 768px; + justify-content: center; + align-items: center; + overflow: visible; +} + +.credits-section .parallax-layer { + top: 0; + left: 0; + right: 0; + bottom: 0; +} + +.credits-box { + display: flex; + background: rgba(0, 0, 0, 1); + border-radius: 100px; + width: 400px; + padding: 10px; + margin-bottom: 5rem; +} + +.parallax-layer { + position: absolute; + width: 100%; + height: 100%; + background-size: cover; + background-position: left; + background-repeat: no-repeat; + min-width: 768px; + z-index: -1; +} + +.layer-1 { + background-image: url('images/Clouds.png'); + top: 0; +} + +.layer-2 { + background-image: url('images/Trees.png'); + top: 0; +} + +.layer-3 { + background-image: url('images/Bridge.png'); + top: 0; +} + /* Media Queries */ @media (min-width: 1440px) { @@ -499,7 +536,7 @@ button[type="reset"] { flex-direction: column; text-align: center; } - + .work-grid { grid-template-columns: repeat(auto-fit, minmax(510px, 1fr)); } @@ -515,13 +552,20 @@ button[type="reset"] { .about-image { margin-top: 1rem; } - + .nav-left { padding-left: 0rem; } - + .nav-right { gap: 1rem; padding-right: 5rem; } } + +@media (max-width: 768px) { + .parallax-layer { + height: 120%; + } +} +