HTML
<div class="index_parallax">
<div class="caption">
<h2 class="catch rich_font"><span>Google ストリートビューで広がる、繋がる</span></h2>
</div>
<div class="overlay"></div>
<div class="bg_image"
data-parallax-image="https://ace214.com/wp-content/uploads/shutterstock_1046336572-scaled.jpg"
style="background-image: url(https://ace214.com/wp-content/uploads/shutterstock_1046336572-scaled.jpg);background-repeat: no-repeat; background-size: cover;"></div>
</div>
CSS
/* パララックス */
.index_parallax {
width: 100%;
height: 520px;
overflow: hidden;
position: relative;
/*
親要素からはみださせる場合
width: 100vw;
margin: 0 calc(49.2% - 50vw);
*/
}
.index_parallax .caption {
font-size: 22px;
color: #fff;
line-height: 1.5;
margin: auto;
z-index: 3;
text-align: center;
width: auto;
margin: 0 auto;
position: absolute;
left: 0;
right: 0;
top: 50%;
transform: translateY(-50%);
}
.index_parallax .catch {
font-size: 30px;
}
.index_parallax .catch {
margin: 0;
}
.index_parallax .catch {
font-size: 30px;
line-height: 1.5;
margin: 0 0 35px 0;
}
.rich_font,
.p-vertical {
font-family: "Hiragino Sans", "ヒラギノ角ゴ ProN", "Hiragino Kaku Gothic ProN", "游ゴシック", YuGothic, "メイリオ", Meiryo, sans-serif;
font-weight: 500;
}
.caption {
padding: 15px 0 0;
}
.index_parallax .overlay {
width: 100%;
height: 100%;
position: absolute;
top: 0px;
left: 0px;
background: rgba(0, 0, 0, 0.2);
z-index: 2;
}
.index_parallax .bg_image {
width: 100%;
height: 170%;
position: absolute;
top: 0px;
left: 0px;
z-index: 1;
}
.index_parallax .catch {
font-size: 30px;
}
.index_parallax .catch {
font-size: 30px;
line-height: 1.5;
margin: 0 0 35px 0;
}
.index_parallax .desc {
font-size: 16px;
line-height: 2.5;
}
@media screen and (max-width: 750px) {
.index_parallax {
width: auto;
height: 150px;
padding: 67px 0 67px;
}
.index_parallax .caption {
padding: 0 20px;
width: auto;
}
.index_parallax .catch {
font-size: 20px;
margin-bottom: 20px;
}
}
/* ----------------------------------------------------------------------
パララックス
---------------------------------------------------------------------- */
jQuery(function($){
var $elems = $('[data-parallax-image]');
if (!$elems.length) return;
// モバイル画像に切り替えるブレイクポイント
var mobileBreakpoint = 650;
var defaultSpeed = 0.3;
var defaultBlur = 0;
// 変数
var $window = $(window);
var $body = $('body');
var ua = window.navigator.userAgent.toLowerCase();
var elemSettings = [];
var images = [];
var mobileImages = [];
var resizeTimer = null;
var winWidth = window.innerWidth || $body.width();
var winHeight = window.innerHeight || $window.innerHeight();
// IE判別
var isIE = (ua.indexOf('msie') > -1 || ua.indexOf('trident') > -1);
// IE・Edgeの場合はsvgでぼかし
// Edgeはfilter: blur(Npx)だとフチ透過対策が効かないため。
// 2019/08時点 Chromium版EdgeはUAがEdgeではなくEdgのため対象外で問題なし。
var useSvgBlur = (isIE || ua.indexOf('edge') > -1);
// スマホ判別
var isSmartPhone = (ua.indexOf('iphone') > -1 || ua.indexOf('ipod') > -1 || ua.indexOf('android') > -1 && ua.indexOf('mobile') > -1);
// モバイル判別
var isMobile = (isSmartPhone || ua.indexOf('ipad') > -1 || ua.indexOf('android') > -1);
// ブレイクポイントによるモバイル判別
var checkParallaxMobile = function() {
var mql = window.matchMedia('(max-width: ' + mobileBreakpoint + 'px)');
return mql.matches;
};
var isParallaxMobile = checkParallaxMobile();
// SVGぼかし用SVG生成
var parallaxCreateSvg = function(src, blur) {
var svgid = Math.random().toString(36).substr(2, 9);
var $svg = $('');
return $svg;
};
// パララックススクロール処理
var parallaxBgScroll = function() {
var winScrollTop = $window.scrollTop();
$elems.each(function(i){
// パララックスなしもしくはサイズ計算が終わっていない場合は終了
if (elemSettings[i].speed === 0 || elemSettings[i].imageOffsetY === undefined) return;
// 全体ぼかしあり
if (elemSettings[i].blur) {
var $elem = $(this);
var $box = $elem.offsetParent();
var boxOffsetTop = Math.ceil($box.offset().top);
var boxHeight = $box.innerHeight();
// この領域が画面内に表示されている場合
if ((winScrollTop + winHeight > boxOffsetTop - 10) && (boxOffsetTop + boxHeight > winScrollTop + 10)) {
var offsetY = Math.round(((winScrollTop - boxOffsetTop - boxHeight / 2 + winHeight / 2) * elemSettings[i].speed - elemSettings[i].imageOffsetY) * 2) / 2;
// translate3dだとchromeで表示領域にぼかしがかかる
$elem.css('transform', 'translateY(' + offsetY + 'px)');
// オーバーレイぼかしありの場合
if (elemSettings[i].$overlayBlurInner) {
elemSettings[i].$overlayBlurInner.css('transform', 'translateY(' + offsetY + 'px)');
}
}
// 全体ぼかしなし
} else {
var $elem = $(this);
var boxOffsetTop = Math.ceil($elem.offset().top);
var boxHeight = $elem.innerHeight();
// この領域が画面内に表示されている場合
if ((winScrollTop + winHeight > boxOffsetTop - 10) && (boxOffsetTop + boxHeight > winScrollTop + 10)) {
var offsetY = Math.round(((winScrollTop - boxOffsetTop - boxHeight / 2) * elemSettings[i].speed - elemSettings[i].imageOffsetY) * 2) / 2;
$elem.css('backgroundPositionY', offsetY);
// オーバーレイぼかしありの場合
if (elemSettings[i].$overlayBlurInner) {
var overlayOffsetY = Math.round(((winScrollTop - boxOffsetTop - boxHeight / 2 + winHeight / 2) * elemSettings[i].speed - elemSettings[i].imageOffsetY) * 2) / 2;
// translate3dだとchromeで表示領域にぼかしがかかる
elemSettings[i].$overlayBlurInner.css('transform', 'translateY(' + overlayOffsetY + 'px)');
}
}
}
});
};
// 背景画像サイズ計算
var parallaxCalcBgImageSize = function(i){
var $elem = $elems.eq(i);
var img, $box, boxHeight, boxWidth, backgroundImageHeight, backgroundImageWidth;
if (isParallaxMobile && mobileImages[i].img.src) {
if (!mobileImages[i].img.complete) return;
img = mobileImages[i].img;
} else {
if (!images[i].img.complete) return;
img = images[i].img;
}
// 画像変更
if (elemSettings[i].currentImageSrc !== img.src) {
$elem.css('backgroundImage', 'url(' + img.src + ')');
elemSettings[i].currentImageSrc = img.src;
// SVGぼかしあり(全体ぼかし・オーバーレイぼかし兼用)
if (useSvgBlur && elemSettings[i].svgs) {
for (var j = 0; j < elemSettings[i].svgs.length; j++) {
elemSettings[i].svgs[j].find('image').attr('xlink:href', img.src);
}
// filter:blurのオーバーレイぼかしあり
} else if (elemSettings[i].$overlayBlurInner) {
elemSettings[i].$overlayBlurInner.css('backgroundImage', 'url(' + img.src + ')');
}
}
// 全体ぼかしあり
if (elemSettings[i].blur) {
$box = $elem.offsetParent();
boxHeight = $box.innerHeight();
boxWidth = $box.innerWidth();
// パララックス効果分込みで必要な画像の高さ
var parallaxHeight = Math.ceil(winHeight * elemSettings[i].speed + boxHeight);
// ぼかしのフチの透過領域込みのサイズ
var parallaxBlurHeight = parallaxHeight + elemSettings[i].blur * 2 * 2;
var parallaxBlurWidth = boxWidth + elemSettings[i].blur * 2 * 2;
var parallaxRatio, imgRatio;
parallaxRatio = parallaxBlurWidth / parallaxBlurWidth;
imgRatio = img.width / img.height;
// 画像の方が横長
if (parallaxRatio < imgRatio) {
backgroundImageWidth = Math.ceil(parallaxBlurHeight / img.height * img.width);
backgroundImageHeight = parallaxBlurHeight;
elemSettings[i].imageOffsetX = (backgroundImageWidth - parallaxBlurWidth) / 2 + elemSettings[i].blur * 2;
elemSettings[i].imageOffsetY = 0;
// 画像の方が縦長
} else {
backgroundImageHeight = Math.ceil(parallaxBlurWidth / img.width * img.height);
backgroundImageWidth = parallaxBlurWidth;
elemSettings[i].imageOffsetX = elemSettings[i].blur * 2;
elemSettings[i].imageOffsetY = 0;
}
$elem.css({
height: backgroundImageHeight,
width: backgroundImageWidth,
bottom: 'auto',
left: elemSettings[i].imageOffsetX * -1,
right: 'auto',
top: (backgroundImageHeight - boxHeight) / -2
});
// スクロール0時に画面内にある場合は天地位置調整
var boxOffsetTop = Math.ceil($box.offset().top);
if (boxOffsetTop + boxHeight < winHeight) {
elemSettings[i].imageOffsetY += Math.ceil((winHeight / 2 - boxOffsetTop - boxHeight / 2) * elemSettings[i].speed);
}
// ぼかしなし
} else {
$box = $elem;
boxHeight = $box.innerHeight();
boxWidth = $box.innerWidth();
// パララックス効果分込みで必要な画像の高さ
var parallaxHeight = Math.ceil(winHeight * elemSettings[i].speed + boxHeight);
var parallaxRatio, imgRatio;
parallaxRatio = boxWidth / parallaxHeight;
imgRatio = img.width / img.height;
// 画像の方が横長
if (parallaxRatio < imgRatio) {
backgroundImageHeight = parallaxHeight;
backgroundImageWidth = Math.ceil(parallaxHeight / img.height * img.width);
$elem.css('backgroundSize', backgroundImageWidth + 'px ' + parallaxHeight + 'px');
elemSettings[i].imageOffsetY = 0;
// 画像の方が縦長
} else {
$elem.css('backgroundSize', 'cover');
backgroundImageHeight = Math.ceil(boxWidth / img.width * img.height);
backgroundImageWidth = boxWidth;
elemSettings[i].imageOffsetY = (backgroundImageHeight - parallaxHeight) / 2;
}
// スクロール0時に画面内にある場合は天地位置調整
var boxOffsetTop = Math.ceil($elem.offset().top);
if (boxOffsetTop + boxHeight < winHeight) {
elemSettings[i].imageOffsetY += Math.ceil((winHeight / 2 - boxOffsetTop - boxHeight / 2) * elemSettings[i].speed);
}
}
// オーバーレイぼかしありの場合
if (elemSettings[i].$overlayBlur) {
var boxOffset = $box.offset();
elemSettings[i].$overlayBlur.each(function(){
var $this = $(this);
var offset = $this.offset();
var $inner = $this.find('.parallax-overlay-blur-inner');
$inner.css({
height: backgroundImageHeight,
width: backgroundImageWidth,
position: 'absolute',
bottom: 'auto',
right: 'auto',
left: (backgroundImageWidth - boxWidth) / -2 + boxOffset.left - offset.left,
top: (backgroundImageHeight - boxHeight) / -2 + boxOffset.top - offset.top,
});
});
}
};
// 初期化
$elems.each(function(i){
var $elem = $(this);
var src = $elem.attr('data-parallax-image');
var srcMobile = $elem.attr('data-parallax-mobile-image');
// モバイル画像のみ
if (!src && srcMobile) {
src = srcMobile;
srcMobile = null;
}
// スマホの場合は1画像のみ
if (isSmartPhone && srcMobile) {
src = srcMobile;
srcMobile = null;
}
var initialSrc = src;
// パララックススクロール係数
var speed = parseFloat($elem.attr('data-parallax-speed'));
if (isNaN(speed) || speed < 0 || speed > 1) {
speed = parseFloat(defaultSpeed) || 0;
}
// 全体ぼかし
var blur = parseFloat($elem.attr('data-parallax-blur'));
if (isNaN(blur) || blur < 0) {
blur = parseFloat(defaultBlur) || 0;
}
if (blur > 0) {
var pos = $elem.css('position');
if (pos !== 'absolute' && pos !== 'fixed') {
blur = 0;
}
}
elemSettings[i] = {
speed: speed,
blur: blur
};
// 画像オブジェクト初期化
images[i] = {};
images[i].img = new Image();
mobileImages[i] = {};
mobileImages[i].img = new Image();
// オーバーレイぼかし
var $closest, $overlayBlur;
var elemPosition = $elem.css('position');
if (elemPosition === 'relative') {
$closest = $elem;
} else if (elemPosition === 'absolute' || elemPosition === 'fixed') {
$closest = $elem.offsetParent();
}
if ($closest) {
$overlayBlur = $closest.find('[data-parallax-overlay-blur]').not('[data-parallax-overlay-blur=""], [data-parallax-overlay-blur="0"]');
}
// モバイルの場合でモバイル画像ありなら初期画像変更
if (isParallaxMobile && srcMobile) {
initialSrc = srcMobile;
}
// オーバーレイぼかしありの場合、子要素生成
if ($overlayBlur.length) {
$overlayBlur.each(function(){
var parallaxOverlayBlur= parseFloat(this.dataset.parallaxOverlayBlur);
if (isNaN(parallaxOverlayBlur) || parallaxOverlayBlur < 0) {
return;
}
var $inner = $('');
// SVGでのぼかし
if (useSvgBlur) {
var $svg = parallaxCreateSvg(initialSrc, parallaxOverlayBlur);
$inner.html($svg);
if (!elemSettings[i].svgs) {
elemSettings[i].svgs = [];
}
elemSettings[i].svgs.push = $svg;
// filter:blurでのぼかし
} else {
$inner.css({
backgroundImage: 'url(' + initialSrc + ')',
backgroundPositionX: 'center',
backgroundPositionY: 'center',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover',
filter: 'blur(' + parallaxOverlayBlur + 'px)'
});
}
$(this).css({
overflow: 'hidden',
position: 'absolute',
bottom: 0,
right: 0,
left: 0,
top: 0,
zIndex: -1
}).html($inner);
});
elemSettings[i].$overlayBlur = $overlayBlur;
elemSettings[i].$overlayBlurInner = $closest.find('.parallax-overlay-blur-inner');
}
// 全体ぼかしあり
if (elemSettings[i].blur) {
// SVGでのぼかし
if (useSvgBlur) {
var $svg = parallaxCreateSvg(initialSrc, elemSettings[i].blur);
$elem.html($svg);
if (!elemSettings[i].svgs) {
elemSettings[i].svgs = [];
}
elemSettings[i].svgs.push = $svg;
// filter:blurでのぼかし
} else {
$elem.css({
backgroundImage: 'url(' + initialSrc + ')',
backgroundPositionX: 'center',
backgroundPositionY: 'center',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover',
filter: 'blur(' + elemSettings[i].blur + 'px)'
});
}
// 全体ぼかしなし
} else {
$elem.css({
backgroundImage: 'url(' + initialSrc + ')',
backgroundPositionX: 'center',
backgroundPositionY: 'center',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover'
});
}
// モバイルの場合でモバイル画像あり
if (isParallaxMobile && srcMobile) {
// 画像を読み込んでからサイズ計算
var img = mobileImages[i].img;
img.onload = function() {
parallaxCalcBgImageSize(i);
};
img.src = srcMobile;
if (img.complete) {
parallaxCalcBgImageSize(i);
}
elemSettings[i].currentImageSrc = srcMobile;
images[i].img.src = src;
// PCの場合
} else if (src) {
// 画像を読み込んでからサイズ計算
var img = images[i].img;
img.onload = function() {
parallaxCalcBgImageSize(i);
};
img.src = src;
if (img.complete) {
parallaxCalcBgImageSize(i);
}
elemSettings[i].currentImageSrc = src;
if (srcMobile) {
mobileImages[i].img.src = srcMobile;
}
}
});
parallaxBgScroll();
$window.on('load scroll', parallaxBgScroll);
// リサイズ
$window.on('resize', function(){
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function(){
var w = window.innerWidth || $body.width();
var h = window.innerHeight || $window.innerHeight();
// モバイルでスクロール時のアドレスバー表示トグルでresizeイベントが実行されるため横幅のみで判定
if (isMobile && winWidth !== w || (!isMobile && (winWidth !== w || winHeight !== h))) {
winWidth = w;
winHeight = h;
isParallaxMobile = checkParallaxMobile();
$elems.each(function(i){
parallaxCalcBgImageSize(i);
});
parallaxBgScroll();
}
}, isIE ? 100 : 16.6666);
});
});