『CSS Secrets』は、@Lea Verou による最新の本で、CSS に関する小さな秘密を説明しています。これは CSSers にとって読む価値のある本です。一定期間読んだ後、私、@全域と @彦子は、関連する読書感想文を W3cplus で公開し、皆さんと共有します。
問題
私たちは 44 年前に月に人類を送りましたが、いまだに CSS で垂直方向の中央揃えをうまく実現できません - @James Anderson
CSS を使用すると、要素を水平方向に中央揃えするのは非常に簡単です。インライン要素の場合は、その親要素に text-align:center; を設定できます。ブロック要素の場合は、margin:auto; を使用できます。しかし、要素を垂直方向の中央に配置することを考えるだけで、死にたくなります。
長年にわたり、垂直方向のセンタリングは CSS に関する不朽の神話であり、フロントエンドの専門家の間での内輪ジョークとなってきました。その理由は次のとおりです:
- 多くの場合
- を使用する必要があります
- 理論的には非常に簡単に見えます
以前は、特に要素サイズが固定されている場合、実際に実装するのは非常に困難でした
フロントエンド開発者は試してきました彼らは長年にわたってこの問題を解決するために最善を尽くしてきましたが、中国共産党にとって最も憂慮すべき点は、多くのハッキング手法を使用していることです。このセクションでは、垂直方向のセンタリングを実現するための最新のテクニックをいくつか紹介します。 ここでは説明されていない一般的なテクニックがいくつかあることに注意してください。主な理由は次のとおりです。 -
- 冗長な HTML タグが必要なため、テーブル レイアウト (テーブル表示モード) については説明されていません
inline-block メソッドは、使用が必要なため含まれていませんたくさんのハック
ただし、この側面に興味がある場合は、これら 2 つのテクニックを紹介している Chris Coyier によるブログ投稿「Centering in the Unknown」を読むことができます。
特別な宣言がない場合、次の例で使用される HTML 構造は、
要素に次のタグを挿入します:
<main> <h1>Am I centered yet?</h1> <p>Center me, please!</p></main>
ログイン後にコピー
以下の図に示す効果を得るために、いくつかのタグも適用します。背景、パディングなどの基本的な CSS スタイル:
絶対位置決めソリューション
垂直方向の中央揃えを実現するための最も初期のテクニックは、要素に固定の幅と高さを必要とすることです:
main { position: absolute; top: 50%; left: 50%; margin-top: -3em; /* 6/2 = 3 */ margin-left: -9em; /* 18/2 = 9 */ width: 18em; height: 6em;}
ログイン後にコピー
本質的には、左上を移動します。要素の角をビューポートの中心に合わせてから、負のマージンを使用します (margin-top と margin-left を使用)。マージンの値は要素の幅と高さの半分であるため、要素の中心点は一致します。ビューポートの中心点と一致します。 calc() を使用すると、次の 2 つのスタイルを削減できます:
main { position: absolute; top: calc(50% - 3em); left: calc(50% - 9em); width: 18em; height: 6em;}
ログイン後にコピー
明らかに、このメソッドの最大の問題は、要素に固定サイズが必要であり、垂直方向の中央に配置する必要がある要素のサイズを決定する必要があることが多いことです。その内容によって。パーセンテージを使用して要素のサイズを制御する方法があれば、問題は解決されるでしょう。残念ながら、ほとんどの CSS プロパティ ( margin を含む) では、パーセンテージ値は親要素の幅を基準にして決定されます。
CSS でこれほど多くのソリューションがあるのは信じられないほどです。この例では、CSS3 変換を使用できます。変換のtranslate()でパーセントを使用すると、要素を独自の幅と高さに応じて移動させることができます。これはまさに必要なものです。
そうです
もちろん、完璧なテクノロジーはありません。実際の使用では、次の点に注意する必要があります: -
- 絶対位置決めは全体のレイアウトに大きな影響を与えるため、通常は良い選択ではありません。
- 垂直方向の中央にある要素のコンテンツがビューポートの高さより高い場合、下の図に示すように、その上部が切り取られます。ただし、この問題は解決できますが、いくつかのハック方法を使用する必要があります。
一部のブラウザでは、要素が 0.5 ピクセルの位置に配置されるため、要素がわずかにぼやけて見える場合があります。これは、transform-style:preserve-3d で解決できますが、これはハックであり、古くならないという保証はありません。
ビューポート単位のソリューション
絶対位置指定の使用を避けたい場合でも、要素の幅と高さのちょうど半分の値をもつtranslate()メソッドを使用できます。しかし、top と left を使用せずに要素を上と左から 50% オフセットして移動するにはどうすればよいでしょうか?
最初に思い浮かぶのは、次のように margin プロパティにパーセンテージを与えることです:
main { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);}
ログイン後にコピー
ただし、その効果は以下に示すように:
これにより、非常に奇妙な効果が作成されます。主な理由は、マージンのパーセンテージ計算が親コンテナの幅を基準にして計算されるためです。はい、margin-top と margin-bottom も含まれます。
🎜 ありがたいことに、要素をビューポートの中央に配置したい場合は、まだ希望があります。 CSS 値と単位 レベル 3 では、ビューポート相対長さ単位と呼ばれる新しい単位が定義されます。 🎜
- vw 是相对于视窗的宽度。与你预期刚好相反, 1vw 相当于视窗宽度的 1% ,而不是 100%
- 与 vw 相似的是, 1vh 相当于视窗高度的 1%
- 如果视窗的宽度小于高度, 1vmin 等于 1vw ,反之,如果视窗宽度大于高度, 1vmin 等于 1vh
- 如果视窗的宽度大于高度, 1vmax 等于 1vw ,反之,如果视窗宽度小于高度, 1vmax 等于 1vh
在这个示例中,我们需要给 margin 的值设置 vh 单位:
main { width: 18em; padding: 1em 1.5em; margin: 50vh auto 0; transform: translateY(-50%);}
ログイン後にコピー
正如你看到效果很完美。
当然,这种方法有用性是有极限的,因为它只适用于元素在视窗中垂直居中。
请注意,还可以使用相对视窗单位来创建全屏效果,而且不需要使用任何脚本。更多细节可以阅读 Andrew Ckor 写的《 Make full screen sections with 1 line of CSS 》博文。
Flexbox的解决方案
这无疑是最好的解决方案,因 Flexbox 的出现就是为了解决这样的问题。其他解决方案仍然可用,唯一原因是他们能更好的在浏览器上呈现,不过Flexbox在现代浏览器也得到更好的好支持。
只需要两个样式,在需要垂直居中的父元素上设置 display:flex (这个示例中就是
)和在垂直居中的元素上设置 margin:auto (这个示例中就是
): body { display: flex; min-height: 100vh; margin: 0; }main { margin: auto;}
ログイン後にコピー
注意,当使用Flexbox和 margin:auto 时,元素不仅水平居中,而且也会垂直居中。也注意,我们甚至没有设置宽度(如果我们想要也可以设置),其实指定的宽度相当于 max-content 。
如果浏览器不支持Flexbox,那么结果看起来就会像下图(如果我们给元素设置了宽度):
即使不是垂直居中,还是可以接受的。
Flexbox的另一个优点是,可以让匿名容器垂直居中。例如,我们将结构换成:
<main>Center me, please!</main>
ログイン後にコピー
我们可以通过 align-items 和 justify-content 属性使设置固定尺寸的 容器里面的文本居中。如下图所示:
我们可以在
和需要居中的元素 使用相同的属性,同时使用 margin:auto 做为备用,以于优雅降级。 main { display: flex; align-items: center; justify-content: center; width: 18em; height: 10em;}
ログイン後にコピー
新特性:对齐所有东西
CSS Box Alignment Level 3 已经在计划,在未来我们甚至不需要使用不同的布局模式就能非常容易的实现垂直居中,我们只需要像下面这样做:
align-self: center;
ログイン後にコピー
不管元素上使用其他样式,这个将来都能运行。这听起来令人难以置信,但将来在浏览器中是可以渲染的。