utility
apple/Macサイトでみられるスクロール量によるオブジェクト拡大
作成日: 2025年6月21日
表題の件、そのためのスクリプト他を作った。
落ちてるもんではなく、都合にあったもん。入れ子がビューポートに入ったら発火し、スクロール量に応じ拡大する。
サンプル
スクロールするためのマージン
スクロールするためのマージン
スクロールするためのマージン
スクロールするためのマージン
スクロールするためのマージン
スクロールするためのマージン
スクロールするためのマージン
スクロールするためのマージン
スクロールするためのマージン
スクロールするためのマージン

以下コード
<script>
// Set minimum and maximum scale values
const MIN_SCALE = 0.5;
let MAX_SCALE; // Max scale dynamically set based on device
function setMaxScaleBasedOnDevice() {
const screenWidth = window.innerWidth;
if (screenWidth < 768) { // Smartphone (e.g., less than 768px)
MAX_SCALE = 1.0; // Smaller scale for smartphones
} else { // PC (768px or more)
MAX_SCALE = 1.0; // Standard scale for PCs
}
}
setMaxScaleBasedOnDevice();
window.addEventListener('resize', setMaxScaleBasedOnDevice);
function updateImageScale(element, container) {
const rect = container.getBoundingClientRect();
const viewportHeight = window.innerHeight;
const animationStartPoint = viewportHeight;
const animationEndPoint = 0;
const containerTop = rect.top;
let progress = 1 - (containerTop - animationEndPoint) / (animationStartPoint - animationEndPoint);
progress = Math.max(0, Math.min(1, progress));
const scale = MIN_SCALE + (MAX_SCALE - MIN_SCALE) * progress;
element.style.setProperty('--current-scale', scale);
}
const observerOptions = {
root: null,
rootMargin: '0px',
threshold: 0
};
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
const container = entry.target;
const image = container.querySelector('img');
if (!image) return; // Do nothing if no image is found
if (entry.isIntersecting) {
const scrollHandler = () => updateImageScale(image, container);
window.addEventListener('scroll', scrollHandler);
container._scrollHandler = scrollHandler;
updateImageScale(image, container);
} else {
if (container._scrollHandler) {
window.removeEventListener('scroll', container._scrollHandler);
container._scrollHandler = null;
}
const rect = container.getBoundingClientRect();
const viewportHeight = window.innerHeight;
if (rect.bottom <= 0) {
image.style.setProperty('--current-scale', MAX_SCALE);
} else if (rect.top >= viewportHeight) {
image.style.setProperty('--current-scale', MIN_SCALE);
}
}
});
}, observerOptions);
// Add all .scroll-effect elements to be observed
document.querySelectorAll('.scroll-effect').forEach(element => {
observer.observe(element);
});
</script>
<style>
<!--
.scroll-effect {
position:relative;
display:inline-block;
width:100%;
max-width:1000px;
text-align:center;
}
.scroll-effect img {
width: 100%;
height: auto;
transform: scale(var(--current-scale, 1));
transform-origin: center bottom;
transition: transform 0.05s linear;
object-fit: cover;
}
-->
</style>
属性はscript css共に適宜変更。