ホームページ  >  記事  >  ウェブフロントエンド  >  知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

青灯夜游
青灯夜游転載
2021-07-21 19:47:074494ブラウズ

この記事では、一般的または特殊なレイアウトを実現するための、あまり知られていないかもしれないが非常に実用的な 純粋な CSS レイアウトと植字テクニックをいくつか紹介します。

知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

あらゆる Web ページの開発は、

レイアウトと組版 から切り離せません。優れた レイアウトと組版 の基礎を築くことによってのみ、その後の開発をよりスムーズにします。もちろん、IExplorer 時代の限定的な考え方に留まっているわけにはいかず、解決できない レイアウトや組版はすべて JS で実装されています。現在は過去とは異なり、最新の CSS プロパティを使用すると、さまざまなレイアウトやレイアウトをより適切かつ迅速に実装できるため、より多くの時間を節約できます。 ただし、作成者の現在の理解によれば、IExplorer# と互換性がある必要がない場合でも、ほとんどの学生は依然として

CSS JS

メソッドに従っていくつかの を完了しています。 ## 一般的なレイアウトまたは特殊なレイアウト レイアウト HTML/CSS/JS のフロントエンド三銃士の位置付けの観点から見ると、HTML は Web ページの 構造 をマップし、CSS は Web ページの ## をマップします。 #PerformanceJS Web ページの behavior をマップします。 レイアウトと組版とは、グラフィックス、テキスト、画像などの視覚情報要素の position

size、およびその他の属性を調整することを指します。ページ レイアウト上のメディア ページ レイアウトが整理されるプロセス。ほとんどの学生は、layout はいくつかの妥当な CSS プロパティを無造作にまとめたものだと考えていますが、ほとんどの場合、たとえ実装されても欠陥があり、JS が介入するために使用される可能性があります。 レイアウトと組版の特徴から、これは カテゴリに属していることがわかり、著者は、ほとんどの

レイアウトと組版

純粋な CSS Complete を使用でき、JS の介入は必要ありません。 この記事では、CSS を使用して実現できる効果については CSS を優先するという 原則に準拠し、著者がさまざまな純粋な CSS 開発テクニックを巧みに使用して、いくつかの を完成させる方法について説明します。一般または特殊なレイアウトの植字

属性トピックに入る前に、著者は

レイアウトと組版

いくつかの必要な属性を要約します。これらの属性は全体的な効果をすばやく構築できます。一部の一般的なセレクターは、完璧な結果を達成するために変更されています。簡単そうに見えますが、使いこなすのは難しいかもしれません。 必須属性はいくつかの幾何学的属性であり、主に

位置

および サイズ を宣言するために使用されます。

#フローティング レイアウト:フロート

  • ##配置レイアウト:position / left/right/top/bottom/z-index
  • 柔軟なレイアウトdisplay:flex/inline-flex flexシリーズ プロパティ
  • #ボックス モデル:ボックス サイズ/マージン/パディング/境界線/幅/高さ
  • #CSSモジュール
  • から派生したセレクターの数も多く、これらのセレクターに対応する機能を特別に覚えておかないと、最大限の効果を発揮することが困難です。 筆者はセレクターを機能別に8つのカテゴリーに分類しており、各カテゴリーのセレクターはアプリケーションシナリオで組み合わせることができますので、これらのカテゴリーのセレクターを覚えておけば、最大限の効果を発揮できると思います。セレクター機能を使用すると、いくつかの 一般的なレイアウトまたは特殊なレイアウト にも簡単に適用できます。
Layout

は特定のセレクターにのみ適用される場合がありますが、次の分類方法を使用して誰もがそれを覚えることが妨げられるわけではありません。 CSS の重要な部分として、セレクターには属性の組み合わせ以外にもさまざまな方法があります。 #基本セレクター

セレクターエイリアス

説明

バージョン
一般的に使用される##タグtag1id タグを指定します1.class タグを指定します#1√2√

階層セレクター

タグセレクター タイプを指定します
ID セレクター アイデンティティの
クラスセレクター クラス名の
* ワイルドカード セレクター すべてのタイプのタグ
セレクターエイリアス説明バージョン 一般的に使用される#elemP elemCelemP>elemC# の子孫要素## 要素の子要素elem1 elem2隣接する兄弟セレクター# の後の 兄弟要素## 要素 ##セレクターエイリアス
#子孫セレクター element 1
##子セレクター ##2#√
隣接する要素 兄弟要素 2 ##elem1~elem2 ユニバーサル兄弟セレクター
#3 コレクション セレクター
説明

バージョン
一般的に使用されるelem1,elem2共用体セレクター複数指定された 要素指定しますクラス名の #1条件セレクターバージョン
1 ##elem.class 交差セレクター 要素
#セレクター 説明
一般的に使用される

#:lang 要素を指定します##:dir()×#:指定された要素を含む :条件##4##:not 条件が指定されていない要素 :where# 条件を指定する要素 ##要素##を指定 ##参照点として #4## リンク要素を含むすべてのリンク##4すべて href4マウスがアクティブになりました 11 √未訪問 1 xx 訪問済み 1×#:target 要素xx:focus##必須の フォーム要素を入力してください:有効な法的なフォーム要素を入力してください:invalid入力が不正です フォーム要素:in-range 入力範囲内のフォーム 要素#:out-of-range入力範囲 ×##:チェック済み フォーム要素 オプションはオプション3イベントが有効になりました3フォーム要素#3√読み取り専用3#読み取りおよび書き込み可能 3対象となる 4×内部フォーム要素はフォーカスされた状態です4√ フォーカスされた 4×入力が空です 4×有効な 4×オプションは未定です4× ##:プレースホルダーで表示4√#一時停止中4×

構造セレクター

#マークアップ言語の 2
書き込み方向を指定する要素 4
## 要素があります 4 ×
#を指定する #要素#です。
4
4 × #:スコープ
#:any-link #href# の
× ##:ローカルリンク を含み、絶対アドレス
× を含むリンク要素<blockquote><p>ステータス セレクター</p></blockquote> <table> <thead><tr class="firstRow"> <th align="center">セレクター</th> <th>説明</th> <th align="center">バージョン</th> <th align="center">一般的に使用される </th> </tr></thead> <tbody> <tr> <td align="center">#:active<code> 要素
#:ホバー 要素
:リンク リンク要素
:訪問済み リンク要素
現在のアンカー ポイントの # #3
フォーカスされた フォーム要素を入力してください 2 #:必須
3
3
3
3
# 以外のフォーム要素##3 オプションが選択されました
3 ##:オプション フォーム要素
:enabled フォーム要素
× #:無効 イベント無効
:読み取り専用 フォーム要素
#:読み取り-書き込み フォーム要素
:target-within 要素アンカー要素がアクティブ化されます
:focus-within element
:focus-visible フォーム要素を入力してください
:blank フォーム要素
:user-invalid フォーム要素を入力してください
:indeterminate フォーム要素
##プレースホルダーで表示#フォーム要素
##:current() ブラウジング中の要素 4
#:past() 閲覧した 要素 4 ×
:future() 未閲覧Element 4 xx
:再生中 再生開始メディア要素 4 ×
:一時停止中 メディア要素
#3√要素 3×##:first-child 要素の最初の 2√ 要素で終わる 3√親要素には、この要素の 3√タグ内のシーケンシャルインデックスを指定する 3√##タグで逆インデックスを指定します。タグ##:first-of-type#3#タグは末尾です3√##:only- of-type#3√##属性セレクターセレクター#説明バージョン
セレクター 説明 バージョン 一般的に使用される
:root ドキュメントの ルート要素 3 ×
:子要素のない空の 要素 3
:nth-child(n) element## で指定されたシーケンシャル インデックスの要素
:nth-last-child(n) 逆インデックスを指定する要素
要素
:last-child 要素
:only-child 要素のみが含まれます
:nth-of-type(n) タグ
:nth-last-of-type(n) #3##× # # tag## タグ
#√ :last-of-type## の最初のタグですtag
親要素には、タグ
# の タグのみがあります。
一般的に使用される

指定された属性の 2√ 要素 [attr^=val] 要素 [attr$=val] 要素[attr~=val] (非推奨) #[attr|=val]疑似要素
[attr] 要素
[attr=val] 属性が等しい 要素指定された値 ##2
##[attr*=val] #属性に指定された値が含まれる # 3
属性が指定された値で始まる 3
属性は指定された値で終わります 3
指定された値を持つ 要素を含む属性 (完全な単語) 2
#属性が次で始まる 要素指定された値 (完全な単語) (非推奨) 2×
セレクター説明 バージョン 一般的に使用される

##::before
挿入された要素の前 content##::after2##::first-letter 要素の最初の文字::first-line 要素の最初の行#::selection マウスによって選択された 要素 # 要素##: :placeholder4
2
要素の後に挿入されるコンテンツ
1 ×
1
#3 #:: 全画面モードの背景
4 ## フォーム要素のプレースホルダー
<h2><strong>ヒント</strong></h2> <p>上記の前提知識を踏まえて、著者に従って、さまざまな純粋な CSS 開発テクニックを巧みに使用して、いくつかの <code>一般的なレイアウトまたは特殊なレイアウトを完成させる方法を体験してみましょう。バー。ブラウザが特定のスタイルを自動的に計算できるようにするには、box-sizing:border-box をグローバルに設定する必要があります。コーディングする前に、作者がまとめた reset.css を導入してください。

メイン レイアウト

メイン レイアウトは、ほとんどの状況で共通で均一な特性を持つプレースホルダー レイアウトを指します。 メイン レイアウトを習得することはフロントエンドの重要なスキルです。設計図を見て全体のレイアウトの大まかな計画を作成するには、これらの メイン レイアウト##の特徴と構造を理解しておく必要があります。 #。

全画面レイアウト
クラシック

全画面レイアウトは、topbottom、# で構成されます。 ## 本体 は 3 つのパーツから構成されており、その特徴は 3 つのパーツを左右に全画面に引き伸ばす 上下の高さが固定であることです。 、および 本体の高さは適応型です。このレイアウトは非常に一般的で、ほとんどの Web アプリケーション本体の主流のレイアウトでもあります。通常、3 つのタグ <header></header><footer></footer>、および <main></main> がセマンティック タイプセットに使用されます。 <aside></aside>sidebar またはその他のセマンティック タグを # 内に挿入することもできます。

<div class="fullscreen-layout">
    <header></header>
    <main></main>
    <footer></footer>
</div>
位置左/右/上/下

知っておく価値のある 8 つの純粋な CSS レイアウト テクニック3 つの部分からなる統合ステートメント

left:0

right:0

right:0

を左右に引き伸ばして画面いっぱいにします。吸い込むには、上部と下部で top:0bottom:0 をそれぞれ宣言します。それを上部と下部に設定し、2 つの高さを固定値として宣言します。ボディの topbottom をそれぞれ上部の高さと下部の高さとして宣言します。 3つの部品は相互に影響を及ぼさないように絶対位置決めにより特定の位置に固定されています。 <pre class="brush:css;toolbar:false;">.fullscreen-layout { position: relative; width: 400px; height: 400px; header, footer, main { position: absolute; left: 0; right: 0; } header { top: 0; height: 50px; background-color: #f66; } footer { bottom: 0; height: 50px; background-color: #66f; } main { top: 50px; bottom: 50px; background-color: #3c9; } }</pre>flex

flex

を使用するとより簡潔になります。
display:flex

デフォルトでは、子ノードは水平に配置されます。これを宣言する必要があります。flex-direction:column子ノードの配置方向を垂直配置に変更します。底部の高さは固定されているため、本体を宣言する必要がありますflex:1高さを適応型にします。 <pre class="brush:css;toolbar:false;">.fullscreen-layout { display: flex; flex-direction: column; width: 400px; height: 400px; header { height: 50px; background-color: #f66; } footer { height: 50px; background-color: #66f; } main { flex: 1; background-color: #3c9; } }</pre><main></main> をスクロール可能な状態で表示する必要がある場合は、コンテナが適応的にスクロールできるように

overflow:auto

を宣言しないでください。他の問題の原因となる 書式設定コンテキストにより、適応スクロールが失敗したり、その他の未知の影響が発生したりする可能性があります。

<main></main> 内に挿入し、次のように宣言する必要があります。 <pre class="brush:css;toolbar:false;">div { overflow: hidden; height: 100%; }</pre>2 列レイアウト
クラシック 2 列レイアウト
左列と右列

で構成され、その特徴は、1 つの列の幅は固定です もう 1 つの列の幅は適応的です 、および 2 つの列の高さは固定されており等しいです。以下では、例として左側の列幅を固定、右側の列幅を適応型として取り上げており、その逆も同様です。

<div class="two-column-layout">
    <div class="left"></div>
    <div class="right"></div>
</div>

float margin-left/right知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

左列宣言

float:left

および固定幅、
float

によりノードがデフローするため、2 つの列が重ならないように、右列で左列の幅として margin-left を宣言する必要があります。 <pre class="brush:css;toolbar:false;">.two-column-layout { width: 400px; height: 400px; .left { float: left; width: 100px; height: 100%; background-color: #f66; } .right { margin-left: 100px; height: 100%; background-color: #66f; } }</pre>overflow float

左の列は上記と同じを宣言し、右の列は

overflow:hidden

を宣言して
を形成しますBFC エリア

with 外界から隔離されています。 <pre class="brush:css;toolbar:false;">.two-column-layout { width: 400px; height: 400px; .left { float: left; width: 100px; height: 100%; background-color: #f66; } .right { overflow: hidden; height: 100%; background-color: #66f; } }</pre>flex

flex

を使用するとより簡潔になります。左の列は固定幅を宣言し、右の列は
flex:1

適応幅を宣言します。 <pre class="brush:css;toolbar:false;">.two-column-layout { width: 400px; height: 400px; .left { float: left; width: 100px; height: 100%; background-color: #f66; } .right { overflow: hidden; height: 100%; background-color: #66f; } }</pre>3 列レイアウト

クラシック 3 列レイアウトは、
左、中、右の列で構成されます。その特徴は次のとおりです:

連続する 2 つの列の幅は固定です残りの列の幅は適応的です、および 3 つの列の高さは固定されており等しい## #。以下では、例として左中央の列の固定幅と右列の適応幅を取り上げており、その逆も同様です。全体的な実装原則は、上記の 2 列のレイアウトと一致しています。

<div class="three-column-layout">
    <div class="left"></div>
    <div class="center"></div>
    <div class="right"></div>
</div>
右列の幅を適応的に計算するために、float margin-left

メソッドは使用されません。 #margin-left

左中央の列の幅にも基づいて計算する必要があります。 知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

オーバーフローフロート

.three-column-layout {
    width: 400px;
    height: 400px;
    .left {
        float: left;
        width: 50px;
        height: 100%;
        background-color: #f66;
    }
    .center {
        float: left;
        width: 100px;
        height: 100%;
        background-color: #66f;
    }
    .right {
        overflow: hidden;
        height: 100%;
        background-color: #3c9;
    }
}
flex

.three-column-layout {
    display: flex;
    width: 400px;
    height: 400px;
    .left {
        width: 50px;
        background-color: #f66;
    }
    .center {
        width: 100px;
        background-color: #66f;
    }
    .right {
        flex: 1;
        background-color: #3c9;
    }
}
圣杯布局/双飞翼布局

经典的圣杯布局双飞翼布局都是由左中右三列组成,其特点为左右两列宽度固定中间一列宽度自适应三列高度固定且相等。其实也是上述两列布局和三列布局的变体,整体的实现原理与上述N列布局一致,可能就是一些细节需注意。

圣杯布局双飞翼布局在大体相同下也存在一点不同,区别在于双飞翼布局中间列需插入一个子节点。在常规实现方式里也是在这个中间列里做文章,如何使中间列内容不被左右列遮挡

    <li>相同
      <li>中间列放首位且声明其宽高占满父节点 <li>被挤出的左右列使用floatmargin负值将其拉回与中间列处在同一水平线上
    <li>不同
      <li>圣杯布局:父节点声明padding为左右列留出空位,将左右列固定在空位上 <li>双飞翼布局:中间列插入子节点并声明margin为左右列让出空位,将左右列固定在空位上

知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

圣杯布局float + margin-left/right + padding-left/right

由于浮动节点在位置上不能高于前面或平级的非浮动节点,否则会导致浮动节点下沉。因此在编写HTML结构时,将中间列节点挪到右列节点后面。

<div class="grail-layout-x">
    <div class="left"></div>
    <div class="right"></div>
    <div class="center"></div>
</div>
.grail-layout-x {
    padding: 0 100px;
    width: 400px;
    height: 400px;
    .left {
        float: left;
        margin-left: -100px;
        width: 100px;
        height: 100%;
        background-color: #f66;
    }
    .right {
        float: right;
        margin-right: -100px;
        width: 100px;
        height: 100%;
        background-color: #66f;
    }
    .center {
        height: 100%;
        background-color: #3c9;
    }
}

双飞翼布局float + margin-left/right

HTML结构大体同上,只是在中间列里插入一个子节点<div>。根据两者区别,CSS声明会与上述圣杯布局有一点点出入,可观察对比找出不同地方。<pre class="brush:html;toolbar:false;">&lt;div class=&quot;grail-layout-y&quot;&gt; &lt;div class=&quot;left&quot;&gt;&lt;/div&gt; &lt;div class=&quot;right&quot;&gt;&lt;/div&gt; &lt;div class=&quot;center&quot;&gt; &lt;div&gt;&lt;/div&gt; &lt;/div&gt; &lt;/div&gt;</pre><pre class="brush:css;toolbar:false;">.grail-layout-y { width: 400px; height: 400px; .left { float: left; width: 100px; height: 100%; background-color: #f66; } .right { float: right; width: 100px; height: 100%; background-color: #66f; } .center { margin: 0 100px; height: 100%; background-color: #3c9; } }</pre><blockquote><p>圣杯布局/双飞翼布局flex</p></blockquote> <p>使用flex实现<code>圣杯布局/双飞翼布局可忽略上述分析,左右两列宽度固定,中间列宽度自适应。

<div class="grail-layout">
    <div class="left"></div>
    <div class="center"></div>
    <div class="right"></div>
</div>
.grail-layout {
    display: flex;
    width: 400px;
    height: 400px;
    .left {
        width: 100px;
        background-color: #f66;
    }
    .center {
        flex: 1;
        background-color: #3c9;
    }
    .right {
        width: 100px;
        background-color: #66f;
    }
}
均分布局

经典的均分布局多列组成,其特点为每列宽度相等每列高度固定且相等。总体来说也是最简单的经典布局,由于每列宽度相等,所以很易找到合适的方式处理。

知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

<div class="average-layout">
    <div class="one"></div>
    <div class="two"></div>
    <div class="three"></div>
    <div class="four"></div>
</div>
.one {
    background-color: #f66;
}
.two {
    background-color: #66f;
}
.three {
    background-color: #f90;
}
.four {
    background-color: #09f;
}

float + width

每列宽度声明为相等的百分比,若有4列则声明width:25%。N列就用公式100 / n求出最终百分比宽度,记得保留2位小数,懒人还可用width:calc(100% / n)自动计算呢。

.average-layout {
    width: 400px;
    height: 400px;
    div {
        float: left;
        width: 25%;
        height: 100%;
    }
}

flex

使用flex实现会更简洁。节点声明display:flex后,生成的FFC容器里所有子节点的高度都相等,因为容器的align-items默认为stretch,所有子节点将占满整个容器的高度。每列声明flex:1自适应宽度。

.average-layout {
    display: flex;
    width: 400px;
    height: 400px;
    div {
        flex: 1;
    }
}
居中布局

居中布局父容器若干个子容器组成,子容器在父容器中横向排列或竖向排列且呈水平居中或垂直居中。居中布局是一个很经典的问题,相信大家都会经常遇到。

知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

在此直接上一个目前最简单最高效的居中方式。display:flexmargin:auto的强行组合,同学们自行体会。

<div class="center-layout">
    <div></div>
</div>
.center-layout {
    display: flex;
    width: 400px;
    height: 400px;
    background-color: #f66;
    div {
        margin: auto;
        width: 100px;
        height: 100px;
        background-color: #66f;
    }
}

自适布局

自适布局指相对视窗任何尺寸都能占据特定百分比的占位布局。自适布局的容器都是根据视窗尺寸计算,即使父节点祖先节点的尺寸发生变化也不会影响自适布局的容器尺寸。

搭建自适布局就离不开视窗比例单位。在CSS3里增加了与viewport相关的四个长度单位,随着时间推移,目前大部分浏览器对这四个长度单位都有较好的兼容性,这也是未来最建议在伸缩方案里使用的长度单位。

    <li> 1vw表示1%视窗宽度 <li> 1vh表示1%视窗高度 <li> 1vmin表示1%视窗宽度和1%视窗高度里最小者 <li> 1vmax表示1%视窗宽度和1%视窗高度里最大者

视窗宽高在JS里分别对应window.innerWdithwindow.innerHeight。若不考虑低版本浏览器兼容性,完全可用一行CSS代码秒杀所有移动端的伸缩方案。

/* 基于UI width=750px DPR=2的网页 */
html {
    font-size: calc(100vw / 7.5);
}

上述代码使用calc()实现font-size的动态计算。calc()自适布局里的核心存在,无它就不能愉快地实现自适布局所有动态计算了。

calc()用于动态计算单位,数值长度角度时间百分比都能作为参数。由于执行数学表达式后返回运算后的计算值,所以可减少大量人工计算甚至无需人工计算。

calc()饥不择食,所有计量单位都能作为参数参加整个动态计算。

  • 数值整数浮点数
  • 长度pxemremvwvh
  • 角度degturn
  • 时间sms
  • 百分比%

calc()虽然好用,但新手难免会遇到一些坑,谨记以下特点,相信就能玩转calc()了。

    <li>四则运算:只能使用+-*/作为运算符号 <li>运算顺序:遵循加减乘除运算顺序,可用()提升运算等级 <li>符号连接:每个运算符号必须使用空格间隔起来 <li>混合计算:可混合不同计量单位动态计算

第三点尤为重要,若未能遵守,浏览器直接忽略该属性。

上述font-size:calc(100vw / 7.5)其实就是根据设计图与浏览器视窗的比例动态计算font-size100/750 = x/100vw

在SPA里有遇过因为有滚动条或无滚动条而导致页面路由在跳转过程里发生向左或向右的抖动吗?这让强迫症患者很难受,此时可用calc()巧妙解决该问题。

.elem {
    padding-right: calc(100vw - 100%);
}

不直接声明padding-right为滚动条宽度是因为每个浏览器的默认滚动条宽度都可能不一致。100vw是视窗宽度,100%内容宽度,那么100vw - 100%就是滚动条宽度,声明padding-right用于保留滚动条出现的位置,这样滚动条出不出现都不会让页面抖动了。

有了calc()做保障就可迅速实现一些与视窗尺寸相关的布局了。例如实现一个视窗宽度都为50%的弹窗。

知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

<div class="modal">
    <div class="modal-wrapper"></div>
</div>
.modal {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    justify-content: center;
    align-items: center;
    background-color: rgba(0, 0, 0, .5);
    &-wrapper {
        width: 50vw;
        height: 200px;
        background-color: #f66;
    }
}

当然使用calc()也不一定结合视窗比例单位计算。例如自适布局已知部分节点高度,不想手动计算最后节点高度但又想其填充布局剩余空间。

知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

<ul class="selfadaption-layout">
    <div class="box-1"></div>
    <div class="box-2"></div>
    <div class="box-3"></div>
</ul>
.selfadaption-layout {
    width: 200px;
    height: 567px;
    .box-1 {
        height: 123px;
        background-color: #f66;
    }
    .box-2 {
        height: 15%;
        background-color: #3c9;
    }
    .box-3 {
        height: calc(100% - 123px - 15%);
        background-color: #09f;
    }
}

吸附布局

吸附布局指相对视窗任何滚动都能占据特定位置的占位布局。视窗滚动到特定位置,布局固定在该位置,后续不随视窗滚动而滚动。该布局产生的效果俗称吸附效果,是一种常见网页效果。譬如吸顶效果吸底效果都是该范畴,经常在跟随导航移动广告悬浮提示等应用场景里出现。

jQuery 時代には多数の吸着効果プラグインがありましたが、現在では 3 つの主要なフロントエンド フレームワークにも独自のサードパーティ製の吸着効果コンポーネントがあります。これらはすべて共通の実装原則を持っています。 scroll イベントを監視し、scrollTopターゲット ノード の位置範囲を決定し、条件が満たされる場合は target nodepositionfixed として宣言され、ウィンドウを基準にして ターゲット ノード を配置するため、ユーザーはウィンドウに釘付けされているように見えます。ウィンドウ内の指定された位置。 オンライン上には吸着効果を実現するための JS コードがたくさんあります。言うまでもなく、著者は CSS をいじるのが好きなので、関連する JS コードはここには掲載しません。ここでは、めったに見られず、めったに使用されない CSS プロパティ

position:sticky

をお勧めします。単純な 2 行のコア CSS コード 10 行以上のコア JS コード の機能を完了できるので、ぜひ実行してみてください。 簡単なレビュー

position

属性値の使用方法については説明しません。誰もがよく知っているはずです。

#値関数バージョン# #inherit標準フロー相対相対位置絶対位置決め固定位置3

当值为sticky时将节点变成粘性定位粘性定位相对定位固定定位的结合体,节点在特定阈值跨越前为相对定位,跨越后为固定定位

知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

<div class="adsorption-position">
    <ul>
        <li>Top 1</li>
        <li>Top 2</li>
        <li>Normal</li>
        <li>Bottom 1</li>
        <li>Bottom 2</li>
    </ul>
</div>
.adsorption-position {
    overflow: auto;
    position: relative;
    width: 400px;
    height: 280px;
    outline: 1px solid #3c9;
    ul {
        padding: 200px 0;
    }
    li {
        position: sticky;
        height: 40px;
        line-height: 40px;
        text-align: center;
        color: #fff;
        &:nth-child(1) {
            top: 0;
            z-index: 9;
            background-color: #f66;
        }
        &:nth-child(2) {
            top: 40px;
            z-index: 9;
            background-color: #66f;
        }
        &:nth-child(3) {
            background-color: #f90;
        }
        &:nth-child(4) {
            bottom: 0;
            z-index: 9;
            background-color: #09f;
        }
        &:nth-child(5) {
            bottom: 40px;
            z-index: 9;
            background-color: #3c9;
        }
    }
}

两行核心CSS代码分别是position:stickytop/bottom:npx。上述5个节点都声明position:sticky,但由于top/bottom赋值有所不同就产生不同吸附效果。

细心的同学可能发现这些节点在某些滚动时刻处于相对定位,在特定滚动时刻处于固定定位

    <li>第1个<li>top0px,滚动到容器顶部就固定 <li>第2个<li>top40px,滚动到距离容器顶部40px就固定 <li>第3个<li>:未声明top/bottom,就一直保持相对定位 <li>第4个<li>bottom40px,滚动到距离容器底部40px就固定 <li>第5个<li>bottom0px,滚动到容器底部就固定

当然,换成leftright也一样能实现横向的吸附效果

值得注意,粘性定位的参照物并不一定是position:fixed。当目标节点的任意祖先节点都未声明position:relative|absolute|fixed|sticky,才与position:fixed表现一致。当离目标节点最近的祖先节点声明position:relative|absolute|fixed|sticky目标节点就相对该祖先节点产生粘性定位。简单来说确认参照物的方式与position:absolute一致。

兼容性勉强还行,近2年发版的浏览器都能支持,SafariFirefox的兼容性还是挺赞的。有吸附效果需求的同学建议一试,要兼容IExplorer就算了。期待该属性有更好的发展,毕竟吸附布局真的是一种常见布局。

知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

横向布局

横向布局指容器内节点以水平方向排列且溢出部分被隐藏的占位布局。竖向布局很常见,声明overflow:hidden;width:xpx;height:ypx就能实现,但横向布局却不能使用类似方式实现。

为了方便使用多种方式实现横向布局,以下将通用代码拆分出来。

知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

<div class="horizontal-layout">
    <ul>
        <li>Alibaba</li>
        <li>Tencent</li>
        <li>Baidu</li>
        <li>Jingdong</li>
        <li>Ant</li>
        <li>Netease</li>
        <li>Meituan</li>
        <li>ByteDance</li>
        <li>360</li>
        <li>Sina</li>
    </ul>
</div>
.horizontal-layout {
    overflow: hidden;
    width: 300px;
    height: 100px;
    ul {
        overflow-x: auto;
        cursor: pointer;
        &::-webkit-scrollbar {
            height: 10px;
        }
        &::-webkit-scrollbar-track {
            background-color: #f0f0f0;
        }
        &::-webkit-scrollbar-thumb {
            border-radius: 5px;
            background-color: #f66;
        }
    }
    li {
        overflow: hidden;
        height: 90px;
        background-color: #66f;
        line-height: 90px;
        text-align: center;
        font-size: 16px;
        color: #fff;
        &:not(:first-child) {
            margin-left: 10px;
        }
    }
}

有些同学可能会使用行内元素实现横向排版,但必须声明overflow-y:hidden使容器在Y轴方向隐藏溢出部分。由于行内元素在当前行排版产生溢出会自动将其余节点排版到下一行,因此还需声明white-space:nowrap使所有行内元素在一行内排版完毕。若产生滚动条,还需对容器的height做适当的微调。

.horizontal-layout.inline {
    height: 102px;
    ul {
        overflow-y: hidden;
        white-space: nowrap;
    }
    li {
        display: inline-block;
        width: 90px;
    }
}

上述方式在笔者在开发认知里觉得太繁琐,实质上将所有节点当成文本排列,也是醉了。笔者推荐使用flex布局完成上述布局,flex布局作为目前最常见的布局方式,相信也不用笔者多说。以下实现方式不知大家是否见过呢?在移动端上体验会更棒喔!

.horizontal-layout.flex {
    ul {
        display: flex;
        flex-wrap: nowrap;
        justify-content: space-between;
    }
    li {
        flex-shrink: 0;
        flex-basis: 90px;
    }
}

凸显布局

凸显布局指容器内节点以同一方向排列且存在一个节点在某个方向上较突出的占位布局。该布局描述起来可能比较拗口,直接看以下效果吧,这是一个横向列表,节点从左往右排列,最右边的节点特别突出。这就是凸显布局的特征,凸显的节点可在凸显布局任意位置,上下左右左上左下右上右下都行。

1知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

这里巧妙运用margin-*:auto实现了凸显布局。相信大家实现水平居中固定宽度的块元素都会使用margin:0 auto

在此同样原理,当节点声明margin-*:auto时,浏览器会自动计算剩余空间并将该值赋值给该节点。在使用该技巧时必须基于flex布局

1知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

1知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

1知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

1知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

<ul class="highlight-layout">
    <li>Alibaba</li>
    <li>Tencent</li>
    <li>Baidu</li>
    <li>Jingdong</li>
    <li>Ant</li>
    <li>Netease</li>
</ul>
.highlight-layout {
    display: flex;
    align-items: center;
    padding: 0 10px;
    width: 600px;
    height: 60px;
    background-color: #3c9;
    li {
        padding: 0 10px;
        height: 40px;
        background-color: #3c9;
        line-height: 40px;
        font-size: 16px;
        color: #fff;
    }
    &.left li {
        &:not(:first-child) {
            margin-left: 10px;
        }
        &:last-child {
            margin-left: auto;
        }
    }
    &.right li {
        &:not(:last-child) {
            margin-right: 10px;
        }
        &:first-child {
            margin-right: auto;
        }
    }
    &.top {
        flex-direction: column;
        width: 120px;
        height: 400px;
        li {
            &:not(:first-child) {
                margin-top: 10px;
            }
            &:last-child {
                margin-top: auto;
            }
        }
    }
    &.bottom {
        flex-direction: column;
        width: 120px;
        height: 400px;
        li {
            &:not(:last-child) {
                margin-bottom: 10px;
            }
            &:first-child {
                margin-bottom: auto;
            }
        }
    }
}

在此还有一个小技巧,那就是:not():first-child:last-child的巧妙运用。这样组合让特殊位置的节点直接减少属性覆盖的问题,不仅易读还能装逼。

  • :not(:first-child):排除首节点,其他节点都使用某些样式
  • :not(:last-child):排除尾节点,其他节点都使用某些样式

间距布局

间距布局指容器内节点从左往右从上往下排列且以特定间距间隔的占位布局。间距布局常见于各大列表,是笔者认为最重要的布局之一。为何如此简单的布局还是花费一些篇幅讲解呢?最近笔者查看了Github上很多与间隔布局相关的CSS代码,虽然整体效果看上去无大碍,但margin/padding结构选择器却乱用,因此笔者想从零到一纠正间距布局的正确编码方式。

在进入编码环节前,笔者想重点讲解:nth-child()的点睛之笔。大部分同学可能只认得:nth-child(n):nth-child(2n-1):nth-child(2n):nth-child(xn)的日常用法,但其实还有一些你可能未见过的用法。在此笔者借这次机会将:nth-child()所有用法总结下,n/x/y代表正整数,最小值为1

  • :nth-child(n):选择第n个元素
  • :nth-child(odd):选择奇数位置元素,相当于:nth-child(2n-1)
  • :nth-child(even):选择偶数位置元素,相当于:nth-child(2n)
  • :nth-child(xn):选择第x*n个元素
  • :nth-child(x-n):选择前x个元素
  • :nth-child(y-n):nth-child(n+x):选择第x~y个元素

分析间距布局的一切特点,捕获特征很有利于将特征转换成CSS代码。

    <li> A:确定容器间的间距,使用margin声明 <li> B:确定容器内的间距,使用padding声明,后续方便声明background-color(该步骤很易与上一步骤混淆,请特别注意) <li> C:确定靠近容器边界的节点与容器的间距,使用padding声明容器而不是使用margin声明节点(该步骤说明上一步骤的处理结果) <li> D:确认每行节点的左右间距,使用margin-left/margin-right(二选一)声明节点 <li> E:确认最左列节点或最右列节点与容器的间距,使用margin-left:0声明最左列节点或使用margin-right:0声明最右列节点 <li> F:除了首行节点,使用margin-top声明其余节点 <li> G:若希望容器顶部底部留空,使用border-top/border-bottom代替padding-top/padding-bottom

全部步骤串联起来理解可能会产生混乱,但结合以下代码理解相信就能很快熟悉。以一行排列3个节点总共8个节点为例,最终效果为三行三列。

1知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

<ul class="spacing-layout">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
</ul>
.spacing-layout {
    display: flex;
    overflow: auto;
    flex-wrap: wrap;
    margin-top: 20px; // 对应A
    padding: 20px; // 对应B和C
    // padding-top: 0; // 对应G
    // padding-bottom: 0; // 对应G
    // border-top: 20px solid #f66; // 对应G
    // border-bottom: 20px solid #f66; // 对应G
    width: 700px; // 稍微留空用于显示滚动条
    height: 400px;
    background-color: #f66;
    li {
        width: 200px;
        height: 200px;
        background-color: #66f;
        line-height: 200px;
        text-align: center;
        font-size: 20px;
        color: #fff;
        &:not(:nth-child(3n)) {
            margin-right: 20px; // 对应D和E
        }
        &:nth-child(n+4) {
            margin-top: 20px; // 对应F
        }
    }
}

空载布局

空载布局指容器内无任何节点时使用其他形式代替的占位布局。还有使用JS判断列表集合为空时显示占位符吗?相信很多使用MVVM框架开发的同学都会使用条件判断的方式渲染虚拟DOM,若列表长度不为0则渲染列表,否则渲染占位符。

<div>
    <ul v-if="list.length">...</ul>
    <div v-esle>Empty</div>
</div>

然而CSS提供一个空判断的选择器:empty,这应该很少同学会注意到吧。

:empty作用于无子节点的节点,该子节点也包括行内匿名盒(单独的文本内容)。以下三种情况均视为非空状态,若不出现这三种状态则视为空状态,此时:empty才会触发。

  • 仅存在节点:<div><p>CSS</p></div>
  • 仅存在文本:<div>CSS</div>
  • 同时存在节点和文本:<div>Hello <p>CSS</p> </div>

知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

<ul class="empty-layout">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
</ul>
<ul class="empty-layout"></ul>
$empty: "https://yangzw.vip/img/empty.svg";
.empty-layout {
    overflow: auto;
    width: 200px;
    height: 150px;
    outline: 1px solid #3c9;
    &:empty {
        display: flex;
        justify-content: center;
        align-items: center;
        background: url($empty) no-repeat center/100px auto;
        &::after {
            margin-top: 90px;
            font-weight: bold;
            content: "没钱就没数据";
        }
    }
    li {
        padding: 0 10px;
        height: 30px;
        background-color: #09f;
        line-height: 30px;
        color: #fff;
        &:nth-child(even) {
            background-color: #f90;
        }
    }
}

另外还存在一种特殊的空载布局,就是不做任何处理。这样最终渲染的DOM只有容器,若已声明margin/padding/border但未声明width/height的情况下,就会出现以下占位效果。无任何子节点的容器还声明着margin/padding/border,看着都尴尬。

知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

没事,:empty帮你搞掂!对于无任何子节点的容器直接声明display:none解决所有无效占位,当然也可作用于指定节点。一招制敌,劲!

// 作用于所有节点
:empty {
    display: none;
}
// 作用于指定节点
.empty-layout:empty {
    display: none;
}

多格布局

多格布局指容器内节点以动态数量的格子形式排列的占位布局。微信朋友圈的相册就是最常见的多格布局了,当单张照片排列、两张照片排列、三张照片排列等等,每种情况下照片的尺寸都可能不一致。笔者制作了一个动态多格相册怀念我家狗狗AB。大家感受下纯CSS实现动态数量的多格布局吧。

在此留个悬念,不讲解如何实现,看看大家能不能根据笔者列出的提示尝试将该效果复原。主要原理是根据结构选择器限制节点范围实现,在本文也可找到原理的答案喔!记得实现完再看以下源码哈!

2知っておく価値のある 8 つの純粋な CSS レイアウト テクニック

<ul class="multigrid-layout">
    <li class="item"><img  src="https://static.yangzw.vip/codepen/ab-3.jpg" alt="知っておく価値のある 8 つの純粋な CSS レイアウト テクニック" ></li>
    <li class="item"><img  src="https://static.yangzw.vip/codepen/ab-3.jpg" alt="知っておく価値のある 8 つの純粋な CSS レイアウト テクニック" ></li>
    <li class="item"><img  src="https://static.yangzw.vip/codepen/ab-3.jpg" alt="知っておく価値のある 8 つの純粋な CSS レイアウト テクニック" ></li>
    <li class="item"><img  src="https://static.yangzw.vip/codepen/ab-3.jpg" alt="知っておく価値のある 8 つの純粋な CSS レイアウト テクニック" ></li>
    <li class="item"><img  src="https://static.yangzw.vip/codepen/ab-3.jpg" alt="知っておく価値のある 8 つの純粋な CSS レイアウト テクニック" ></li>
    <li class="item"><img  src="https://static.yangzw.vip/codepen/ab-3.jpg" alt="知っておく価値のある 8 つの純粋な CSS レイアウト テクニック" ></li>
    <li class="item"><img  src="https://static.yangzw.vip/codepen/ab-3.jpg" alt="知っておく価値のある 8 つの純粋な CSS レイアウト テクニック" ></li>
    <li class="item"><img  src="https://static.yangzw.vip/codepen/ab-3.jpg" alt="知っておく価値のある 8 つの純粋な CSS レイアウト テクニック" ></li>
    <li class="item"><img  src="https://static.yangzw.vip/codepen/ab-3.jpg" alt="知っておく価値のある 8 つの純粋な CSS レイアウト テクニック" ></li>
</ul>
@mixin square($count: 2) {
    $length: calc((100% - #{$count} * 10px) / #{$count});
    width: $length;
    height: $length;
}
.multigrid-layout {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-start;
    align-content: flex-start;
    padding: 5px;
    border: 1px solid #ccc;
    border-radius: 5px;
    width: 400px;
    height: 400px;
    li {
        display: flex;
        overflow: hidden;
        justify-content: center;
        margin: 5px;
        background-color: #f0f0f0;
        @include square(3);
    }
    img {
        width: 100%;
        height: 100%;
        object-fit: cover;
    }
}
// 一个元素
.item:only-child {
    border-radius: 10px;
    width: auto;
    max-width: 80%;
    height: auto;
    max-height: 80%;
}
// 两个元素
.item:first-child:nth-last-child(2),
.item:first-child:nth-last-child(2) ~ .item:nth-child(2) {
    @include square(2);
}
.item:first-child:nth-last-child(2) {
    border-radius: 10px 0 0 10px;
}
.item:first-child:nth-last-child(2) ~ .item:nth-child(2) {
    border-radius: 0 10px 10px 0;
}
// 三个元素
.item:first-child:nth-last-child(3),
.item:first-child:nth-last-child(3) ~ .item:nth-child(2),
.item:first-child:nth-last-child(3) ~ .item:nth-child(3) {
    @include square(2);
}
.item:first-child:nth-last-child(3) {
    border-top-left-radius: 10px;
}
.item:first-child:nth-last-child(3) ~ .item:nth-child(2) {
    border-top-right-radius: 10px;
}
.item:first-child:nth-last-child(3) ~ .item:nth-child(3) {
    border-bottom-left-radius: 10px;
}
// 四个元素
.item:first-child:nth-last-child(4),
.item:first-child:nth-last-child(4) ~ .item:nth-child(2),
.item:first-child:nth-last-child(4) ~ .item:nth-child(3),
.item:first-child:nth-last-child(4) ~ .item:nth-child(4) {
    @include square(2);
}
.item:first-child:nth-last-child(4) {
    border-top-left-radius: 10px;
}
.item:first-child:nth-last-child(4) ~ .item:nth-child(2) {
    border-top-right-radius: 10px;
}
.item:first-child:nth-last-child(4) ~ .item:nth-child(3) {
    border-bottom-left-radius: 10px;
}
.item:first-child:nth-last-child(4) ~ .item:nth-child(4) {
    border-bottom-right-radius: 10px;
}
// 五个元素
.item:first-child:nth-last-child(5) {
    border-top-left-radius: 10px;
}
.item:first-child:nth-last-child(5) ~ .item:nth-child(3) {
    border-top-right-radius: 10px;
}
.item:first-child:nth-last-child(5) ~ .item:nth-child(4) {
    border-bottom-left-radius: 10px;
}
// 六个元素
.item:first-child:nth-last-child(6) {
    border-top-left-radius: 10px;
}
.item:first-child:nth-last-child(6) ~ .item:nth-child(3) {
    border-top-right-radius: 10px;
}
.item:first-child:nth-last-child(6) ~ .item:nth-child(4) {
    border-bottom-left-radius: 10px;
}
.item:first-child:nth-last-child(6) ~ .item:nth-child(6) {
    border-bottom-right-radius: 10px;
}
// 七个元素
.item:first-child:nth-last-child(7) {
    border-top-left-radius: 10px;
}
.item:first-child:nth-last-child(7) ~ .item:nth-child(3) {
    border-top-right-radius: 10px;
}
.item:first-child:nth-last-child(7) ~ .item:nth-child(7) {
    border-bottom-left-radius: 10px;
}
// 八个元素
.item:first-child:nth-last-child(8) {
    border-top-left-radius: 10px;
}
.item:first-child:nth-last-child(8) ~ .item:nth-child(3) {
    border-top-right-radius: 10px;
}
.item:first-child:nth-last-child(8) ~ .item:nth-child(7) {
    border-bottom-left-radius: 10px;
}
// 九个元素
.item:first-child:nth-last-child(9) {
    border-top-left-radius: 10px;
}
.item:first-child:nth-last-child(9) ~ .item:nth-child(3) {
    border-top-right-radius: 10px;
}
.item:first-child:nth-last-child(9) ~ .item:nth-child(7) {
    border-bottom-left-radius: 10px;
}
.item:first-child:nth-last-child(9) ~ .item:nth-child(9) {
    border-bottom-right-radius: 10px;
}

总结

很多同学可能觉得CSS很简单,但真正玩起来也能与JS有得一比。笔者从事前端领域多年,一直致力于CSS技术的研究与应用,当然真的不是为了玩,而是在玩的过程里将实践到的知识充分应用于工作上。

JS重要但CSS同样重要,希望喜欢CSS的同学多多关注笔者,相信你一定会有更多CSS方面的收获。

原文地址:https://juejin.cn/post/6986873449721364510

作者:JowayYoung

更多编程相关知识,请访问:编程入门!!

継承 2 ##静的
2
#2 絶対
2 #修正済み
2 sticky ##スティッキーポジショニング

以上が知っておく価値のある 8 つの純粋な CSS レイアウト テクニックの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。