CSS Grid のおかげで、画像のグリッドを簡単に作成できます。 しかし、グリッドに派手なことをさせる After 配置された画像は、引き離すのが難しい場合があります。
画像が成長し、画像が置かれている行や列を超えてズームするところに、派手なホバー効果を追加したいとしますか? 私たちはそれができる!
かっこいいでしょ? コードを確認すると、JavaScript、複雑なセレクター、さらには マジックナンバー. そして、これは私たちが探求する多くの例のほんの一例です!
グリッドの構築
グリッドを作成する HTML コードは、コンテナー内の画像のリストと同じくらい単純です。 それ以上は必要ありません。
<div class="gallery">
<img>
<img>
<img>
<!-- etc. -->
</div>
CSS の場合、最初に次を使用してグリッドを設定することから始めます。
.gallery {
--s: 150px; /* controls the size */
--g: 10px; /* controls the gap */
display: grid;
gap: var(--g);
width: calc(3*var(--s) + 2*var(--g)); /* 3 times the size plus 2 times the gap */
aspect-ratio: 1;
grid-template-columns: repeat(3, auto);
}
つまり、画像のサイズを制御する変数と、画像間のギャップのサイズを設定する変数の XNUMX つの変数があります。 aspect-ratio
物事のバランスを保つのに役立ちます。
行を定義せずに列を XNUMX つだけ定義している理由を不思議に思うかもしれません。 いいえ、行を忘れていません。明示的に設定する必要がないだけです。 CSS グリッドは、アイテムを自動的に配置することができます 暗黙的な行と列、つまり、投げる画像の数に必要な数の行を取得します。 代わりに行を明示的に定義できますが、追加する必要があります grid-auto-flow: column
ブラウザーが必要な列を作成することを確認します。
両方のケースを説明する例を次に示します。 違いは、XNUMX つが流れていることです。 row
の方向 column
方向。
チェックアウト 私が書いたこの別の記事 暗黙的なグリッドと自動配置アルゴリズムの詳細については、.
グリッドができたので、画像のスタイルを設定します。
.gallery > img {
width: 0;
height: 0;
min-height: 100%;
min-width: 100%;
object-fit: cover;
}
作成しているホバー効果は、この CSS に依存しています。 幅と高さの両方がなく、幅と高さの最小値が 100% の画像を作成しているのは、おそらく奇妙に思えるでしょう。 しかし、これが私たちが達成しようとしているものにとってはかなり巧妙なトリックであることがわかるでしょう。
ここで行っているのは、画像に必要な情報をブラウザーに伝えることです。 0
幅と高さだけでなく、最小の高さも必要です 100%
… だが 100%
なにかの? パーセンテージを使用する場合、値は 他のものとの相対的な. この場合、画像は グリッドセル そのサイズを知る必要があります 100%
に相対的です。
ブラウザは最初に無視します min-height: 100%
グリッドセルのサイズを計算しますが、使用します height: 0
その計算で。 つまり、画像はグリッド セルのサイズには影響しません。技術的に物理的なサイズがないためです。 これにより、グリッドのサイズに基づいた XNUMX つの等しい列と行が作成されます ( .gallery
の幅と aspect-ratio
)。 各グリッドセルの高さは変数に他なりません --s
定義しました (幅についても同じです)。
グリッドのセルの寸法が得られたので、ブラウザーはそれを次のように使用します。 min-height: 100%
(と min-width: 100%
) これにより、画像が各グリッド セルのスペースを完全に埋めます。 全体がややこしく見えるかもしれませんが、主なアイデアは、グリッドが画像のサイズを定義するのではなく、その逆ではないことを確認することです。 画像でグリッドのサイズを定義したくありません。ホバー効果を追加すると、その理由がわかります。
ホバー効果の作成
必要なのは、ホバーしたときに画像のスケールを大きくすることです。 画像を調整することでそれを行うことができます width
& height
on :hover
:
.gallery {
--f: 1.5; /* controls the scale factor */
}
.gallery img:hover{
width: calc(var(--s) * var(--f));
height: calc(var(--s) * var(--f));
}
新しいカスタム変数を追加しました。 --f
、ホバー時のサイズを制御するための倍率としてミックスに追加します。 サイズ変数をどのように乗算しているかに注目してください。 --s
、それによって新しい画像サイズを計算します。
しかし、画像サイズは 0 である必要があるとおっしゃいました。何が起こっているのでしょうか? 迷っています…
私が言ったことはまだ真実ですが、ホバーされた画像は例外です。 私はブラウザーに、XNUMX つの画像だけがゼロ以外のサイズになることを伝えています。つまり、その画像はグリッドの次元に寄与し、他のすべての画像は等しいままです。 0
.
左側は、ホバーされた画像のない自然な状態のグリッドを示しています。これは、右側が示しているものです。 すべての画像に物理的な寸法がないため、左側のすべてのグリッド セルのサイズは同じです。
右側では、最初の行の XNUMX 番目の画像がホバーされており、グリッド セルのサイズに影響する寸法が表示されています。 ブラウザーはホバー時にその特定のグリッド セルを大きくし、全体のサイズに影響します。 また、グリッド全体のサイズが設定されているため (固定を設定しているため) width
.gallery
)、他のグリッド セルは論理的に応答して小さくなり、 .gallery
の全体的なサイズはそのままです。
これが実際のズーム効果です。 XNUMX つの画像のみのサイズを大きくすることで、グリッド構成全体に影響を与えます。前に、各画像がそのグリッド セル内で伸びてすべてのスペースを埋めるように、グリッドが画像のサイズを定義することを説明しました。
これに、 transition
使用する object-fit
画像の歪みを防ぎ、錯覚もバッチリ!
トリックの背後にあるロジックを把握するのは容易ではないことはわかっています。 完全に理解できなくても心配しないでください。 最も重要なことは、使用されるコードの構造と、より多くのバリエーションを得るためにコードを変更する方法を理解することです。 それが私たちが次にやることです!
さらに画像を追加する
主なトリックを説明するために 3×3 のグリッドを作成しましたが、おそらくそこで停止する必要はないと推測したでしょう。 列と行の数を変数にして、必要な数の画像を追加できます。
.gallery {
--n: 3; /* number of rows*/
--m: 4; /* number of columns */
--s: 150px; /* control the size */
--g: 10px; /* control the gap */
--f: 1.5; /* control the scale factor */
display: grid;
gap: var(--g);
width: calc(var(--m)*var(--s) + (var(--m) - 1)*var(--g));
height: calc(var(--n)*var(--s) + (var(--n) - 1)*var(--g));
grid-template-columns: repeat(var(--m),auto);
}
行数と列数の XNUMX つの新しい変数があります。 次に、それらを使用してグリッドの幅と高さを定義するだけです。 同じ grid-template-columns
これを使用します --m
変数。 前と同じように、行を明示的に定義する必要はありません。使用している画像要素の数に関係なく、CSS グリッドの自動配置機能が仕事をしてくれるからです。
幅と高さの値が異なるのはなぜですか? 私たちはそれができる:
.gallery {
--n: 3; /* number of rows*/
--m: 4; /* number of columns */
--h: 120px; /* control the height */
--w: 150px; /* control the width */
--g: 10px; /* control the gap */
--f: 1.5; /* control the scale factor */
display: grid;
gap: var(--g);
width: calc(var(--m)*var(--w) + (var(--m) - 1)*var(--g));
height: calc(var(--n)*var(--h) + (var(--n) - 1)*var(--g));
grid-template-columns: repeat(var(--m),auto);
}
.gallery img:hover{
width: calc(var(--w)*var(--f));
height: calc(var(--h)*var(--f));
}
交換します --s
XNUMX つの変数 (XNUMX つは幅)、 --w
、もう XNUMX つは高さです。 --h
. その後、それに応じて他のすべてを調整します。
そのため、固定サイズと要素数のグリッドから始めましたが、必要な構成を取得するために新しい変数セットを作成しました。 必要なだけ画像を追加し、それに応じて CSS 変数を調整するだけです。 組み合わせは無限大!
画像の全画面ギャラリー
フルスクリーン版はどうですか? はい、それも可能です。 必要なのは、変数に割り当てる必要がある値を知ることだけです。 私たちが望むなら N
画像の行があり、グリッドをフルスクリーンにしたい場合は、まず高さを解決する必要があります 100vh
:
var(--n) * var(--h) + (var(--n) - 1) * var(--g) = 100vh
幅についても同じロジックですが、 vw
vh
:
var(--m) * var(--w) + (var(--m) - 1) * var(--g) = 100vw
以下を得るために計算を行います。
--w: (100vw - (var(--m) - 1) * var(--g)) / var(--m)
--h: (100vh - (var(--n) - 1) * var(--g)) / var(--n)
完了!
これはまったく同じ HTML ですが、グリッドのサイズ変更と動作を変更する変数がいくつか更新されています。
以前に設定した式を省略したことに注意してください .gallery
〜の width
& height
そしてそれらを 100vw
& 100vh
、 それぞれ。 式は同じ結果をもたらしますが、必要な値がわかっているため、追加された複雑さをすべて捨てることができます。
単純化することもできます --h
& --w
これを支持して方程式からギャップを取り除くことによって:
--h: calc(100vh / var(--n)); /* Viewport height divided by number of rows */
--w: calc(100vw / var(--m)); /* Viewport width divided by number of columns */
これにより、ホバリングされた画像が前の例よりも少し大きくなりますが、スケールを --f
乗数として使用している変数。
また、変数は XNUMX か所で使用されるため、それらを完全に削除してコードを単純化できます。
この最適化はフルスクリーンの例にのみ適用され、これまでに説明した例には適用されないことに注意してください。 この例は、他の例で必要だった複雑な計算作業の一部を削除することで、コードを軽量化できる特定のケースです。
パネルを展開する一般的なパターンを作成するために必要なものはすべて揃っています。
さらに掘り下げてみましょう
スケール ファクターが 1
? ホバーした画像のサイズをより小さく定義できます。 --h
or --w
しかし、ホバーすると画像が大きくなります。
初期のグリッド セル サイズは次のとおりです。 --w
& --h
、では、なぜより小さい値がグリッドセルを作るのですか より大きい? セルが取得するべきではありません より小さい、または少なくとも初期サイズを維持しますか? そして、グリッドセルの最終的なサイズは?
CSS グリッド アルゴリズムがグリッド セルのサイズを計算する方法をさらに深く掘り下げる必要があります。 これには、CSS グリッドのデフォルトを理解することが含まれます ストレッチアラインメント.
ロジックを理解するための例を次に示します。
デモの左側で、XNUMX 列を定義しました。 auto
幅。 XNUMX つの等しい列 (および XNUMX つの等しいグリッド セル) という直感的な結果が得られます。 しかし、デモの右側に設定したグリッドは、次を使用して配置を更新しています。 place-content: start
、何もないように見えます。
DevTools は、両方のケースで実際に何が起こっているかを示すのに役立ちます。
XNUMX 番目のグリッドには XNUMX つの列がありますが、それらの幅は XNUMX であるため、グリッド コンテナーの左上隅で折りたたまれた XNUMX つのグリッド セルを取得します。 これは バグですが、グリッドの配置の論理的な結果です。 列(または行)のサイズを変更するとき auto
、それはその内容がそのサイズを決定することを意味します—しかし、私たちは空を持っています div
スペースを確保するコンテンツがありません。
しかし、以来 stretch
がデフォルトの配置で、グリッド内に十分なスペースがある場合、ブラウザーは両方のグリッド セルを均等に引き伸ばして、その領域全体をカバーします。 これが、左側のグリッドが XNUMX つの等しい列で巻き上げられる方法です。
仕様:
の特定の値に注意してください。
justify-content
&align-content
トラックが離れてしまう可能性があります (space-around
,space-between
,space-evenly
) またはサイズ変更 (stretch
).
ここで重要な「サイズ変更」に注意してください。 最後の例では、使用しました place-content
これはの省略形です justify-content
& align-content
そして、これはどこかに埋もれています グリッド サイジング アルゴリズム 仕様:
この手順では、 オート 最大トラックサイジング機能 残りの陽性を割ることによって、 明確 フリースペース それらの間で等しく。 空き容量がある場合 不定しかし、 グリッドコンテナ 明確な 最小幅/高さ、代わりにそのサイズを使用して、このステップの空き容量を計算します。
「均等に」は、なぜ私たちが均等なグリッド セルになってしまうのかを説明しますが、それは非常に重要な「自由空間」に当てはまります。
前の例を取り上げて、コンテンツを div
s:
正方形を追加しました 50px
画像。 以下は、この例の各グリッドがその画像にどのように反応するかを示しています。
最初のケースでは、最初のセル (赤) が XNUMX 番目のセル (青) よりも大きいことがわかります。 XNUMX 番目のケースでは、最初のセルのサイズがイメージの物理的なサイズに合わせて変更されますが、XNUMX 番目のセルには寸法がありません。 空き領域は均等に分割されますが、最初のセルにはより多くのコンテンツが含まれているため、セルが大きくなります。
これは、空き領域を計算するための計算です。
(grid width) - (gap) - (image width) = (free space)
200px - 5px - 50px = 145px
XNUMX で割ると (列数)、幅が得られます。 72.5px
列ごとに。 しかし、画像のサイズを追加します。 50px
、最初の列に XNUMX つの列を残します 122.5px
そしてXNUMX番目のものはに等しい 72.5px
.
画像のグリッドにも同じロジックが適用されます。 すべての画像のサイズは 0
(コンテンツなし)ホバーされた画像はサイズに貢献します—それがちょうど 1px
— グリッド セルを他のセルよりも大きくします。 このため、スケール ファクターは、 0
間の偶数小数 0
& 1
.
グリッド セルの最終的な幅を取得するには、同じ計算を行って次を取得します。
(container width) - (sum of all gaps) - (hovered image width) = (free space)
コンテナーの幅は次のように定義されます。
var(--m)*var(--w) + (var(--m) - 1)*var(--g)
…そして、すべてのギャップは次のようになります。
(var(--m) - 1)*var(--g)
…ホバリングされた画像については、次のようになります。
var(--w)*var(--f)
そのすべてを変数で計算できます。
var(--m)*var(--w) - var(--w)*var(--f) = var(--w)*(var(--m) - var(--f))
列数は次のように定義されます --m
、したがって、その空き領域を均等に分割して取得します。
var(--w)*(var(--m) - var(--f))/var(--m)
…ホバーされていない画像のサイズがわかります。 ホバーされた画像の場合、次のようになります。
var(--w)*(var(--m) - var(--f))/var(--m) + var(--w)*var(--f)
var(--w)*((var(--m) - var(--f))/var(--m) + var(--f))
ホバリングされた画像の最終的なサイズを制御したい場合は、上記の式を考慮して、必要な正確なサイズを取得します。 たとえば、画像を XNUMX 倍の大きさにしたい場合は、次のようにします。
(var(--m) - var(--f))/var(--m) + var(--f) = 2
したがって、スケール乗数の値は、 --f
、次と等しい必要があります。
var(--m)/(var(--m) - 1)
XNUMX列の場合、 3/2 = 1.5
これは、この記事の最初のデモで使用した倍率です。ホバー時に画像を XNUMX 倍の大きさにしたかったからです。
高さの計算にも同じロジックが適用されます。両方を個別に制御したい場合は、ホバー時に特定の幅と高さを確保するために XNUMX つの倍率を考慮する必要があります。
.gallery {
/* same as before */
--fw: 1.5; /* controls the scale factor for the width */
--fh: 1.2; /* controls the scale factor for the height */
/* same as before */
}
.gallery img:hover{
width: calc(var(--w)*var(--fw));
height: calc(var(--h)*var(--fh));
}
これで、クールなホバー効果を備えたあらゆる種類の画像グリッドを作成するための秘密がすべてわかりました。また、先ほど説明した数学を使用して必要なサイズを制御することもできます。
包み込む
私の中で 前回の記事、CSS グリッドの暗黙的なグリッドと自動配置機能を使用する数行の CSS を使用して、複雑に見えるグリッドを作成しました。 この記事では、ホバー時にズームし、それに応じてグリッドを調整する画像の派手なグリッドを作成するために、いくつかの CSS グリッドのサイズ変更トリックに依存しました。 これらすべては、CSS 変数を使用して簡単に調整できる単純化されたコードで行われます!
次の記事では、形で遊びます! CSS グリッドを mask および clip-path と組み合わせて、画像の派手なグリッドを取得します。