CSSだけのスクロールパラパラ

positionプロパティでfixedを指定した要素は、親要素に指定したoverflowプロパティの指定を無視してしまうものと思っていたのだけれど、親要素にposition: relativeと、z-indexプロパティを指定していれば、overflowがちゃんと効きます!

スマホでもCSSだけでパラパラする

子要素がposition: fixedを指定した要素でも、親要素にposition: relativez-indexプロパティを指定していれば、overflowプロパティは、ちゃんと適用されるんです…X‹
ただし、それだけだとFirefoxとChromeではoverflowプロパティが効かないままなのですけれど、加えてborder-radiusプロパティを指定すれば、Chromeでoverflowプロパティが適用されるようになります(後述)X)(※それでも、Firefoxでは依然、overflowプロパティは効かないままです…:/

z-indexの値は、数値ならばなんでも大丈夫なので、ここでは0を指定します。border-radiusは、0よりも大きい値でないとダメなので、角丸にしてるのがバレないように、ごく小さい値0.1pxを指定します。

#scpr li::after {
	z-index: 0;
	position: relative;
	overflow: hidden;
	height: 240px;
	margin: 0;
	border-radius: .1px;
}

これで、iPhoneでもAndroidでもちゃんとパラパラするようになりました!

あとはこれを、background-attachmentプロパティに対応していない、iPhone全般と、Android(ただしChrome)にだけ、適用されるようにすればよいわけですね。

iPhoneやAndroidを振り分けるため、前述の「未対応のブラウザだけJavaScriptにする」の項と同じく、ユーザーエージェントでブラウザを判別する方法を使うことにします。ここでは、iPhone全般と、Android(ただしChrome)の時だけ、目印として、unsupportedというclassを付けます。

const ua = window.navigator.userAgent.toLowerCase();
const isIos = ua.indexOf("iphone") != -1 || ua.indexOf("ipad") != -1;
const isAndroid = ua.indexOf('android') != -1 && ua.indexOf('chrome') != -1;
if (isIos || isAndroid) {
	document.getElementById('scpr').classList.add('unsupported');
}

ul要素にunsupportedというclassが付いていない場合は、li要素の背景をbackground-attachmentで固定配置する方法を適用して、unsupportedというclassが付いている場合は、li要素の擬似要素をposition: fixedで固定配置する方法を適用するようにすれば、できあがり!

#scpr:not(.unsupported) li {
	background: #f5f6f8 center / 400px no-repeat fixed;
}
︙
#scpr.unsupported li::after {
	content: "";
	position: fixed;
	︙
	background: #f5f6f8 center / 400px no-repeat;
}

※ただし、デスクトップでユーザーエージェントだけ切り替えて表示した場合には、イラストが全部ハミ出して表示されます…X(

ul要素にunsupportedというclassが付いてなかったらli要素の背景で、付いてたらli要素の擬似要素と分けてることで、なんだかCSSが無駄に増えちゃってますね…。

ここは、どちらの時もli要素の擬似要素にイラストを表示することにして、unsupportedというclassが付いてなかったらbackground-attachmentプロパティfixedにして、付いてたらpositionプロパティfixedにする、という風にします。

#scpr li::after {
	content: "";
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	background: #f5f6f8 center / 400px no-repeat;
}
#scpr:not(.unsupported) li::after {
	position: absolute;
	background-attachment: fixed;
}
#scpr.unsupported li::after {
	position: fixed;
}

うん、だいぶCSSがすっきりしましたー;D