CSSのグラデーションとアスペクト比を使用してレスポンシブな画像効果を作成します
公開: 2022-03-10object-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
に続く要素に水平方向のマージンを追加します。
そして、これまでの進歩により、次のカードの外観が得られます。
最後に、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
スタイルで次のレイアウトが得られます。
プレビュー画像に示されているように、これらのベースラインスタイルは、さまざまな自然な寸法を考えると、画像を適切に含めるには十分ではありません。 これらの画像を均一かつ一貫して制約する方法が必要です。
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つのコンテキストは、要素間の間隔です。
このアップデートにより、私たちは間違いなく物事を改善し、視覚的な結果は、古い背景画像の手法を使用するかのようになります。
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
を設定した場合の外観とほぼ一致するため、この特定のインスタンスでは視覚的な違いに気付くのはおそらく難しいでしょう。
「アスペクト比」を設定すると、要素が拡大または縮小しても比率が維持されますが、「オブジェクトフィット」と「高さ」のみを設定すると、コンテナの寸法が変化しても画像の比率は常に流動的になります。
「「
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-fit
、 aspect-ratio
、 max()
などの関数をグラデーションに追加して、楽しいレスポンシブ効果を試してみてください。 クロスブラウザ(今のところ!)とさまざまなビューポートとコンテナサイズで物事を再確認してください。
本日レビューした機能と効果を含むCodePenは次のとおりです。
もっとお探しですか? ここでスマッシングに関するCSSガイドを確認してください→