Files
luxury-detailing-maine/reviews.html
T

391 lines
12 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="description"
content="Luxury Detailing Maine provides mobile professional car cleaning services in the Portland Area"
/>
<title>Luxury Detailing Maine</title>
<link href="css/style.css" rel="stylesheet" />
<link href="css/hamburger.css" rel="stylesheet" />
<!-- juxtapose is the image slider / comparison tool-->
<link href="css/juxtapose.css" rel="stylesheet" />
<style>
h1 {
margin-bottom: 5rem;
}
.jx-handle, .jx-arrow {
background-color: rgba(0,0,0,0);
}
/** REVIEWS */
#reviews {
margin-top: 7rem;
}
#reviewContainer {
display: flex;
flex-wrap: wrap;
gap: 4rem;
width: 90%;
align-items: center;
justify-content: space-evenly;
}
/** REVIEW CARD */
.review-card {
display: flex;
flex-direction: column;
justify-content: flex-start;
padding: 3rem;
border: 2px solid var(--gold);
border-radius: 1rem;
box-shadow: 3px 3px 0px var(--gold);
color: white;
}
.review-card-head {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-bottom: 1rem;
color: var(--gold);
}
.review-card-head a {
color: var(--gold);
transition: 0.2s ease;
}
.review-card-head a:hover {
color: white;
}
.review-card-head-left {
word-wrap: none;
text-align: left;
}
.review-card-head-right {
word-wrap: none;
text-align: right;
}
.review-card-body {
max-height: 15rem;
overflow: hidden;
text-align: left;
color: white;
align-self: center;
}
/** GALLERY */
#gallery {
min-width: 100%;
}
#imageContainer {
display: flex;
width: 90%;
flex-direction: column;
align-items: center;
}
/** JUXTAPOSE ADJUSTMENTS **/
a.jx-knightlab div.knightlab-logo {
visibility: hidden !important;
display: none !important;
}
a.jx-knightlab span.juxtapose-name {
visibility: hidden !important;
display: none !important;
}
.juxtapose img {
border-radius: 2rem;
}
div.jx-slider {
color: var(--gold) !important;
}
div.jx-arrow.jx-left {
border-color: transparent var(--gold) transparent transparent;
}
div.jx-arrow.jx-right {
border-color: transparent transparent transparent var(--gold);
}
/************************************************
* DESKTOP RULES
*/
@media screen and (min-width: 851px) {
#reviewContainer {
flex-direction: row;
}
.review-card {
width: 25rem;
height: min-content;
}
#imageContainer {
flex-direction: row;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 2rem;
}
}
/*
* MOBILE RULES
*/
@media screen and (max-width: 850px) {
#reviewContainer {
flex-direction: column;
}
#imageContainer {
flex-direction: column;
gap: 2rem;
}
.review-card {
width: 90%;
}
}
</style>
</head>
<body>
<a href="#main-content" class="skipLink">Skip to main content</a>
<header>
<div class="banner" role="banner">
<a href="index.html" class="logo" aria-label="Company Logo">LUXURY DETAILING</a>
<button
id="hamburger"
aria-label="Toggle mobile navigation menu"
aria-expanded="false"
>
<span></span>
<span></span>
<span></span>
</button>
<nav>
<a class="navLink" role="navigation" href="ceramic-coating.html">Ceramic Coating</a>
<a class="navLink" role="navigation" href="services.html">Services</a>
<a class="navLink" role="navigation" href="reviews.html"style="color: white" >Reviews</a>
<a class="navLink" role="navigation" href="contact.html">About</a>
</nav>
</div>
</header>
<main id="main-content">
<section id="reviews">
<div id="reviewContainer"></div>
</section>
<section id="gallery">
<h1>Before & After Gallery</h1>
<div id="imageContainer">
<div class="juxtapose">
<img src="assets/img/before1.jpg" alt="An interior of a car trunk, the floor is covered in dirt and grass." />
<img src="assets/img/after1.jpg" alt="The same trunk after it has been restored to like-new condition." />
</div>
<div class="juxtapose">
<img src="assets/img/before1.jpg" alt="An interior of a car trunk, the floor is covered in dirt and grass." />
<img src="assets/img/after1.jpg" alt="The same trunk after it has been restored to like-new condition." />
</div>
</div>
</section>
</main>
<footer>
<div id="footer-left">
&copy;Luxury Detailing Maine 2025<br />
All rights reserved<br />
Portland, ME
</div>
<div id="footer-right">
207-807-6770<br />
example@email.com<br />
<a
href="https://www.instagram.com/luxurydetailingmaine/"
target="_blank"
>@luxurydetailingmaine</a
>
</div>
</footer>
<script src="js/hamburger.js"></script>
<script src="js/juxtapose.js"></script>
<script>
/** script stuff just for this page */
/**
* PAGE INITIALIZATION
*/
window.onload = function () {
// first, insert all reviews into the page
insertReviews(reviewData);
// set listener to jiggle gallery sliders
window.addEventListener("scroll", jiggleGallerySliders);
// set listener for overriding gallery resize logic
window.addEventListener("resize", setImageSizes);
// initialize gallery image sizes by feigning resize upon init
setImageSizes();
};
/** review insertion **/
let reviewData = [
{
name: "Sasha M.",
text: "Easy 5 stars! Aden was super communicative, very friendly, and reasonably priced. I would happily recommend this service to anyone.",
url: "https://share.google/zUOkEQ8Yv6L2SkBsl",
},
{
name: "Tara D.",
text: "Job well done, had the vehicle feeling like it just left the lot. You can tell Aden takes great pride and is meticulous in his work.",
url: "https://share.google/uMS4Ma8xT7ARAqf83",
},
{
name: "Adrianna W.",
text: "Luxury Detailing's Platinum package delivered incredible results, making my partners 15-year-old car look and feel brand new! ",
url: "https://maps.app.goo.gl/vS8JALPh7KNquRyu7",
},
{
name: "Adam B.",
text: "Aden was easy to work with and did a fantastic job! Im very happy with how the detailing came out! Great pricing for high quality service!",
url: "https://maps.app.goo.gl/Hp9Ez5hEF9iTrbn6A"
},
{
name: "Jacob S.",
text: "I could not be happier with the way my Cadillac turned out. The way the car came out is a night and day difference.",
url: "https://share.google/89ldWBKVGn25MnHPM"
},
{
name: "Sasha P.",
text: "I second all of the great reviews so far, Aden really is that great! My car really does look practically brand new.",
url: "https://share.google/ax2m0N4UOjvWIJpo0",
},
];
function insertReviews(reviews) {
let target = document.getElementById("reviewContainer");
for (let i = 0; i < reviews.length; i++) {
let review = reviews[i];
let linkedName = `<a href="${review.url}" class="reviewLink" target="_blank">${review.name}</a>`;
// load reviews
target.insertAdjacentHTML(
"beforeend",
`
<div class="review-card">
<div class="review-card-head">
<span class="review-card-head-left">
${review.url ? linkedName : review.name}
</span>
<span class="review-card-head-right">
<span>★</span>
<span>★</span>
<span>★</span>
<span>★</span>
<span>★</span>
</span>
</div>
<p class="review-card-body">
${review.text}
</p>
</div>
`
);
}
}
/** gallery jiggling (indicate to user they can slide images for comparison) */
let jiggled = false;
let jiggleThreshold = document.getElementById("reviews").offsetHeight + 25;
async function jiggleGallerySliders() {
// ensure jiggle only triggers once, upon gallery scrolling into view
if (window.scrollY < jiggleThreshold || jiggled) return;
jiggled = true;
// once user scrolls to gallery, move sliders on all images right a bit
let sliders = juxtapose.sliders;
for (let i = 0; i < sliders.length; i++) {
sliders[i].updateSlider(60, true);
}
// sleep, then slide them all left,
await new Promise(resolve => setTimeout(resolve, 1000));
for (let i = 0; i < sliders.length; i++) {
sliders[i].updateSlider(40, true);
}
// sleep, then reset sliders back to center
await new Promise(resolve => setTimeout(resolve, 1000));
for (let i = 0; i < sliders.length; i++) {
sliders[i].updateSlider(50, true);
}
}
/** override logic for 'juxtapose' image scaling based on window size changes */
function setImageSizes() {
let isDesktop = window.innerWidth > 850;
let newWidth, newHeight;
if (isDesktop) {
newWidth = window.innerWidth * 0.40;
}
else {
newWidth = window.innerWidth * 0.80;
}
// keep all images at 1:1.2 ratio
newHeight = newWidth * 1.2;
// resize iframes
let images = document.getElementsByClassName("juxtapose");
for (let i = 0; i < images.length; i++) {
images[i].style.width = newWidth + 'px';
images[i].style.height = newHeight + 'px';
}
// resize images in each iframe to match new dimensions
images = document.getElementsByClassName("jx-image");
for (let i = 0; i < images.length; i++) {
images[i].style.width = newWidth + 'px';
images[i].style.height = newHeight + 'px';
images[i].children[0].style.width = newWidth + 'px';
images[i].children[0].style.height = newHeight + 'px';
}
// quickly touch every iframe/slider (otherwise the images glitch out until user interacts with slider again)
let sliders = juxtapose.sliders;
for (let i = 0; i < sliders.length; i++) {
sliders[i].updateSlider(sliders[i].sliderPosition.replace("%", ""), true);
}
}
</script>
<!-- <script src="https://cdn.knightlab.com/libs/juxtapose/latest/js/juxtapose.min.js"></script> -->
</body>
</html>