CSSのグラデーションとアスペクト比を使用してレスポンシブな画像効果を作成します

公開: 2022-03-10
簡単な要約↬CSSの典型的な問題は、カードなどの関連コンポーネント間で画像のアスペクト比を維持することです。 object-fitと組み合わせて新しくサポートされたaspect-ratioプロパティは、過去のこの頭痛の種に対する救済策を提供します! 余分なフレアのためのレスポンシブグラデーション画像効果を作成することに加えて、これらのプロパティの使用方法を学びましょう。

将来の画像効果に備えるために、上部に大きな画像があり、その後に見出しと説明が続くカードコンポーネントを設定します。 この設定に共通する問題は、画像が何であるか、さらに重要なのはそのサイズが何であるかを常に完全に制御できるとは限らないことです。 これは事前にトリミングすることで解決できますが、応答サイズのコンテナが原因で問題が発生する可能性があります。 その結果、カードの内容の位置が不均一になり、カードの列を提示すると本当に目立ちます。

トリミング以外の別の以前の解決策は、インラインimgから、 background-imageを介して画像を表示するためだけに存在していた空白のdivに交換することでした。 私は過去に何度もこのソリューションを実装しました。 これが持つ利点の1つは、高さゼロの要素を使用し、 padding-bottom値を設定するアスペクト比の古いトリックを使用することです。 パディング値をパーセントとして設定すると、要素の幅を基準にした最終的な計算値が得られます。 このアイデアを使用して、ビデオ埋め込みの比率を16:9に維持することもできます。この場合、パディング値は次の式で求められます: 9/16 = 0.5625 * 100% = 56.26% 。 ただし、余分な計算を必要とせず、柔軟性が高く、空のdivの代わりに実際のimgを使用して提供されるセマンティクスを維持できる2つの最新のCSSプロパティについて説明します。

まず、カードのコンテナとして順序付けされていないリストを使用するなど、HTMLのセマンティクスを定義しましょう。

 <ul class="card-wrapper"> <li class="card"> <img src="" alt=""> <h3>A Super Wonderful Headline</h3> <p>Lorem ipsum sit dolor amit</p> </li> <!-- additional cards --> </ul>

次に、 .cardコンポーネントのベースラインスタイルの最小限のセットを作成します。 カード自体の基本的な視覚スタイルをいくつか設定し、予想されるh3の見出しをすばやく更新してから、カード画像のスタイル設定を開始するための基本的なスタイルを設定します。

 .card { background-color: #fff; border-radius: 0.5rem; box-shadow: 0.05rem 0.1rem 0.3rem -0.03rem rgba(0, 0, 0, 0.45); padding-bottom: 1rem; } .card > :last-child { margin-bottom: 0; } .card h3 { margin-top: 1rem; font-size: 1.25rem; } img { border-radius: 0.5rem 0.5rem 0 0; width: 100%; } img ~ * { margin-left: 1rem; margin-right: 1rem; }

最後のルールでは、一般的な兄弟コンビネータを使用して、画像自体をカードの側面と同じ高さにしたいので、 imgに続く要素に水平方向のマージンを追加します。

そして、これまでの進歩により、次のカードの外観が得られます。

前述のベースラインスタイルが適用され、マグカップの温かい飲み物の横にある小さなプレートにデザートのUnsplashからの画像が含まれている1枚のカード
前述のベースラインスタイルが適用され、マグカップの温かい飲み物の横にある小さなプレートにデザートのUnsplashからの画像が含まれている1枚のカード。 (大プレビュー)

最後に、CSSグリッドを使用してレスポンシブレイアウトを高速化するための.card-wrapperスタイルを作成します。 これにより、デフォルトのリストスタイルも削除されます。

 .card-wrapper { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(30ch, 1fr)); grid-gap: 1.5rem; }

このグリッド手法に慣れていない場合は、12列グリッドの最新のソリューションに関するチュートリアルの説明を確認してください。

これを適用し、有効なソースパスを持つ画像を含むすべてのカードを使用すると、 .card-wrapperスタイルで次のレイアウトが得られます。

カードラッパーのレイアウトスタイルが適用されているため、3枚のカードが連続して表示されます。各カードには、自然なアスペクト比が異なる固有の画像があり、最後のカードには、他のカード画像の2倍以上の高さの垂直方向の画像があります。
カードラッパーのレイアウトスタイルが適用されているため、3枚のカードが連続して表示されます。 各カードには、自然なアスペクト比が異なる固有の画像があり、最後のカードには、他のカード画像の2倍以上の高さの垂直方向の画像があります。 (大プレビュー)

プレビュー画像に示されているように、これらのベースラインスタイルは、さまざまな自然な寸法を考えると、画像を適切に含めるには十分ではありません。 これらの画像を均一かつ一貫して制約する方法が必要です。

ジャンプした後もっと! 以下を読み続けてください↓

object-fitで均一な画像サイズを有効にする

前述のように、以前にこのシナリオで更新を行って、代わりにbackground-imageを介して追加される画像を変更し、 background-size: coverを使用して画像のサイズ変更を適切に処理した可能性があります。 または、事前にトリミングを強制しようとした可能性があります(画像サイズを小さくするとパフォーマンスが向上するため、これでも価値のある目標です)。

これで、 imgタグが画像のコンテナとして機能できるようにするプロパティobject-fit利用可能になりました。 また、背景画像ソリューションと同様の効果をもたらすcover値も付属していますが、インライン画像のセマンティクスを保持するというボーナスがあります。 それを適用して、それがどのように機能するかを見てみましょう。

画像コンテナをどのように動作させるかについての追加のガイダンスとして、 heightの寸法とペアにする必要があります(すでにwidth: 100% )。 また、 max()関数を使用して、特定のコンテキストでどちらが大きいかに応じて10remまたは30vhを選択します。これにより、小さいビューポートで、またはユーザーが大きいズームを設定したときに、画像の高さが大きく縮小するのを防ぎます。

 img { /* ...existing styles */ object-fit: cover; height: max(10rem, 30vh); }

ボーナスアクセシビリティのヒントデスクトップでは常に200%と400%のズームでレイアウトをテストする必要があります。 現在、 zoomメディアクエリはありませんが、 max()などの関数はレイアウトの問題を解決するのに役立ちます。 この手法が役立つもう1つのコンテキストは、要素間の間隔です。

このアップデートにより、私たちは間違いなく物事を改善し、視覚的な結果は、古い背景画像の手法を使用するかのようになります。

これで、3枚のカードの画像の高さが均一になり、画像の内容がコンテナのように画像の中央に配置されます。
これで、3枚のカードの画像の高さが均一になり、画像の内容がコンテナのように画像の中央に配置されます。 (大プレビュー)

aspect-ratio使用した、応答性の高い一貫性のある画像サイズ設定

object-fitを単独で使用する場合、1つの欠点は、いくつかのディメンションヒントを設定する必要があることです。

aspect-ratioと呼ばれる今後のプロパティ(現在Chromiumブラウザで利用可能)により、画像のサイズを一貫して設定する機能が強化されます。

このプロパティを使用すると、明示的なサイズを設定する代わりに、画像のサイズを変更する比率を定義できます。 これらのサイズがコンテナとしての画像にのみ影響するように、引き続きobject-fitと組み合わせて使用​​します。そうしないと、画像が歪んで表示される可能性があります。

完全に更新された画像ルールは次のとおりです。

 img { border-radius: 0.5rem 0.5rem 0 0; width: 100%; object-fit: cover; aspect-ratio: 4/3; }

カードのコンテキストでは、画像の比率を4⁄3から始めますが、任意の比率を選択できます。 たとえば、正方形の場合は1⁄1 、標準のビデオ埋め込みの場合は16⁄9です。

更新されたカードは次のとおりですが、アスペクト比はobject-fitのみのheightを設定した場合の外観とほぼ一致するため、この特定のインスタンスでは視覚的な違いに気付くのはおそらく難しいでしょう。

3枚のカードの画像の幅と高さの寸法は同じですが、以前のオブジェクトフィットソリューションとは少し異なります。
3枚のカードの画像の幅と高さの寸法は同じですが、以前のオブジェクトフィットソリューションとは少し異なります。 (大プレビュー)

「アスペクト比」を設定すると、要素が拡大または縮小しても比率が維持されますが、「オブジェクトフィット」と「高さ」のみを設定すると、コンテナの寸法が変化しても画像の比率は常に流動的になります。

「「

CSSのグラデーションと関数を使用してレスポンシブ効果を追加する

さて、一貫したサイズの画像を設定する方法がわかったので、グラデーション効果を追加して画像を楽しんでみましょう。

この効果の目的は、画像がカードの内容にフェードインしているように見せることです。 グラデーションを追加するために画像を独自のコンテナでラップしたくなるかもしれませんが、画像のサイズ設定ですでに行った作業のおかげで、メインの.cardで安全に行う方法を見つけることができます。

最初のステップは、グラデーションを定義することです。 CSSカスタムプロパティを使用してグラデーションの色を追加し、青からピンクまでグラデーション効果を簡単に交換できるようにします。 カードコンテンツの背景への移行を維持し、「フェザー」エッジを作成するために、グラデーションの最後の色は常に白になります。

 .card { --card-gradient: #5E9AD9, #E271AD; background-image: linear-gradient( var(--card-gradient), white max(9.5rem, 27vh) ); /* ...existing styles */ }

しかし、待ってください—それはCSS max()関数ですか? グラデーションで? はい、それは可能です、そしてそれはこのグラデーションを敏感に効果的にする魔法です!

ただし、スクリーンショットを追加した場合、実際にはグラデーションが画像に影響を与えることはまだわかりません。 そのためには、 mix-blend-modeプロパティを取り込む必要があります。このシナリオでは、 overlay値を使用します。

 img { /* ...existing styles */ mix-blend-mode: overlay; }

mix-blend-modeプロパティは、Photoshopなどの写真操作ソフトウェアで使用可能なレイヤーブレンディングスタイルを適用するのと似ています。 また、 overlay値には、画像の中間調が背後のグラデーションとブレンドできるようにする効果があり、次の結果になります。

各カード画像には、上部の水色から始まり、赤みがかったピンクにブレンドされ、残りのカードテキストコンテンツの前に白にフェザリングすることで終了するグラデーションブレンド効果があります。
各カード画像には、上部の水色から始まり、赤みがかったピンクにブレンドされ、残りのカードテキストコンテンツの前に白にフェザリングすることで終了するグラデーションブレンド効果があります。 (大プレビュー)

現在、この時点では、画像のサイズを変更するためにaspect-ratioの値のみに依存しています。 また、コンテナのサイズを変更してカードレイアウトをリフローさせると、画像の高さが変化すると、グラデーションが白にフェードする場所に不整合が生じます。

そのため、 max()関数使用し、グラデーションの値よりもわずかに大きい値を含むmax-heightプロパティも追加します。 結果として生じる動作は、グラデーションが(ほとんどの場合)画像の下部と正しく整列することです。

 img { /* ...existing styles */ max-height: max(10rem, 30vh); }

`max-height`を追加すると、`aspect-ratio`の動作が変わることに注意してください。 常に正確な比率を使用するのではなく、 `max-height`の新しい追加の制約を考慮して、十分な割り当てスペースがある場合にのみ使用されます。

「「

ただし、 aspect-ratioは、 object-fitのみの場合と同様に、画像のサイズが一貫して変更されるようにします。 最終的なCodePenデモでaspect-ratioをコメントアウトして、コンテナーサイズ間での違いを確認してください。

私たちの当初の目標は、一貫してレスポンシブな画像のサイズを実現することでしたので、まだ目標を達成しています。 独自のユースケースでは、目的の効果を実現するために、比率と高さの値をいじる必要がある場合があります。

代替: mix-blend-modeとフィルターの追加

mix-blend-mode値としてoverlayを使用することは、私たちが探していた白へのフェード効果の最良の選択でしたが、より劇的な効果のために別のオプションを試してみましょう。

ソリューションを更新して、 mix-blend-mode値のCSSカスタムプロパティを追加し、グラデーションの色値も更新します。

 .card { --card-gradient: tomato, orange; --card-blend-mode: multiply; } img { /* ...existing styles */ mix-blend-mode: var(--card-blend-mode); }

multiply値は中間調に暗くなりますが、白と黒をそのまま維持するため、次のようになります。

各カード画像には、赤オレンジから純粋なオレンジに始まる新しいグラデーションからの強いオレンジの色合いがあります。白い部分はまだ白で、黒い部分はまだ黒い
各カード画像には、赤オレンジから純粋なオレンジに始まる新しいグラデーションからの強いオレンジの色合いがあります。 白い領域はまだ白で、黒い領域はまだ黒です。 (大プレビュー)

フェードがなくなり、画像の下部にハードエッジができましたが、グラデーションの白い部分は、カードのコンテンツの前にグラデーションを確実に終了させるために重要です。

追加できる追加の変更の1つは、 filterの使用です。特に、 grayscale()関数を使用して画像の色を削除し、グラデーションを画像の色の唯一のソースにします。

 img { /* ...existing styles */ filter: grayscale(100); }

grayscale(100)の値を使用すると、画像の自然な色が完全に削除され、白黒に変換されます。 これは、 multiplyでオレンジ色のグラデーションを使用した場合の効果の前のスクリーンショットと比較するための更新です。

これで、各カード画像にはまだオレンジ色のグラデーションがありますが、他のすべての色は削除され、灰色の色合いに置き換えられます
これで、各カード画像にはオレンジ色のグラデーションが残りますが、他のすべての色が削除され、灰色の色合いに置き換えられます。 (大プレビュー)

プログレッシブエンハンスメントとしてaspect-ratioを使用する

前述のように、現在、 aspect-ratioは最新バージョンのChromiumブラウザー(ChromeおよびEdge)でのみサポートされています。 ただし、すべてのブラウザはobject-fitをサポートしており、 heightの制約とともに、Safariの場合に見られるように、理想的ではありませんが、それでも許容できる結果になります。

カード画像の高さには上限がありますが、各カードの実現高さはわずかに異なります
カード画像の高さには上限がありますが、各カードの実現高さはわずかに異なります。 (大プレビュー)

aspect-ratioが機能しない場合、ここでの結果は、最終的に画像の高さが制限されますが、各画像の自然な寸法により、カードの画像の高さが多少異なります。 代わりに、 max-heightの追加に変更するか、 max()関数を再度使用して、さまざまなカードサイズでmax-heightの応答性を高めることができます。

勾配効果の拡張

グラデーションカラーストップをCSSカスタムプロパティとして定義したので、さまざまなコンテキストでそれらを変更するためのアクセスが可能です。 たとえば、カードにカーソルを合わせたり、子の1つにフォーカスがある場合は、グラデーションを変更して、色の1つをより強く表示することができます。

まず、各カードh3を更新して、次のようなリンクを含めます。

 <h3><a href="">A Super Wonderful Headline</a></h3>

次に、利用可能な最新のセレクターの1つである:focus-withinを使用して、リンクにフォーカスがあるときにカードのグラデーションを変更できます。 可能な相互作用をさらにカバーするために、これを:hoverと組み合わせます。 そして、 max()のアイデアを再利用して、カードの画像部分のカバレッジを引き継ぐために単一の色を割り当てます。 この特定の効果の欠点は、グラデーションが停止し、色の変化を確実にアニメートできないことです。ただし、CSSHoudiniのおかげですぐにアニメーション化できるようになります。

色を更新して新しいカラーストップを追加するには、次の新しいルール内で--card-gradientの値を再割り当てする必要があります。

 .card:focus-within, .card:hover { --card-gradient: #24a9d5 max(8.5rem, 20vh); }

max()値は、フェザーエッジを維持するためにwhiteに使用されている元の値よりも小さくなっています。 同じ値を使用した場合、それはwhiteに適合し、明確に直定規の分離を作成します。

このデモを作成するにあたり、私はもともと、ズームイン効果のためにscale付きのtransformを使用する効果を試しました。 しかし、 mix-blend-modeが適用されているため、ブラウザが一貫して画像を再描画せず、不快なちらつきが発生することがわかりました。 ブラウザにCSSのみのエフェクトとアニメーションを実行するように要求することには常にトレードオフがあります。私たちができることは非常にクールですが、エフェクトのパフォーマンスへの影響を確認することをお勧めします。

実験を楽しんでください!

最新のCSSは、 aspect-ratioが最新の追加である、Webデザインツールキットを更新するためのいくつかの素晴らしいツールを提供してくれました。 さあ、 object-fitaspect-ratiomax()などの関数をグラデーションに追加して、楽しいレスポンシブ効果を試してみてください。 クロスブラウザ(今のところ!)とさまざまなビューポートとコンテナサイズで物事を再確認してください。

本日レビューした機能と効果を含むCodePenは次のとおりです。

StephanieEcklesによるペン[CSSグラデーションとアスペクト比を使用したレスポンシブ画像効果](https://codepen.io/smashingmag/pen/WNoERXo)を参照してください。

StephanieEcklesによるCSSグラデーションとアスペクト比を使用したペンレスポンシブ画像効果を参照してください。

もっとお探しですか? ここでスマッシングに関するCSSガイドを確認してください→