WIP marquee and some refactoring
This commit is contained in:
parent
eca995ca2c
commit
2ca3604414
6 changed files with 406 additions and 127 deletions
|
|
@ -14,124 +14,4 @@ import MarqueeContent from "./MarqueeContent.astro";
|
||||||
<MarqueeContent/>
|
<MarqueeContent/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script src="@config/styling/marquee_old.ts"/>
|
||||||
const marquee = document.getElementById("marquee-content")!;
|
|
||||||
marquee.style.setProperty("--scroll", "0")
|
|
||||||
marquee.style.setProperty("--mult", "1")
|
|
||||||
|
|
||||||
window.addEventListener("load", autoplayInit, false);
|
|
||||||
let videos = document.getElementsByClassName("marquee-item-content") as HTMLCollectionOf<HTMLVideoElement>;
|
|
||||||
const videoCount = videos.length;
|
|
||||||
const lastVideoIndex = videos[videos.length - 1]
|
|
||||||
let currentVideoIndex = 0;
|
|
||||||
let currentVideo: HTMLVideoElement | null = null;
|
|
||||||
|
|
||||||
function autoplayInit() {
|
|
||||||
setActiveVideo(0);
|
|
||||||
currentVideo.play();
|
|
||||||
currentVideo.style.animationPlayState = "running";
|
|
||||||
}
|
|
||||||
|
|
||||||
function setActiveVideo(index: number) {
|
|
||||||
if (currentVideo) {
|
|
||||||
currentVideo.pause();
|
|
||||||
}
|
|
||||||
|
|
||||||
currentVideoIndex = index;
|
|
||||||
if (index === videos.length - 1) {
|
|
||||||
console.log("shift")
|
|
||||||
|
|
||||||
const shifted = videos.item(0);
|
|
||||||
marquee.firstElementChild.remove()
|
|
||||||
const video_div = document.createElement("div");
|
|
||||||
|
|
||||||
video_div.classList.add("marquee-item");
|
|
||||||
console.log("shift: ",video_div.classList.toString())
|
|
||||||
|
|
||||||
shifted.setAttribute("data-media-index", (index+1).toString())
|
|
||||||
|
|
||||||
video_div.appendChild(shifted);
|
|
||||||
marquee.appendChild(video_div);
|
|
||||||
videos = document.getElementsByClassName("marquee-item-content") as HTMLCollectionOf<HTMLVideoElement>;
|
|
||||||
currentVideoIndex = index - 1;
|
|
||||||
console.log("shift", marquee)
|
|
||||||
}
|
|
||||||
currentVideo = videos[currentVideoIndex];
|
|
||||||
|
|
||||||
currentVideo.currentTime = 0;
|
|
||||||
marquee.style.setProperty("--scroll", `-${currentVideoIndex*100}%`)
|
|
||||||
marquee.style.setProperty("--mult", `${currentVideoIndex + 1}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
function offsetCarousel(offset: number) {
|
|
||||||
let nextIndex = currentVideoIndex + offset;
|
|
||||||
// if (nextIndex < 0) nextIndex += videoCount;
|
|
||||||
// nextIndex = nextIndex % videoCount;
|
|
||||||
setActiveVideo(nextIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
const intersectionOptions = {
|
|
||||||
root: marquee,
|
|
||||||
rootMargin: "0px",
|
|
||||||
threshold: 0.1,
|
|
||||||
};
|
|
||||||
const mult = marquee.style.getPropertyValue("--mult") ?? 0;
|
|
||||||
|
|
||||||
const observer = new IntersectionObserver((entries) => {
|
|
||||||
entries.forEach((entry) => {
|
|
||||||
const video = entry.target as HTMLVideoElement;
|
|
||||||
|
|
||||||
if (!entry.isIntersecting) {
|
|
||||||
video.pause();
|
|
||||||
|
|
||||||
video.style.animationName = "none";
|
|
||||||
void video.offsetWidth;
|
|
||||||
|
|
||||||
video.style.animationName = "fade";
|
|
||||||
video.style.animationDuration = "0.3s";
|
|
||||||
video.style.animationTimingFunction = "ease-in-out";
|
|
||||||
video.style.animationFillMode = "forwards";
|
|
||||||
video.style.animationDirection = "reverse";
|
|
||||||
} else if (video === currentVideo) {
|
|
||||||
video.play();
|
|
||||||
|
|
||||||
video.style.animationName = "none";
|
|
||||||
void video.offsetWidth;
|
|
||||||
|
|
||||||
video.style.animationName = "fade";
|
|
||||||
video.style.animationDuration = "0.3s";
|
|
||||||
video.style.animationTimingFunction = "ease-in-out";
|
|
||||||
video.style.animationFillMode = "forwards";
|
|
||||||
video.style.animationPlayState = "running";
|
|
||||||
video.style.animationDirection = "normal";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, intersectionOptions);
|
|
||||||
|
|
||||||
for (const video of videos) {
|
|
||||||
observer.observe(video);
|
|
||||||
|
|
||||||
video.addEventListener("ended", () => {
|
|
||||||
// The "ended" event might just mean its buffering.
|
|
||||||
if (video == currentVideo && video.duration !== 0 && video.currentTime === video.duration) {
|
|
||||||
offsetCarousel(1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let wasPaused = false;
|
|
||||||
document.addEventListener("visibilitychange", () => {
|
|
||||||
if (currentVideo) {
|
|
||||||
if (document.hidden) {
|
|
||||||
wasPaused = currentVideo.paused;
|
|
||||||
currentVideo.pause();
|
|
||||||
} else if (!wasPaused) {
|
|
||||||
currentVideo.play();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// left-right buttons
|
|
||||||
document.getElementById("marquee-scroll-left")!.addEventListener("mousedown", () => offsetCarousel(-1));
|
|
||||||
document.getElementById("marquee-scroll-right")!.addEventListener("mousedown", () => offsetCarousel(1));
|
|
||||||
</script>
|
|
||||||
|
|
|
||||||
200
src/config/styling/marquee.ts
Normal file
200
src/config/styling/marquee.ts
Normal file
|
|
@ -0,0 +1,200 @@
|
||||||
|
// NOTE: at last index, append every item 1 by 1 starting from 0
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const container = document.querySelector(
|
||||||
|
".marquee-item"
|
||||||
|
) as HTMLDivElement;
|
||||||
|
const scroller = document.querySelector(
|
||||||
|
".marquee-content"
|
||||||
|
) as HTMLDivElement;
|
||||||
|
if (!scroller) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sections = Array.from(
|
||||||
|
scroller.querySelectorAll(".marquee-item")
|
||||||
|
);
|
||||||
|
|
||||||
|
const smoothFactor = 0.05;
|
||||||
|
const touchSensitivity = 2.5;
|
||||||
|
const bufferSize = 2;
|
||||||
|
|
||||||
|
let targetScrollX = 0;
|
||||||
|
let currentScrollX = 0;
|
||||||
|
let isAnimating = false;
|
||||||
|
|
||||||
|
let isDown = false;
|
||||||
|
let lastTouchX = 0;
|
||||||
|
let touchVelocity = 0;
|
||||||
|
let lastTouchTime = 0;
|
||||||
|
|
||||||
|
const lerp = (start: number, end: number, factor: number) =>
|
||||||
|
start + (end - start) * factor;
|
||||||
|
|
||||||
|
const setupScroll = () => {
|
||||||
|
scroller.querySelectorAll(".clone").forEach(clone => {
|
||||||
|
clone.remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
const originalSections = Array.from(
|
||||||
|
scroller.querySelectorAll(".marquee-item:not(.clone)")
|
||||||
|
);
|
||||||
|
|
||||||
|
const templateSections =
|
||||||
|
originalSections.length > 0 ? originalSections : sections;
|
||||||
|
|
||||||
|
let sequenceWidth = 0;
|
||||||
|
templateSections.forEach(section => {
|
||||||
|
sequenceWidth += parseFloat(
|
||||||
|
window.getComputedStyle(section).width
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create clones before original sections
|
||||||
|
for (let i = -bufferSize; i < 0; i++) {
|
||||||
|
templateSections.forEach((section, index) => {
|
||||||
|
const clone = section.cloneNode(true) as HTMLDivElement;
|
||||||
|
clone.classList.add("clone");
|
||||||
|
clone.setAttribute("data-clone-index", `${i}-${index}`);
|
||||||
|
scroller.appendChild(clone);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add original sections if none exist
|
||||||
|
if (originalSections.length === 0) {
|
||||||
|
templateSections.forEach((section, index) => {
|
||||||
|
const clone = section.cloneNode(true) as HTMLDivElement;
|
||||||
|
clone.setAttribute("data-clone-index", `0-${index}`);
|
||||||
|
scroller.appendChild(clone);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create clones after original sections
|
||||||
|
for (let i = 1; i <= bufferSize; i++) {
|
||||||
|
templateSections.forEach((section, index) => {
|
||||||
|
const clone = section.cloneNode(true) as HTMLDivElement;
|
||||||
|
clone.classList.add("clone");
|
||||||
|
clone.setAttribute("data-clone-index", `${i}-${index}`);
|
||||||
|
scroller.appendChild(clone);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
scroller.style.width = `${sequenceWidth * (1 + bufferSize * 2)}px`;
|
||||||
|
targetScrollX = sequenceWidth * bufferSize;
|
||||||
|
currentScrollX = targetScrollX;
|
||||||
|
scroller.style.transform = `translateX(-${currentScrollX}px)`;
|
||||||
|
|
||||||
|
return sequenceWidth;
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkBoundaryAndReset = (sequenceWidth: number) => {
|
||||||
|
if (currentScrollX > sequenceWidth * (bufferSize + 0.5)) {
|
||||||
|
targetScrollX -= sequenceWidth;
|
||||||
|
currentScrollX -= sequenceWidth;
|
||||||
|
scroller.style.transform = `translateX(-${currentScrollX}px)`;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentScrollX < sequenceWidth * (bufferSize - 0.5)) {
|
||||||
|
targetScrollX += sequenceWidth;
|
||||||
|
currentScrollX += sequenceWidth;
|
||||||
|
scroller.style.transform = `translateX(-${currentScrollX}px)`;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const animate = (
|
||||||
|
sequenceWidth: number,
|
||||||
|
forceProgressReset = false
|
||||||
|
) => {
|
||||||
|
currentScrollX = lerp(
|
||||||
|
currentScrollX,
|
||||||
|
targetScrollX,
|
||||||
|
smoothFactor
|
||||||
|
);
|
||||||
|
scroller.style.transform = `translateX(-${currentScrollX}px)`;
|
||||||
|
|
||||||
|
if (Math.abs(targetScrollX - currentScrollX) > 0.01) {
|
||||||
|
requestAnimationFrame(() => animate(sequenceWidth));
|
||||||
|
} else {
|
||||||
|
isAnimating = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialize
|
||||||
|
const sequenceWidth = setupScroll();
|
||||||
|
|
||||||
|
// Wheel event
|
||||||
|
container.addEventListener(
|
||||||
|
"wheel",
|
||||||
|
e => {
|
||||||
|
e.preventDefault();
|
||||||
|
targetScrollX += e.deltaY;
|
||||||
|
|
||||||
|
const needsReset = checkBoundaryAndReset(sequenceWidth);
|
||||||
|
|
||||||
|
if (!isAnimating) {
|
||||||
|
isAnimating = true;
|
||||||
|
requestAnimationFrame(() =>
|
||||||
|
animate(sequenceWidth, needsReset)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ passive: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
// Touch events
|
||||||
|
container.addEventListener("touchstart", e => {
|
||||||
|
isDown = true;
|
||||||
|
lastTouchX = e.touches[0].clientX;
|
||||||
|
lastTouchTime = Date.now();
|
||||||
|
targetScrollX = currentScrollX;
|
||||||
|
});
|
||||||
|
|
||||||
|
container.addEventListener("touchmove", e => {
|
||||||
|
if (!isDown) return;
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const currentTouchX = e.touches[0].clientX;
|
||||||
|
const touchDelta = lastTouchX - currentTouchX;
|
||||||
|
|
||||||
|
targetScrollX += touchDelta * touchSensitivity;
|
||||||
|
|
||||||
|
const currentTime = Date.now();
|
||||||
|
const timeDelta = currentTime - lastTouchTime;
|
||||||
|
if (timeDelta > 0) {
|
||||||
|
touchVelocity = (touchDelta / timeDelta) * 15;
|
||||||
|
}
|
||||||
|
lastTouchX = currentTouchX;
|
||||||
|
lastTouchTime = currentTime;
|
||||||
|
|
||||||
|
const needsReset = checkBoundaryAndReset(sequenceWidth);
|
||||||
|
if (!isAnimating) {
|
||||||
|
isAnimating = true;
|
||||||
|
requestAnimationFrame(() =>
|
||||||
|
animate(sequenceWidth, needsReset)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
container.addEventListener("touchend", () => {
|
||||||
|
isDown = false;
|
||||||
|
|
||||||
|
if (Math.abs(touchVelocity) > 0.1) {
|
||||||
|
targetScrollX += touchVelocity * 20;
|
||||||
|
|
||||||
|
const decayVelocity = () => {
|
||||||
|
touchVelocity *= 0.95;
|
||||||
|
|
||||||
|
if (Math.abs(touchVelocity) > 0.1) {
|
||||||
|
targetScrollX += touchVelocity;
|
||||||
|
requestAnimationFrame(decayVelocity);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
requestAnimationFrame(decayVelocity);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
144
src/config/styling/marquee_old.ts
Normal file
144
src/config/styling/marquee_old.ts
Normal file
|
|
@ -0,0 +1,144 @@
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const marquee = document.getElementById("marquee-content")!;
|
||||||
|
marquee.style.setProperty("--scroll", "0");
|
||||||
|
|
||||||
|
window.addEventListener("load", autoplayInit, false);
|
||||||
|
let videos = document.getElementsByClassName(
|
||||||
|
"marquee-item-content"
|
||||||
|
) as HTMLCollectionOf<HTMLVideoElement>;
|
||||||
|
let vid_containers = document.getElementsByClassName(
|
||||||
|
"marquee-item"
|
||||||
|
) as HTMLCollectionOf<HTMLDivElement>;
|
||||||
|
|
||||||
|
let currentVideoIndex = 0;
|
||||||
|
let currentVideo: HTMLVideoElement | null = null;
|
||||||
|
|
||||||
|
function autoplayInit() {
|
||||||
|
setActiveVideo(0);
|
||||||
|
if (currentVideo) {
|
||||||
|
currentVideo.play();
|
||||||
|
currentVideo.style.animationPlayState = "running";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setActiveVideo(index: number) {
|
||||||
|
if (currentVideo) {
|
||||||
|
currentVideo.pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
currentVideoIndex = index;
|
||||||
|
currentVideo = videos[currentVideoIndex];
|
||||||
|
|
||||||
|
currentVideo.currentTime = 0;
|
||||||
|
marquee.style.setProperty("--scroll", `-${index * 100}%`);
|
||||||
|
marquee.style.setProperty("--mult", `${index + 1}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function offsetCarousel(offset: number) {
|
||||||
|
let nextIndex = currentVideoIndex + offset;
|
||||||
|
|
||||||
|
if (nextIndex === videos.length - 1) {
|
||||||
|
nextIndex = shiftItems(nextIndex);
|
||||||
|
marquee.style.setProperty(
|
||||||
|
"--scroll",
|
||||||
|
`-${(nextIndex - 1) * 100}%`
|
||||||
|
);
|
||||||
|
marquee.style.setProperty("--mult", `${nextIndex - 1}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: previous behavior
|
||||||
|
// nextIndex = nextIndex % videos.length;
|
||||||
|
|
||||||
|
setActiveVideo(nextIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
function shiftItems(index: number) {
|
||||||
|
const vid_arr = Array.from(vid_containers);
|
||||||
|
const shifted = vid_arr.shift()! as HTMLDivElement;
|
||||||
|
|
||||||
|
shifted.setAttribute("clone", "");
|
||||||
|
|
||||||
|
marquee.firstElementChild?.remove();
|
||||||
|
marquee.appendChild(shifted);
|
||||||
|
|
||||||
|
videos = marquee.getElementsByClassName(
|
||||||
|
"marquee-item-content"
|
||||||
|
) as HTMLCollectionOf<HTMLVideoElement>;
|
||||||
|
vid_containers = document.getElementsByClassName(
|
||||||
|
"marquee-item"
|
||||||
|
) as HTMLCollectionOf<HTMLDivElement>;
|
||||||
|
return index - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const intersectionOptions = {
|
||||||
|
root: marquee,
|
||||||
|
rootMargin: "0px",
|
||||||
|
threshold: 0.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
const observer = new IntersectionObserver(entries => {
|
||||||
|
entries.forEach(entry => {
|
||||||
|
const video = entry.target as HTMLVideoElement;
|
||||||
|
|
||||||
|
if (!entry.isIntersecting) {
|
||||||
|
video.pause();
|
||||||
|
|
||||||
|
video.style.animationName = "none";
|
||||||
|
void video.offsetWidth;
|
||||||
|
|
||||||
|
video.style.animationName = "fade";
|
||||||
|
video.style.animationDuration = "0.3s";
|
||||||
|
video.style.animationTimingFunction = "ease-in-out";
|
||||||
|
video.style.animationFillMode = "forwards";
|
||||||
|
video.style.animationDirection = "reverse";
|
||||||
|
} else if (video === currentVideo) {
|
||||||
|
video.play();
|
||||||
|
|
||||||
|
video.style.animationName = "none";
|
||||||
|
void video.offsetWidth;
|
||||||
|
|
||||||
|
video.style.animationName = "fade";
|
||||||
|
video.style.animationDuration = "0.3s";
|
||||||
|
video.style.animationTimingFunction = "ease-in-out";
|
||||||
|
video.style.animationFillMode = "forwards";
|
||||||
|
video.style.animationPlayState = "running";
|
||||||
|
video.style.animationDirection = "normal";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, intersectionOptions);
|
||||||
|
|
||||||
|
for (const video of videos) {
|
||||||
|
observer.observe(video);
|
||||||
|
|
||||||
|
video.addEventListener("ended", () => {
|
||||||
|
// The "ended" event might just mean its buffering.
|
||||||
|
if (
|
||||||
|
video === currentVideo &&
|
||||||
|
video.duration !== 0 &&
|
||||||
|
video.currentTime === video.duration
|
||||||
|
) {
|
||||||
|
offsetCarousel(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let wasPaused = false;
|
||||||
|
document.addEventListener("visibilitychange", () => {
|
||||||
|
if (currentVideo) {
|
||||||
|
if (document.hidden) {
|
||||||
|
wasPaused = currentVideo.paused;
|
||||||
|
currentVideo.pause();
|
||||||
|
} else if (!wasPaused) {
|
||||||
|
currentVideo.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// left-right buttons
|
||||||
|
document
|
||||||
|
.getElementById("marquee-scroll-left")!
|
||||||
|
.addEventListener("mousedown", () => offsetCarousel(-1));
|
||||||
|
document
|
||||||
|
.getElementById("marquee-scroll-right")!
|
||||||
|
.addEventListener("mousedown", () => offsetCarousel(1));
|
||||||
|
});
|
||||||
52
src/config/styling/progressBars.ts
Normal file
52
src/config/styling/progressBars.ts
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
let currentProgressScale = 0;
|
||||||
|
let targetProgressScale = 0;
|
||||||
|
let lastPercentage = 0;
|
||||||
|
const progressCounter = document.querySelector(
|
||||||
|
".progress-counter h1"
|
||||||
|
);
|
||||||
|
const progressBar = document.querySelector(
|
||||||
|
".progress-bar"
|
||||||
|
) as HTMLDivElement;
|
||||||
|
|
||||||
|
const updateProgress = (
|
||||||
|
sequenceWidth: number,
|
||||||
|
forceReset = false
|
||||||
|
) => {
|
||||||
|
const basePosition = sequenceWidth * bufferSize;
|
||||||
|
const currentPosition =
|
||||||
|
(currentScrollX - basePosition) % sequenceWidth;
|
||||||
|
let percentage = (currentPosition / sequenceWidth) * 100;
|
||||||
|
|
||||||
|
if (percentage < 0) {
|
||||||
|
percentage = 100 + percentage;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isWrapping =
|
||||||
|
(lastPercentage > 80 && percentage < 20) ||
|
||||||
|
(lastPercentage < 20 && percentage > 80) ||
|
||||||
|
forceReset;
|
||||||
|
|
||||||
|
progressCounter.textContent = `${Math.round(percentage)}`;
|
||||||
|
targetProgressScale = percentage / 100;
|
||||||
|
|
||||||
|
if (isWrapping) {
|
||||||
|
currentProgressScale = targetProgressScale;
|
||||||
|
progressBar.style.transform = `scaleX(${currentProgressScale})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastPercentage = percentage;
|
||||||
|
};
|
||||||
|
updateProgress(sequenceWidth, true);
|
||||||
|
progressBar.style.transform = `scaleX(${currentProgressScale})`;
|
||||||
|
updateProgress(sequenceWidth, forceProgressReset);
|
||||||
|
|
||||||
|
if (!forceProgressReset) {
|
||||||
|
currentProgressScale = lerp(
|
||||||
|
currentProgressScale,
|
||||||
|
targetProgressScale,
|
||||||
|
smoothFactor
|
||||||
|
);
|
||||||
|
}
|
||||||
|
progressBar.style.transform = `scaleX(${currentProgressScale})`;
|
||||||
|
});
|
||||||
|
|
@ -29,17 +29,18 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-block: var(--lg);
|
margin-block: var(--xl);
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
scroll-snap-type: x mandatory;
|
scroll-snap-type: x mandatory;
|
||||||
}
|
}
|
||||||
|
|
||||||
.marquee-content {
|
.marquee-content {
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
will-change: transform;
|
||||||
|
transform: translateX(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.marquee-item {
|
.marquee-item {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ html {
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|
||||||
height: 100svh;
|
height: 100svh;
|
||||||
|
width: 100svw;
|
||||||
|
max-width: 100svw;
|
||||||
|
|
||||||
font-synthesis: none;
|
font-synthesis: none;
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue