エクスレラ8

アバターの派手なホバー効果

誰かの頭が円や穴から突き出ているような効果を知っていますか? 一連の赤い輪から飛び出しながら別れを告げる有名なポーキー ピッグのアニメーションは、その完璧な例です。 Kilian Valkhof は、CSS-Tricks で実際にそれを再作成しました。.

私も似たようなアイデアを持っていますが、別の方法で、アニメーションを少し加えて取り組みました。 これはかなり実用的で、自分のアバターのようなものに使用できるきちんとしたホバー効果になると思います。

わかりますか? アバターが入っているサークルから飛び出してきたようなスケーリング アニメーションを作成します。いいですね。 コードを見ないで、一緒にこのアニメーションを段階的に作成しましょう。

HTML: たった XNUMX つの要素

デモのコードを確認しておらず、いくつあるのか疑問に思っている場合は、 divマークアップは単一の画像要素にすぎないため、これで終わりです。

<img src="" alt="">

はい、単一の要素です。 この演習の難しい部分は、可能な限り最小限のコードを使用することです。 あなたがされている場合 私をフォロー しばらくの間、これに慣れる必要があります。 私は可能な限り最小で最もメンテナンスしやすいコードで実現できる CSS ソリューションを見つけようと懸命に努力しています。

私が書いた 一連の記事 CSS-Tricks では、単一の要素を含む同じ HTML マークアップを使用してさまざまなホバー効果を調べます。 グラデーション、マスキング、クリッピング、アウトライン、さらにはレイアウト テクニックについても詳しく説明します。 この投稿で多くのトリックを再利用するので、それらをチェックすることを強くお勧めします.

背景が透明な正方形の画像ファイルが、ここでの作業に最適です。 あなたがそれから始めたいなら、これが私が使っているものです。

によって設計された チャン

実際の画像を使用したこの例をできるだけ多く見たいと思っています。コレクションを作成できるように、完了したらコメントで最終結果を共有してください!

CSS に飛び込む前に、まず効果を分析しましょう。 ホバーすると画像が大きくなるので、必ず使用します transform: scale() そこで。 アバターの後ろに円があり、放射状のグラデーションでうまくいくはずです。 最後に、円の下部にアバターの外観を作成する境界線を作成する方法が必要です。

仕事に行きましょう!

スケール効果

変換を追加することから始めましょう。

img { width: 280px; aspect-ratio: 1; cursor: pointer; transition: .5s;
}
img:hover { transform: scale(1.35);
}

まだ複雑なことはありませんよね? 次へ移りましょう。

サークル

背景は放射状のグラデーションになると言いました。 放射状グラデーションの色の間にハード ストップを作成できるため、これは完璧です。これにより、実線で円を描いているように見えます。

img { --b: 5px; /* border width */ width: 280px; aspect-ratio: 1; background: radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), #C02942 calc(100% - var(--b)) 99%, #0000 ); cursor: pointer; transition: .5s;
}
img:hover { transform: scale(1.35);
}

CSS 変数に注意してください。 --b、 そこで使っています。 これは、放射状グラデーションの赤い部分のハード カラー ストップを定義するために実際に使用されている「境界線」の太さを表します。

次のステップは、ホバー時にグラデーション サイズを操作することです。 画像が大きくなっても、円はそのサイズを維持する必要があります。 を適用していますので、 scale() 変換する必要があります 減少 それ以外の場合はアバターに合わせて拡大するため、円のサイズ。 したがって、画像が拡大する間、縮小するにはグラデーションが必要です。

CSS変数を定義することから始めましょう。 --f、「倍率」を定義し、それを使用して円のサイズを設定します。 私は使用しています 1 デフォルト値として、それが画像の初期スケールであり、変換元の円です。

このトリックを説明するデモを次に示します。 ホバーして、舞台裏で何が起こっているかを確認します。

XNUMX色目を追加しました radial-gradient ホバー時にグラデーションの領域をより適切に識別するには:

radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), #C02942 calc(100% - var(--b)) 99%, lightblue
);

次に、背景を円の中心に配置し、高さ全体を占めるようにする必要があります。 私はすべてを直接宣言するのが好きです background 省略形のプロパティなので、背景の配置を追加し、それらの値を radial-gradient():

background: radial-gradient() 50% / calc(100% / var(--f)) 100% no-repeat;

背景は中央に配置されます (50%)、幅は calc(100%/var(--f))、高さは 100%.

次の場合は何もスケーリングしません --f 等しい 1 — 繰り返しますが、最初のスケールです。 一方、グラデーションはコンテナの全幅を占めます。 増やすと --f、要素のサイズが大きくなります — のおかげで scale() 変換 — グラデーションのサイズが小さくなります。

これらすべてをデモに適用すると、次のようになります。

近づいてきました! 上部にオーバーフロー効果がありますが、画像の下部を非表示にする必要があるため、円の前に座っているのではなく、円から飛び出しているように見えます. それがこの全体のトリッキーな部分であり、次にやろうとしていることです.

下の境界線

私は最初にこれに取り組んでみました border-bottom プロパティですが、境界線のサイズを円のサイズに合わせる方法を見つけることができませんでした。 これが私が得ることができる最高のものであり、すぐにそれが間違っていることがわかります:

実際の解決策は、 outline 財産。 はい、 outlineはなく、 border。 に 前の記事、方法を示します outline は強力で、クールなホバー効果を作成できます。 と組み合わせ outline-offset、私たちは効果に必要なものを正確に持っています。

アイデアは、設定することです outline をクリックし、そのオフセットを調整して下の境界線を作成します。 オフセットは、グラデーション サイズと同じようにスケーリング係数に依存します。

これで、下の「境界線」ができました (実際には outline)グラデーションによって作成された「境界線」と組み合わせて、完全な円を作成します。 まだ一部を非表示にする必要があります outline (上部と側面から) これについてはすぐに説明します。

これまでのコードには、画像サイズを構成するために使用できるいくつかの CSS 変数が含まれています (--s) と「境界線」の色 (--c):

img { --s: 280px; /* image size */ --b: 5px; /* border thickness */ --c: #C02942; /* border color */ --f: 1; /* initial scale */ width: var(--s); aspect-ratio: 1; cursor: pointer; border-radius: 0 0 999px 999px; outline: var(--b) solid var(--c); outline-offset: calc((1 / var(--f) - 1) * var(--s) / 2 - var(--b)); background: radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), var(--c) calc(100% - var(--b)) 99%, #0000 ) 50% / calc(100% / var(--f)) 100% no-repeat; transform: scale(var(--f)); transition: .5s;
}
img:hover { --f: 1.35; /* hover scale */
}

円形の下枠が必要なので、 border-radius 下側で、 outline グラデーションの曲率に合わせます。

で使用される計算 outline-offset 見た目よりずっと簡単です。 デフォルトでは、 outline 描かれています 外側 要素のボックスの。 そして私たちの場合、それが必要です オーバーラップ 要素。 より正確には、グラデーションによって作成された円をたどる必要があります。

バックグラウンド遷移の図。

要素をスケーリングすると、円とエッジの間にスペースが表示されます。 スケール変換の実行後も円を同じサイズに保つという考え方を忘れないでください。これにより、上の図に示すように、アウトラインのオフセットを定義するために使用するスペースが残ります。

XNUMX 番目の要素がスケーリングされるため、結果もスケーリングされることを忘れないでください。つまり、結果を で割る必要があります。 f 実際のオフセット値を取得するには:

Offset = ((f - 1) * S/2) / f = (1 - 1/f) * S/2

アウトラインを外側から内側に移動する必要があるため、マイナス記号を追加します。

Offset = (1/f - 1) * S/2

これは、アウトラインがグラデーションにどのように追従するかを示す簡単なデモです。

すでに表示されているかもしれませんが、下のアウトラインが円を通り抜けるのではなく、円に重なるようにする必要があります。 境界線のサイズをオフセットから削除することで、これを行うことができます。

outline-offset: calc((1 / var(--f) - 1) * var(--s) / 2) - var(--b));

次に、アウトラインから上部を削除する方法を見つける必要があります。 つまり、画像の下部のみが必要です outline.

まず、上部の重なりを避けるために、パディングで上部にスペースを追加しましょう。

img { --s: 280px; /* image size */ --b: 5px; /* border thickness */ --c: #C02942; /* border color */ --f: 1; /* initial scale */ width: var(--s); aspect-ratio: 1; padding-block-start: calc(var(--s)/5); /* etc. */
}
img:hover { --f: 1.35; /* hover scale */
}

その上部のパディングには特定のロジックはありません。 アイデアは、アウトラインがアバターの頭に触れないようにすることです。 要素のサイズを使用して、そのスペースが常に同じ比率になるように定義しました。

を追加したことに注意してください content-box に値 background:

background: radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), var(--c) calc(100% - var(--b)) 99%, #0000 ) 50%/calc(100%/var(--f)) 100% no-repeat content-box;

これが必要なのは、パディングを追加し、背景をコンテンツ ボックスに設定したいだけなので、背景をそこで停止するように明示的に指示する必要があるためです。

ミックスに CSS マスクを追加する

最後の部分に到達しました! いくつかのピースを非表示にするだけで、完了です。 これについては、 mask プロパティ、そしてもちろんグラデーション。

これは、より正確にするために何を隠す必要があるか、または何を示す必要があるかを示す図です

マスクが円の下部にどのように適用されるかを示します。

左の画像が現在のもので、右が欲しいものです。 緑色の部分は、最終結果を得るために元の画像に適用する必要があるマスクを示しています。

マスクの XNUMX つの部分を識別できます。

  • アバターの後ろに円を作成するために使用した放射状グラデーションと同じ寸法と曲率を持つ下部の円形部分
  • アウトライン内の領域を覆う上部の長方形。 アウトラインが上部の緑色の領域の外側にあることに注意してください。これは最も重要な部分です。これにより、下部のみが表示されるようにアウトラインを切り取ることができるからです。

最終的な CSS は次のとおりです。

img { --s: 280px; /* image size */ --b: 5px; /* border thickness */ --c: #C02942; /* border color */ --f: 1; /* initial scale */ --_g: 50% / calc(100% / var(--f)) 100% no-repeat content-box; --_o: calc((1 / var(--f) - 1) * var(--s) / 2 - var(--b)); width: var(--s); aspect-ratio: 1; padding-top: calc(var(--s)/5); cursor: pointer; border-radius: 0 0 999px 999px; outline: var(--b) solid var(--c); outline-offset: var(--_o); background: radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), var(--c) calc(100% - var(--b)) 99%, #0000) var(--_g); mask: linear-gradient(#000 0 0) no-repeat 50% calc(-1 * var(--_o)) / calc(100% / var(--f) - 2 * var(--b)) 50%, radial-gradient( circle closest-side, #000 99%, #0000) var(--_g); transform: scale(var(--f)); transition: .5s;
}
img:hover { --f: 1.35; /* hover scale */
}

それを分解しましょう mask 財産。 まず、同様の radial-gradient() background プロパティはそこにあります。 新しい変数を作成しましたが、 --_g、共通部分が物事を混乱させないようにするため。

--_g: 50% / calc(100% / var(--f)) 100% no-repeat content-box; mask: radial-gradient( circle closest-side, #000 99%, #0000) var(--_g);

次に、 linear-gradient() そこにも:

--_g: 50% / calc(100% / var(--f)) 100% no-repeat content-box; mask: linear-gradient(#000 0 0) no-repeat 50% calc(-1 * var(--_o)) / calc(100% / var(--f) - 2 * var(--b)) 50%, radial-gradient( circle closest-side, #000 99%, #0000) var(--_g);

これにより、マスクの長方形部分が作成されます。 その幅は、放射状グラデーションの幅から境界線の太さの XNUMX 倍を引いた値に等しくなります。

calc(100% / var(--f) - 2 * var(--b))

長方形の高さは半分に等しく、 50%、要素のサイズ。

また、水平方向の中央に配置された線形グラデーションも必要です (50%)、アウトラインのオフセットと同じ値だけ上部からオフセットします。 別の CSS 変数を作成しましたが、 --_o、前に定義したオフセットについて:

--_o: calc((1 / var(--f) - 1) * var(--s) / 2 - var(--b));

ここで紛らわしいことの XNUMX つは、 アウトラインのオフセット(外側から内側に移動するため)ですが、 正の グラデーションのオフセット (上から下に移動)。 では、なぜオフセットを乗算するのか疑問に思われる場合は、 --_o、によって -1、まあ、今あなたは知っています!

マスクのグラデーション構成を説明するデモは次のとおりです。

上にカーソルを合わせて、すべてが一緒に移動する様子を確認してください。 中央のボックスは、XNUMX つのグラデーションで構成されるマスク レイヤーを示しています。 左の画像の目に見える部分だと想像してください。最終的な結果が右に表示されます!

包み込む

おっと、これで完了です。 洗練されたホバー アニメーションを作成しただけでなく、すべてを XNUMX つの HTML で実現しました。 <img> エレメント。 それだけで、CSS トリックは 20 行未満です。

確かに、このような複雑な効果を実現するために、いくつかの小さなトリックと数式に依存していました。 しかし、事前に必要な部分を特定していたので、何をすべきかは正確にわかっていました。

もっと HTML を許可すれば、CSS を簡素化できたでしょうか? 絶対。 しかし、私たちは新しい CSS トリックを学ぶためにここにいます! これは、CSS グラデーション、マスキング、 outline プロパティの動作、変換、その他多数。 どこかで迷ったら、ぜひチェックしてみてください 私のシリーズ 同じ一般的な概念を使用します。 より多くの例やユースケースを見ると、ポイントを理解するのに役立つ場合があります。

最後に、人気の CSS 開発者の写真を使用したデモを XNUMX つ紹介します。 コレクションに追加できるように、あなた自身の画像のデモを見せてください!

私たちとチャット

やあ! どんな御用でしょうか?