今日のポイントは、実験的なCSS専用の画像ギャラリーを構築することです。また、機能クエリの有用性についても見ていきましょう。
ある日、私はデザイナーの友達に、彼女の作成しているウェブサイトに関して意見を求められました。そのサイトは、中古のCNCマシンを販売している会社のためのものだったのですが、サイトにはスライダー付きの画像ギャラリーが使われていたのです。
スライダー付きの画像ギャラリーを使用する目的は、バイヤーが可能な限り多くの角度とクローズアップからマシンを見れるようにするためです。また、Javascriptを使わずにそれを構築することも、完璧に可能であることがわかりました。
では、スライダー付きの画像ギャラリーに必要なものを解説しましょう。
ギャラリーを常に他のすべての画像のサムネイルと同様に、適度に大きいサイズで表示する必要があります。表示された画像はクリックされるサムネイルに対応し、サムネイルはギャラリーのナビゲーションになります。
これはスライダー付きの画像ギャラリーのタイプの1つにすぎず、そのようなコンポーネントには無数の動作があり、構築するのには異なった手法が必要になることを心に留めておいてください。上記で説明したものに関連する、目的動作を達成するためのCSSプロパティは次のとおりです。
- ・フレックスボックス
- ・ビューポートパーセンテージ単位
- ・オブジェクトフィット
- ・変換
- ・アニメーション
- ・:target
- ・:not()
私が実験したかったのは、ビューポートのサイズがどのように変化したとしても、元の画像にアスペクト比を維持すること、そして画像ギャラリーがビューポートの境界を決して超えないことが可能かということでした。
<div class="container"> | |
<ul class="slides"> | |
<li id="slide1"><img src="https://cdn.rawgit.com/huijing/filerepo/gh-pages/lw1.jpg" alt="" /></li> | |
<li id="slide2"><img src="https://cdn.rawgit.com/huijing/filerepo/gh-pages/lw2.jpg" alt="" /></li> | |
<li id="slide3"><img src="https://cdn.rawgit.com/huijing/filerepo/gh-pages/lw3.jpg" alt="" /></li> | |
<li id="slide4"><img src="https://cdn.rawgit.com/huijing/filerepo/gh-pages/lw4.jpg" alt="" /></li> | |
<li id="slide5"><img src="https://cdn.rawgit.com/huijing/filerepo/gh-pages/lw5.jpg" alt="" /></li> | |
</ul> | |
<ul class="thumbnails"> | |
<li><a href="#slide1"><img src="https://cdn.rawgit.com/huijing/filerepo/gh-pages/lw1.jpg" /></a></li> | |
<li><a href="#slide2"><img src="https://cdn.rawgit.com/huijing/filerepo/gh-pages/lw2.jpg" /></a></li> | |
<li><a href="#slide3"><img src="https://cdn.rawgit.com/huijing/filerepo/gh-pages/lw3.jpg" /></a></li> | |
<li><a href="#slide4"><img src="https://cdn.rawgit.com/huijing/filerepo/gh-pages/lw4.jpg" /></a></li> | |
<li><a href="#slide5"><img src="https://cdn.rawgit.com/huijing/filerepo/gh-pages/lw5.jpg" /></a></li> | |
</ul> | |
</div> |
サムネイルと表示画像は同じですが、その理由は、とにかく表示画像を読みこむ必要があったので、それをサムネイルに使用して、応じてスタイルを変更する方がよさそうだったためです。そうすれば、サムネイル用に画像を準備する必要がなくなります。
表示イメージにはすべてIDがあり、対応するサムネイルにはそのIDのhrefが付いています。これは:target疑似クラスセレクタが動作するために必要なのです。これにより、フラグメント識別子を含むURIのターゲット要素にスタイルを適用することができます。
.thumbnails { | |
display: flex; | |
flex-direction: column; | |
line-height: 0; | |
li { | |
flex: auto; | |
} | |
a { | |
display: block; | |
} | |
img { | |
width: 30vmin; | |
height: 20vmin; | |
object-fit: cover; | |
object-position: top; | |
} | |
} |
画像ギャラリーを常にビューポートの範囲内に保つコツは、vmin単位です。これは、ビューポートの幅または高さのいずれか小さい方の1%を表します。ギャラリーの高さを100vminに設定しても、ギャラリーがビューポートをオーバーフローすることはありません。
.slides { | |
overflow: hidden; | |
width: 75vmin; | |
height: 100vmin; | |
li { | |
width: 75vmin; | |
height: 100vmin; | |
position: absolute; | |
z-index: 1; | |
} | |
img { | |
height: 100vmin; | |
object-fit: cover; | |
object-position: top; | |
} | |
} |
スライダーには、CSSの変換とアニメーションの助けを借りて実現できる滑り効果もあります。この技術の前提は、すべての表示画像を高さの100%上方に平行移動させ、それぞれのサムネイルがクリックされたときに元の位置に戻すことです。
.slides li:target { | |
z-index: 3; | |
-webkit-animation: slide 1s 1; | |
} | |
.slides li:not(:target) { | |
-webkit-animation: hidden 1s 1; | |
} | |
@keyframes slide { | |
0% { | |
transform: translateY(-100%); | |
} | |
100% { | |
transform: translateY(0%); | |
} | |
} | |
@keyframes hidden { | |
0% { | |
z-index: 2; | |
} | |
100% { | |
z-index: 2; | |
} | |
} |
最終結果は以下のCodePenで確認できます。コードは多くなく、IE9でも動作しています。なぜなら:targetセレクタはIE9以降にサポートされているからです。 IE11はオブジェクトフィットをサポートしていないので、サムネイルのアスペクト比は非常に歪んでいます。
機能クエリ
ブラウザごとに画像のレンダーリングが異なることがあるため、機能クエリを使わない手はありません。このCSS専用の画像ギャラリーでは、サポートされている最小のプロパティはobject-fitで、次にビューポイントパーセンテージレングスが続きます。このアプローチの背後にあるロジックは、構築しようとしている機能に不可欠なプロパティを評価し、サポートレイヤを細分化する方法を決定するためのものです。
基本的なフォールバック
最終的な結果を念頭に置いて始めますが、私はいつも、フィーチャのないコンポーネントのベースレベルのディスプレイであるスペクトルの反対側を考えています。このような画像ギャラリーの場合、画像を羅列することになります。
.container { | |
text-align: center; | |
margin-bottom: 1em; | |
ul, | |
li, | |
img { | |
margin: 0; | |
} | |
li { | |
list-style: none; | |
} | |
.slides { | |
display: inline-block; | |
li { | |
width: 10em; | |
display: inline-block; | |
vertical-align: top; | |
margin-bottom: 0.25em; | |
} | |
img { | |
width: 100%; | |
} | |
} | |
.thumbnails { | |
display: none; | |
} | |
} |
最も基本的なレイアウト手法のinline-blockを使用して、ビューポートサイズが大きくなるにつれて、画像を列に表示することを選択しました。これがスライダーではなければ、サムネイルは必要なかったでしょう。
@media screen and (min-width: 540px) { | |
@supports (object-fit:cover) { | |
.container { | |
display: flex; | |
justify-content: center; | |
margin-bottom: 1em; | |
.slides { | |
overflow: hidden; | |
width: 50vmax; | |
li { | |
position: absolute; | |
z-index: 1; | |
width: initial; | |
display: block; | |
} | |
li:target { | |
z-index: 3; | |
-webkit-animation: fade 0.6s 1; | |
} | |
li:not(:target) { | |
-webkit-animation: hidden 0.6s 1; | |
} | |
img { | |
width: auto; | |
object-fit: cover; | |
object-position: top; | |
height: 37.5vmax; | |
} | |
} | |
.thumbnails { | |
display: flex; | |
flex-direction: column; | |
line-height: 0; | |
width: 13.75vmax; | |
li { | |
flex: auto; | |
} | |
a { | |
display: block; | |
border: 0; | |
} | |
img { | |
object-fit: cover; | |
object-position: top; | |
width: 100%; | |
height: calc(37.5vmax / 7); | |
} | |
} | |
} | |
} | |
} |
スライダーが動作するために必要なCSSプロパティの簡単な実験により、サポートされていないプロパティがobject-fitであることがわかっています。すべてのコンテキストが異なるため、機能クエリで何を使用するのかについて厳格なルールはありません。このケースでは、機能クエリの基礎としてobject-fitを使用しました。
必要なCSSプロパティに対して、作成しようとしているコンポーネントが段階的に機能する場合もあります。その場合、複数の機能クエリがあり、より詳細な機能サポートが提供されます。
最後に
さまざまなCSSプロパティを実験する中で、機能クエリはコードの中で重要な要素であることがわかりました。皆さんにもぜひ一度試してみていただきたいです。
▼こちらの記事もおすすめです!
・ECサイトにおける商品画像ギャラリーのベストプラクティス【商品画像の表示のコツとは…】
・【PhotoshopなしでOK!】CSSでできるシンプルな画像加工9選
※本記事はBuilding a CSS-only image gallery (with fallbacks)を翻訳・再構成したものです。