【不同的CSS】深刻理解 position (掌握定位就是這麼 sao 氣)

【不同的CSS】深刻理解 position (掌握定位就是這麼 sao 氣)

寫在前面

對 CSS 佈局掌握程度決定你在 Web 開發中的開發頁面速度。隨着 Web 技術的不斷革新,實現各類佈局的方式已經多得數不勝數了。css

最近利用碎片時間,大概用了半個月的時間整理了一個系列,本系列文章總結了 CSS 中的各類佈局,以及實現方式及其經常使用技巧。讓你經過該系列文章對 CSS 佈局有一個新的認識。html

該系列的導航帖點我進入,裏面能夠快速跳轉到你想了解的文章(建議收藏)web

position 屬性概述

position 屬性是掌握 CSS 佈局中重要得一個屬性,該屬性用於指定一個元素在文檔中的定位方式。經過 top,right,bottomleft 屬性則決定了該元素的最終位置。瀏覽器

該屬性具備如下五個值:markdown

  • static: 默認值,表示正常佈局行爲,此時設置 top, right, bottom, leftz-index 屬性均無效。
  • relative將元素設置爲相對定位元素,該方式不脫離文檔流
  • absolute將元素設置爲絕對定位元素,使元素相對於最近的非 static 定位祖先元素的進行定位。
  • fixed: 將元素設置爲固定定位元素,使元素相對於視覺窗口進行定位。
  • sticky: 將元素設置爲粘性定位元素,一開始不脫離文檔流在默認位置,當到達某個位置時,相對於視口進行定位。

absolute 屬性值

基本特性

absolute 屬性值與 float 屬性名,具備相同的特性:佈局

  1. 包裹性:所謂的包裹性就是指元素的寬度會收縮到與內容一致。
  2. 破壞性:所謂的破壞性指的就是父元素的高度塌陷

脫離文檔流

position 屬性的值設置爲 absolute 時,其元素會脫離文檔流。post

文檔流就是將窗體自上而下分紅一行一行,並在每行中按從左至右依次排放元素,稱爲文檔流,也稱爲普通流。flex

所謂的脫離文檔流就是元素再也不在文檔流中佔據空間,而是處於浮動狀態 (能夠理解爲漂浮在文檔流的上方) 。脫離文檔流的元素的定位基於正常的文檔流,當一個元素脫離文檔流後,依然在文檔流中的其餘元素將忽略該元素並填補其原先的空間。優化

示例代碼以下:ui

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>脫離文檔流</title>
        <style> .item { width: 300px; height: 200px; background-color: #ec407a; /* 脫離文檔流 不佔文檔中的空間 */ position: absolute; } img { width: 500px; } </style>
    </head>
    <body>
        <div class="item"></div>
        <img src="./../image/img.jpg" />
    </body>
</html>
複製代碼

不脫離文檔流的表現以下圖所示:

image-20210514205208841

脫離文檔流的表現以下圖所示:

image-20210514205238054

能夠看出 <div> 元素已經漂浮在圖片的上方了。

margin 共同使用

absolute 屬性值與 margin 共同使用時能夠完成一些效果很不錯的佈局。例如一個搜索框效果,示例代碼以下所示:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>下拉框定位二三事</title>
        <style> body { margin: 0; background-color: #edeff0; } /* 容器樣式 */ .container { margin-top: 120px; margin-left: 240px; overflow: hidden; } /* 輸入框樣式 */ .input { width: 240px; line-height: 18px; padding: 10px; margin: 0; border: 0 none; } .input:focus { outline: 0 none; } .list { /* 默認不顯示,當輸入內容時,經過js控制其顯示 */ /* display: none; */ position: absolute; width: 260px; /* 經過 margin 來控制其顯示的位置 */ margin: 39px 0 0 -1px; padding-left: 0; list-style-type: none; border: 1px solid #e6e8e9; background-color: #fff; box-shadow: 0px 1px 2px #d5d7d8; font-size: 12px; } /* 列表項樣式以及懸停樣式 */ .list > li { line-height: 30px; padding-left: 12px; } .list > li:hover { background-color: #f9f9f9; } .list a { display: block; color: #5e5e5e; text-decoration: none; } .list a:hover { color: #000; } </style>
    </head>

    <body>
        <div class="container">
            <ul class="list">
                <li>
                    <a>玩轉CSS佈局之 Grid 佈局</a>
                </li>
                <li>
                    <a>玩轉CSS佈局之 Flex 佈局</a>
                </li>
                <li>
                    <a>玩轉CSS佈局之深刻理解 position 定位</a>
                </li>
                <li>
                    <a>玩轉CSS佈局之深刻理解 z-index 定位</a>
                </li>
            </ul>
            <input class="input" placeholder="請輸入內容" />
        </div>
    </body>
</html>

複製代碼

執行結果以下圖所示:

image-20210514221831036

此時能夠經過 JavaScript 的方式來控制提示內容的顯示與隱藏。

left、right、top、bottom 的使用

開啓定位以後,能夠經過這四個屬性來控制其偏移量,其參數能夠傳遞像素值,百分比(表明元素包含塊的寬度的百分比)等。

簡單的使用這裏就不介紹了,這裏介紹一些在開發中的小技巧

  1. 沒有寬度和高度聲明實現的全屏自適應效果

    示例代碼以下所示:

    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="UTF-8" />
            <meta http-equiv="X-UA-Compatible" content="IE=edge" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
            <title>沒有寬度和高度聲明實現的全屏自適應效果</title>
            <style> .overlay { position: absolute; /* 將其元素拉滿整個頁面 */ left: 0; top: 0; right: 0; bottom: 0; background-color: #000; opacity: 0.5; } </style>
        </head>
    
        <body>
            <div class="overlay"></div>
        </body>
    </html>
    複製代碼
  2. left rightwidth 實現水平居中,示例代碼以下所示:

    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="UTF-8" />
            <meta http-equiv="X-UA-Compatible" content="IE=edge" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
            <title>left right 和 width 實現水平居中</title>
            <style> img { position: absolute; right: 0; left: 0; width: 800px; /* 開啓決定定位後 margin: auto 是沒法實現水平居中的,須要經過 left right 和 width 配合使用 */ margin: auto; } </style>
        </head>
        <body>
            <img src="../image/img.jpg" />
        </body>
    </html>
    複製代碼

    實現效果以下所示:

    image-20210514223204545

值得注意的是absolute 屬性值是不能與 float 共同使用的,當共同使用時,float 將會失效。

z-index 的關係

絕對定位的元素能夠經過 z-index 控制層級顯示,可是在開發過程當中,須要咱們的代碼結構清晰,這個並非必要的。使用準則以下:

  1. 若是隻有一個決定定位的元素,天然就不須要 z-index 來控制層級顯示,該元素會自動覆蓋普通元素。
  2. 若是有兩個絕對定位的元素,控制 DOM 流的先後順序也能達到須要的覆蓋效果,天然也不須要 z-index 屬性。
  3. 若是有多個絕對定位交錯,這種事很是少見的,經過 DOM 流的順序,和 z-index: 1 就能夠實現
  4. 若是是非彈框類的決定定位元素 z-index 的值是大於2的,一定 z-index 是冗餘的,代碼徹底能夠優化。

relative 屬性值

absolute 的限制做用

relative 屬性值對 對 absolute 的具備以下限制做用

  1. 當父元素開啓 relative 定位後,其子元素若是開啓 absolute 定位後 子元素的 left、right、topbottom 的屬性值永遠不會超出父元素。

    示例代碼以下所示:

    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="UTF-8" />
            <meta http-equiv="X-UA-Compatible" content="IE=edge" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
            <title>relative 屬性值對 對 `absolute` 的具備以下限制做用</title>
            <style> .container { /* 父級元素開啓 relative 定位 */ position: relative; height: 400px; width: 600px; margin: 0 auto; background-color: #9c27b0; } .item { /* 子元素開啓 absolute 定位 */ position: absolute; background-color: #4caf50; height: 200px; width: 300px; /* 子元素的 top left right bottom 會被限制在 父級容器中 */ right: 0; bottom: 0; } </style>
        </head>
        <body>
            <div class="container">
                <div class="item"></div>
            </div>
        </body>
    </html>
    複製代碼

    執行結果以下所示:

    image-20210515085225610

  2. 當有兩個元素都開啓 relative 定位,並都經過 z-index 限制層級,假如父元素1號的 z-index 的值爲2,父元素2號的 z-index 的值爲1。父元素2號下面的子元素不管 z-index 的值多大,永遠不會覆蓋父元素1下面的子元素。

  3. 若是父元素未開啓 relative 定位,其 overflow: hidden; 的限制對 absolute 定位的子元素並無任何限制,只有父元素開啓 relative 定位後,纔會對 absolute 定位的子元素作限制。

    示例代碼以下:

    .container {
        /* 父級元素開啓 relative 定位 */
        position: relative;
        height: 400px;
        width: 600px;
        margin: 0 auto;
        background-color: #9c27b0;
        overflow: hidden;
    }
    .item {
        /* 子元素開啓 absolute 定位 */
        position: absolute;
        background-color: #4caf50;
        height: 200px;
        width: 300px;
        right: 0;
        top: 0;
    }
    複製代碼

    HTML 結構同上

    當父元素未開啓 relative 定位的效果以下:

    image-20210515090413687

    開啓後以下所示:

    image-20210515090427261

left、right、top、bottom 的使用

當元素開啓 relative 定位後,其偏移是相對於自身,且對其餘元素沒有侵入性的。簡單的說就是相對本身原來的位置進行偏移,且對其餘元素與沒有任何的影響。

示例代碼以下:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>left等偏移屬性的使用</title>
        <style> .container { /* 父級元素開啓 relative 定位 */ position: relative; height: 400px; width: 600px; background-color: #9c27b0; left: 100px; top: 100px; } </style>
    </head>
    <body>
        <div class="container"></div>
    </body>
</html>
複製代碼

執行結果以下:

image-20210515091248757

realtive 最小化影響原則

所謂 relative 的最小化影響原則,指的是儘可能 relative 屬性值對其餘元素或佈局的潛在影響!具體體如今兩個方面:

  1. 使用 absolute 屬性值時,儘可能不使用 relative 作限制,而是使用 margin 完成其定位功能。

  2. 當必須經過 父元素開啓 relative 定位,子元素的 absolute 才能實現定位效果的時候,能夠再其子元素單首創建一個的父元素,並開啓 relative 定位,子元素就能夠相對於該父元素進行定位,這麼作的好處就是 relative 佈局就不會影響其餘元素。

    示例代碼以下:

    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="UTF-8" />
            <meta http-equiv="X-UA-Compatible" content="IE=edge" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
            <title>relative 最小化影響原則</title>
            <style> .container { height: 400px; width: 600px; background-color: #9c27b0; margin: 0 auto; } .item { height: 100px; width: 50px; background-color: #ff7043; line-height: 100px; font-size: 30px; text-align: center; } </style>
        </head>
        <body>
            <div class="container">
                <!-- 單首創建一個 開啓 relative 定位的 父元素-->
                <div style="position: relative">
                    <!-- 這樣不會影響後面元素的定位 -->
                    <div class="item" style="position: absolute; right: 0">1</div>
                </div>
                <div class="item">2</div>
            </div>
        </body>
    </html>
    複製代碼

    執行結果如圖所示:

    image-20210515093138396

fixed 屬性值

position 的屬性值設置爲 fixed 時,該元素會相對於瀏覽器窗口進行偏移,即定位的基準點就是瀏覽器窗口。這就會致使該元素的位置不會跟隨頁面滾動而變化,就像固定在頁面上同樣。

該屬性還能夠搭配 topbottomleftright 這四個屬性一塊兒使用,表示該元素的初始位置是基於視口計算的。若是不使用這四個屬性,表示元素的起始位置就是元素的默認位置。

示例代碼以下所示:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>fixed 屬性值</title>
        <style> body { margin: 0; height: 2000px; } .container { /* 開啓 fixed 定位 */ position: fixed; height: 400px; background: #2c80c5; /* 實現居中 */ left: 0; right: 0; width: 500px; margin: auto; } </style>
    </head>
    <body>
        <div class="container"></div>
    </body>
</html>
複製代碼

當頁面不管怎麼滾動,該元素始終定位在頂部。

執行結果以下:

image-20210515211240930

sticky 屬性值

sticky 屬性值與其餘屬性值不同,該屬性值會產生一個動態效果,靈活的運用該屬性值能夠完成一個吸頂的效果。

這個值像是 relativefixed的結合。一些時候是 relative 定位 (定位的基準點是自身默認位置) ,另外一些時候自動變成 fixed 定位 (定位的基準點是視口) 。

該屬性值必須搭配 topbottomleftright 這四個屬性一塊兒使用,不能省略,不然等同於 relative 定位,不產生 動態固定 的效果。

該屬性值得定位規則爲:當頁面滾動,父元素開始脫離視口時即部分不可見) ,只要與 sticky 元素的距離達到生效門檻,relative 定位自動切換爲 fixed 定位;等到父元素徹底脫離視口時 (即徹底不可見) ,fixed 定位自動切換回 relative 定位。

示例代碼以下:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>sticky 屬性值</title>
        <style> .container { background: #eee; width: 600px; height: 1000px; margin: 0 auto; } .title { /* 適配 safari 瀏覽器 */ position: -webkit-sticky; position: sticky; height: 60px; background: #ff7300; top: 0px; font-size: 30px; text-align: center; color: #fff; line-height: 60px; } img { width: 100%; display: block; } </style>
    </head>
    <body>
        <div class="container">
            <div>
                <div class="title">內容1</div>
                <img src="../image/img.jpg" />
            </div>
            <div>
                <div class="title">內容2</div>
                <img src="../image/img.jpg" />
            </div>
            <div>
                <div class="title">內容3</div>
                <img src="../image/img.jpg" />
            </div>
            <div>
                <div class="title">內容4</div>
                <img src="../image/img.jpg" />
                <img src="../image/img.jpg" />
            </div>
        </div>
    </body>
</html>
複製代碼

執行結果以下圖所示:

當咱們的頁面滾動時,只要視口的頂部與 .title 的距離 >=0,.title 就會自動變爲 fixed 定位,保持與視口頂部 0px 的距離。頁面繼續向下滾動,父元素完全離開視口(即整個父元素徹底不可見),.title 恢復成 relative 定位。

生效規則

position:sticky 的生效是有必定的限制的,總結以下:

  1. 須指定 top, right, bottomleft 四個閾值其中之一,纔可以使粘性定位生效。不然其行爲與相對定位相同。
    • 而且 topbottom 同時設置時,top 生效的優先級高,leftright 同時設置時,left 的優先級高。
  2. 設定爲 position:sticky 元素的任意父節點的 overflow 屬性必須是 visible,不然 position:sticky 不會生效。這裏須要解釋一下:
    • 若是 position:sticky 元素的任意父節點定位設置爲 overflow:hidden,則父容器沒法進行滾動,因此 position:sticky 元素也不會有滾動而後固定的狀況。
    • 若是 position:sticky 元素的任意父節點定位設置爲 position:relative | absolute | fixed,則元素相對父元素進行定位,而不會相對視覺窗口定位。
  3. 達到設定的閥值。這個還算好理解,也就是設定了 position:sticky 的元素表現爲 relative 仍是 fixed 是根據元素是否達到設定了的閾值決定的。
相關文章
相關標籤/搜索