よし、だから 前回チェックインしたとき、CSS Gridを使用し、それらをCSSと組み合わせていました clip-path
& mask
ファンシーな形状のグリッドを作成するテクニック。
これは、私たちが一緒に作った素晴らしいグリッドの XNUMX つです。
第XNUMXラウンドの準備はできましたか? 私たちはまだ CSS Grid を使用しています。 clip-path
, mask
、しかし、この記事の終わりまでに、グリッド上に画像を配置するさまざまな方法について説明します.
そして、何を推測しますか? 私たちは使用しています 前回使用したのと同じマークアップ. これが再びです:
<div class="gallery">
<img src="..." alt="...">
<img src="..." alt="...">
<img src="..." alt="...">
<img src="..." alt="...">
<!-- as many times as we want -->
</div>
前回の記事と同様に、内部に画像を含むコンテナーのみが必要です。 これ以上何もない!
ネストされた画像グリッド
前回のグリッドは、まあ、典型的な画像グリッドでした。 マスクに使用したきちんとした形状を除けば、画像を内部に配置する方法に関しては、かなり標準的な対称グリッドでした。
グリッドの中央に画像を入れ子にしてみましょう:
まず、2 つの画像に 2×XNUMX グリッドを設定します。
.gallery {
--s: 200px; /* controls the image size */
--g: 10px; /* controls the gap between images */
display: grid;
gap: var(--g);
grid-template-columns: repeat(2, auto);
}
.gallery > img {
width: var(--s);
aspect-ratio: 1;
object-fit: cover;
}
まだ複雑なことは何もありません。 次のステップは、画像の角を切り取って、ネストされた画像用のスペースを作成することです。 についての詳細な記事がすでにあります を使用してコーナーをカットする方法 clip-path
& mask
. 私のも使えます オンラインジェネレータ コーナーをマスキングするための CSS を取得します。
ここで必要なのは、次の角度で角を切り取ることです。 90deg
. 同じものを使用できます 円錐勾配法 その記事からそれを行うには:
.gallery > img {
mask: conic-gradient(from var(--_a), #0000 90deg, #000 0);
}
.gallery > img:nth-child(1) { --_a: 90deg; }
.gallery > img:nth-child(2) { --_a: 180deg; }
.gallery > img:nth-child(3) { --_a: 0deg; }
.gallery > img:nth-child(4) { --_a:-90deg; }
私たちは使用することができます clip-path
同じ記事から手を抜くための方法ですが、すべての画像に同じ構成があるため、ここではグラデーションでマスキングする方が適しています — 必要なのは回転 (変数で定義された) だけです --_a
)効果が得られるので、外側のエッジではなく内側からマスキングしています。
これで、マスクされたスペース内にネストされた画像を配置できます。 まず、HTML に XNUMX 番目の画像要素があることを確認しましょう。
<div class="gallery">
<img src="..." alt="...">
<img src="..." alt="...">
<img src="..." alt="...">
<img src="..." alt="...">
<img src="..." alt="...">
</div>
そこに配置するには、古き良き絶対位置に依存します。
.gallery > img:nth-child(5) {
position: absolute;
inset: calc(50% - .5*var(--s));
clip-path: inset(calc(var(--g) / 4));
}
inset
プロパティを使用すると、単一の宣言を使用して画像を中央に配置できます。 画像のサイズはわかっています(変数で定義されます --s
)、コンテナのサイズが 100% に等しいことがわかっています。 計算すると、各エッジからの距離は次のようになります。 (100% - var(--s))/2
.
なぜ私たちが使用しているのか不思議に思うかもしれません clip-path
ここではまったく。 ネストされた画像で使用して、一貫したギャップを作ります。 それを削除すると、すべての画像の間に同じギャップがないことに気付くでしょう。 このようにして、XNUMX 番目の画像から少し切り取って、周囲に適切なスペースを確保します。
再び完全なコード:
.gallery {
--s: 200px; /* controls the image size */
--g: 10px; /* controls the gap between images */
display: grid;
gap: var(--g);
grid-template-columns: repeat(2, auto);
position: relative;
}
.gallery > img {
width: var(--s);
aspect-ratio: 1;
object-fit: cover;
mask: conic-gradient(from var(--_a), #0000 90deg, #000 0);
}
.gallery > img:nth-child(1) {--_a: 90deg}
.gallery > img:nth-child(2) {--_a:180deg}
.gallery > img:nth-child(3) {--_a: 0deg}
.gallery > img:nth-child(4) {--_a:-90deg}
.gallery > img:nth-child(5) {
position: absolute;
inset: calc(50% - .5*var(--s));
clip-path: inset(calc(var(--g) / 4));
}
さて、あなたの多くは疑問に思っているかもしれません: 最後の画像を一番上に配置し、それに境界線を追加できるのに、なぜ複雑なことをするのでしょうか? マスクなしでネストされた画像の下にある画像を非表示にしますよね?
これは本当です。次の結果が得られます。
いいえ mask
に clip-path
. はい、コードは簡単に理解できますが、少し欠点があります。幻想を完璧にするには、境界線の色をメインの背景と同じにする必要があります。 この小さな欠点は、背景から独立した真の透明性と引き換えに、コードをより複雑にするのに十分です。 国境へのアプローチが悪いとか間違っていると言っているのではありません。 背景がわかっているほとんどの場合にお勧めします。 しかし、私たちは新しいものを探求し、最も重要なこととして、環境に依存しないコンポーネントを構築するためにここにいます。
今度は別の形を試してみましょう。
今回は、ネストされた画像を正方形ではなく円形にしました。 それは簡単な作業です border-radius
しかし、私たちは使用する必要があります 円形の切り欠き 他の画像について。 ただし、今回は、 radial-gradient()
の代わりに conic-gradient()
丸みのある素敵な外観を得るために。
.gallery > img {
mask:
radial-gradient(farthest-side at var(--_a),
#0000 calc(50% + var(--g)/2), #000 calc(51% + var(--g)/2));
}
.gallery > img:nth-child(1) { --_a: calc(100% + var(--g)/2) calc(100% + var(--g)/2); }
.gallery > img:nth-child(2) { --_a: calc(0% - var(--g)/2) calc(100% + var(--g)/2); }
.gallery > img:nth-child(3) { --_a: calc(100% + var(--g)/2) calc(0% - var(--g)/2); }
.gallery > img:nth-child(4) { --_a: calc(0% - var(--g)/2) calc(0% - var(--g)/2); }
すべての画像は前の例と同じ構成を使用しますが、中心点を毎回更新します。
上の図は、各円の中心点を示しています。 それでも、実際のコードでは、ギャップを考慮して、すべてのポイントが同じ位置 (グリッドの中心) にあることを確認し、それらを組み合わせた場合に連続した円を取得していることに気付くでしょう。
レイアウトができたので、ホバー効果について話しましょう。 気が付かなかったかもしれませんが、クールなホバー効果により、ネストされた画像のサイズが大きくなり、それに応じて他のすべてが調整されます。 サイズを大きくするのは比較的簡単な作業ですが、デフォルトではグラデーションはアニメーション化できないため、グラデーションの更新はより複雑になります。 これを克服するために、私は font-size
放射状グラデーションをアニメーション化できるようにハックします。
グラデーションのコードを確認すると、追加していることがわかります 1em
:
mask:
radial-gradient(farthest-side at var(--_a),
#0000 calc(50% + var(--g)/2 + 1em), #000 calc(51% + var(--g)/2 + 1em));
それは知られています em
単位は親要素の相対値です font-size
、だから変更する font-size
.gallery
計算された em
値 — これが私たちが使用しているトリックです。 をアニメーション化しています font-size
の値から 0
その結果、グラデーションがアニメーション化され、ネストされた画像のサイズが大きくなるにつれて、切り抜き部分が大きくなります。
ホバー効果に関係する部分を強調するコードは次のとおりです。
.gallery {
--s: 200px; /* controls the image size */
--g: 10px; /* controls the gaps between images */
font-size: 0; /* initially we have 1em = 0 */
transition: .5s;
}
/* we increase the cut-out by 1em */
.gallery > img {
mask:
radial-gradient(farthest-side at var(--_a),
#0000 calc(50% + var(--g)/2 + 1em), #000 calc(51% + var(--g)/2 + 1em));
}
/* we increase the size by 2em */
.gallery > img:nth-child(5) {
width: calc(var(--s) + 2em);
}
/* on hover 1em = S/5 */
.gallery:hover {
font-size: calc(var(--s) / 5);
}
font-size
トリックは、アニメーション化できないグラデーションやその他のプロパティをアニメーション化する場合に役立ちます。 @property で定義されたカスタム プロパティはそのような問題を解決できますが、 それのサポート 執筆時点ではまだ不足しています。
を発見した font-size
からのトリック @SelenIT2 解決しようとしながら ツイッターでチャレンジ.
別の形? さあ行こう!
今回はネストした画像をひし形に切り抜きました。 どのようにしてここにたどり着いたかを理解するための演習として、コードを分析してみましょう。 構造が例と同じであることがわかります。 唯一の違いは、グラデーションを使用して形状を作成する方法です。 掘り下げて学びましょう!
円形画像グリッド
ここと以前の記事で学んだことを組み合わせて、さらにエキサイティングな画像グリッドを作成できます。 今回は、グリッド内のすべての画像を円形にし、ホバー時に画像を拡大して、残りの写真をカバーするように全体を表示しましょう。
グリッドの HTML および CSS 構造は以前から新しいものではないので、その部分を飛ばして、代わりに必要な円形とホバー効果に注目しましょう。
使用します clip-path
とその circle()
への関数 — ご想像のとおりです。 — 画像から円を切り取ります。
その図は、 clip-path
最初の画像に使用。 左側は画像の初期状態を示し、右側はホバーした状態を示します。 使用できます このオンラインツール 再生して視覚化する clip-path
値。
他の画像については、円の中心を更新できます (70% 70%
) 次のコードを取得します。
.gallery > img:hover {
--_c: 50%; /* same as "50% at 50% 50%" */
}
.gallery > img:nth-child(1) {
clip-path: circle(var(--_c, 55% at 70% 70%));
}
.gallery > img:nth-child(2) {
clip-path: circle(var(--_c, 55% at 30% 70%));
}
.gallery > img:nth-child(3) {
clip-path: circle(var(--_c, 55% at 70% 30%));
}
.gallery > img:nth-child(4) {
clip-path: circle(var(--_c, 55% at 30% 30%));
}
をどのように定義しているかに注意してください。 clip-path
内部のフォールバックとしての値 var()
. このようにして、ホバー時の値をより簡単に更新できます。 --_c
変数。 使用時 circle()
、中心点のデフォルト位置は 50% 50%
、したがって、より簡潔なコードのためにそれを省略できます。 そのため、設定しているだけであることがわかります 50%
50% at 50% 50%
.
次に、ホバー時の画像のサイズをグリッド全体のサイズまで拡大して、他の画像をカバーできるようにします。 また、 z-index
ホバーした画像の方が値が高いため、 スタッキングコンテキスト.
.gallery {
--s: 200px; /* controls the image size */
--g: 8px; /* controls the gap between images */
display: grid;
grid: auto-flow var(--s) / repeat(2, var(--s));
gap: var(--g);
}
.gallery > img {
width: 100%;
aspect-ratio: 1;
cursor: pointer;
z-index: 0;
transition: .25s, z-index 0s .25s;
}
.gallery > img:hover {
--_c: 50%; /* change the center point on hover */
width: calc(200% + var(--g));
z-index: 1;
transition: .4s, z-index 0s;
}
.gallery > img:nth-child(1){
clip-path: circle(var(--_c, 55% at 70% 70%));
place-self: start;
}
.gallery > img:nth-child(2){
clip-path: circle(var(--_c, 55% at 30% 70%));
place-self: start end;
}
.gallery > img:nth-child(3){
clip-path: circle(var(--_c, 55% at 70% 30%));
place-self: end start;
}
.gallery > img:nth-child(4){
clip-path: circle(var(--_c, 55% at 30% 30%));
place-self: end;
}
何が起こっているのか
place-self
財産? なぜそれが必要なのですか? また、各画像に特定の値があるのはなぜですか?
前回の記事で発生した問題を覚えていますか? パズルのピースのグリッドを作成する? 画像のサイズを大きくしてオーバーフローを作成しましたが、一部の画像のオーバーフローが正しくありませんでした。 を使用してそれらを修正しました place-self
プロパティ。
ここで同じ問題。 画像のサイズを大きくして、各画像がグリッド セルからはみ出すようにします。 しかし、何もしなければ、すべてグリッドの右側と下側にあふれてしまいます。 必要なものは次のとおりです。
- 右下端からはみ出した最初の画像 (デフォルトの動作)、
- 左下端からはみ出す XNUMX 番目の画像
- 右上端からはみ出す XNUMX 番目の画像、および
- 左上端からオーバーフローする XNUMX 番目のイメージ。
そのためには、各画像を正しく配置する必要があります。 place-self
プロパティ。
あなたが慣れていない場合 place-self
、それはの省略形です justify-self
& align-self
要素を水平および垂直に配置します。 値が XNUMX つの場合、両方のアラインメントで同じ値が使用されます。
画像パネルの拡大
前の記事、行数、列数、サイズ、倍率など、すべてを制御できる画像のグリッドに適用されるクールなズーム効果を作成しました。
特定のケースは、従来のエキスパンド パネルで、XNUMX つの行と全幅のコンテナしかありません。
この例を取り上げて、形状と組み合わせます!
先に進む前に、私の記事を読むことを強くお勧めします 他の記事 これからカバーするトリックがどのように機能するかを理解するために。 それを確認してください。ここでは引き続き、パネル形状の作成に焦点を当てます。
まず、コードを単純化し、いくつかの変数を削除することから始めましょう
必要な行は XNUMX つだけで、列の数は画像の数に基づいて調整する必要があります。 つまり、行数の変数はもう必要ありません (--n
)および列(--m
) しかし、使用する必要があります grid-auto-flow: column
、新しい画像を追加するときにグリッドが列を自動生成できるようにします。 コンテナーの固定高を検討します。 デフォルトでは、全角になります。
画像を斜めの形に切り取りましょう:
繰り返しますが、各画像はそのグリッド セルに含まれているため、画像間に必要以上のスペースがあります。
オーバーラップを作成するには、画像の幅を広げる必要があります。 交換します min-width:
100%
min-width: calc(100% + var(--s))
ここで、 --s
形状を制御する新しい変数です。
ここで、最初と最後の画像を修正する必要があります。これにより、隙間なくページからにじみ出るようになります。 つまり、最初の画像の左側から傾斜を取り除き、最後の画像の右側から傾斜を取り除くことができます。 新しいものが必要です clip-path
特にこれらの XNUMX つの画像に対して。
オーバーフローも修正する必要があります。 デフォルトでは、すべての画像が両側でオーバーフローしますが、最初の画像では右側のオーバーフローが必要で、最後の画像では左側のオーバーフローが必要です。
.gallery > img:first-child {
min-width: calc(100% + var(--s)/2);
place-self: start;
clip-path: polygon(0 0,100% 0,calc(100% - var(--s)) 100%,0 100%);
}
.gallery > img:last-child {
min-width: calc(100% + var(--s)/2);
place-self: end;
clip-path: polygon(var(--s) 0,100% 0,100% 100%,0 100%);
}
最終結果は、傾斜した画像の素敵なエキスパンド パネルです。
画像はいくつでも追加でき、グリッドは自動的に調整されます。 さらに、形状を制御するために必要な値は XNUMX つだけです。
単一行の要素を扱っているため、これと同じレイアウトを flexbox で作成することもできました。 ここは 私の実装.
確かに斜めの画像はクールですが、ジグザグ パターンはどうでしょうか。 私はすでにこれをからかった 最後の記事の最後.
ここで行っているのは交換だけです clip-path
mask
…そして何を推測しますか? についての詳細な記事がすでにあります そのジグザグ形状を作成する —オンラインは言うまでもありません コードを取得するジェネレーター. すべてがどのように組み合わされるかご覧ください。
ここで最も難しいのは、ジグザグが完全に整列していることを確認することです。そのためには、すべてにオフセットを追加する必要があります。 :nth-child(odd)
イメージ要素。
.gallery > img {
mask:
conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg)
100% calc(50% + var(--_p, 0%))/51% calc(2*var(--s)) repeat-y,
conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg)
0% calc(50% + var(--_p, 0%))/51% calc(2*var(--s)) repeat-y;
}
/* we add an offset to the odd elements */
.gallery > img:nth-child(odd) {
--_p: var(--s);
}
.gallery > img:first-child {
mask:
conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg)
0 calc(50% + var(--_p, 0%))/100% calc(2*var(--s));
}
.gallery > img:last-child {
mask:
conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg)
0 calc(50% + var(--_p, 0%)) /100% calc(2*var(--s));
}
ここでは、 --_p
にフォールバックする変数 0%
しかし、等しくなります --_s
奇妙なイメージのために。
この問題を説明するデモを次に示します。 ホバーして、オフセットがどのように定義されているかを確認します --_p
— 位置合わせを修正しています。
また、前の例で行ったように、最初と最後の画像に異なるマスクを使用する方法にも注目してください。 最初の画像の右側と最後の画像の左側のジグザグだけが必要です。
そして、なぜ丸みを帯びていないのですか? やってみましょう!
コードが恐ろしく、理解するのが難しいように見えることはわかっていますが、実際に行われているのは、この記事や既に共有した他の記事で説明したさまざまなトリックの組み合わせだけです。 この場合、ジグザグと斜めの形状と同じコード構造を使用します。 これらの例と比較してみてください。違いはありません。 それらは同じトリックです ズーム効果に関する以前の記事. それから、私は自分の その他の書き込み & 私のオンラインジェネレーター これらの丸みを帯びた形状を作成するマスクのコードを取得します。
ジグザグに行ったことを思い出すと、すべての画像に同じマスクを使用しましたが、奇数の画像にオフセットを追加して完全なオーバーラップを作成する必要がありました。 この場合、奇数番号の画像には別のマスクが必要です。
最初のマスク:
mask:
linear-gradient(-90deg,#0000 calc(2*var(--s)),#000 0) var(--s),
radial-gradient(var(--s),#000 98%,#0000) 50% / calc(2*var(--s)) calc(1.8*var(--s)) space repeat;
XNUMX番目のもの:
mask:
radial-gradient(calc(var(--s) + var(--g)) at calc(var(--s) + var(--g)) 50%,#0000 98% ,#000)
calc(50% - var(--s) - var(--g)) / 100% calc(1.8*var(--s))
ここで行った唯一の作業は、XNUMX 番目のマスクを更新してギャップ変数 (--g
) 画像間にそのスペースを作成します。
最後の仕上げは、最初と最後の画像を修正することです。 前のすべての例と同様に、最初の画像にはまっすぐな左端が必要ですが、最後の画像にはまっすぐな右端が必要です。
最初の画像では、必要なマスクが常にわかっています。これは次のとおりです。
.gallery > img:first-child {
mask:
radial-gradient(calc(var(--s) + var(--g)) at right, #0000 98%, #000) 50% / 100% calc(1.8 * var(--s));
}
最後の画像の場合、要素の数に依存するため、その要素が :nth-child(odd)
or :nth-child(even)
.
.gallery > img:last-child:nth-child(even) {
mask:
linear-gradient(to right,#0000 var(--s),#000 0),
radial-gradient(var(--s),#000 98%,#0000) left / calc(2*var(--s)) calc(1.8*var(--s)) repeat-y
}
.gallery > img:last-child:nth-child(odd) {
mask:
radial-gradient(calc(var(--s) + var(--g)) at left,#0000 98%,#000) 50% / 100% calc(1.8*var(--s))
}
それで全部です! XNUMX つの異なるレイアウトですが、毎回同じ CSS トリック:
- ズーム効果を作成するコード構造
- シェイプを作成するためのマスクまたはクリップパス
- 場合によっては、完全なオーバーラップを確保するための奇数要素の個別の構成
- 片側のみの形状を維持するための最初と最後の画像の特定の構成。
そして、ここにそれらすべてをまとめた大きなデモがあります。 必要なのは、見たいレイアウトをアクティブにするクラスを追加することだけです。
そして、ここにFlexbox実装のものがあります
包み込む
おっと、これで完了です! この記事と前回の記事の間には、多くの CSS のトリックと例があることはわかっています。もちろん、私が書いた他の記事から参照した他のすべてのトリックは言うまでもありません。 すべてをまとめるのに時間がかかりました。一度にすべてを理解する必要はありません。 XNUMX 回読むだけですべてのレイアウトの概要を把握できますが、すべてのトリックを把握するには、記事を複数回読んで各例に集中する必要がある場合があります。
おそらくマークアップ内の画像の数を除いて、HTML にはまったく触れていないことに気付きましたか? 作成したすべてのレイアウトは同じ HTML コードを共有していますが、これは画像のリストにすぎません。
話を終える前に、最後の例を XNUMX つ紹介します。 クールなホバー効果を持つ XNUMX つのアニメ キャラクターの「対」です。
あなたはどうですか? 学んだことを基に何かを作ることはできますか? 複雑である必要はありません。私がアニメの対戦で行ったように、クールで面白いものを想像してみてください。 それはあなたにとって良い練習になる可能性があり、コメント セクションでの優れたコレクションで終了する可能性があります。