# CSS 定位 position ###### tags: `HTML, CSS` ## 預設值 static * 基本上你不設置 html 元素position的話,預設就是 static * 而她處理的效果會讓所以 html tag 照順序排列並且緊貼著其他元素(以下面的例子舉例就是One Two Three 等等) HTML ```html= <body> <div class="parent"> Parent <div class="child-one child">One</div> <div class="child-two child">Two</div> <div class="child-three child">Three</div> </div> </body> ``` CSS ```css= .parent { padding: 5px; background-color: #00AAFF; } .child { padding: 5px; } .child-one { background-color: rgb(116, 255, 116); } .child-two { background-color: rgb(248, 117, 117); } .child-three { background-color: rgb(255, 116, 232); } ``` 要尋找屬性的話可以使用 computed 內建的 filter功能 ![](https://i.imgur.com/7ZSD6rg.png) 這邊使用 position: static 出來的 html 會如下圖呈現: 1. 所有元素緊鄰其他元素 2. 照 html 順序排列 3. 基本上就是你的 html 怎麼打他就怎麼樣呈現在瀏覽器上 ![](https://i.imgur.com/fpCVcFW.png) ## position: relative * relative 基本上操作起來跟 static 一樣特性也差不多,不同之處在於多了四個屬性可以操作元素,方別是 top, right, bottom, left 藉由這四個屬性來操作元素的位置 * 使用 relative 定位方式會相對原本的 static 位置做偏移,而偏移的位置則靠四個屬性來控制 這邊單純使用 relative 沒有加上屬性的話他不會有任何改變 ```css= .child-one { position: relative; } ``` 加上屬性之後 ```css= .child-one { position: relative; left: 10px; } ``` 偏移的效果就會產生 ![](https://i.imgur.com/lSKGYIg.png) ### relative 會浮出 document flow > 這邊的標題會浮出 document flow 的意思是,這邊被設定 relative 的元素它不會干涉到其他的元素的意思 所以我下面操作的方式會往下移動10px 但是下面的 two, three 卻沒有被往下推而是被蓋住,代表的就是 one 這元素浮起來而不會干涉到其他元素了 ```css= .child-one { position: relative; top: 10px; } ``` ![](https://i.imgur.com/AiIGYCD.png) ### 注意,一般不會使用這四個屬性在 relative 上 > 一般我們不會設置 relative 四個屬性讓他浮出去,因為這樣的情況會讓裝飾其他的區塊非常麻煩 但是如果我還是想要 two, three 也一起向下移動呢? 則必須大家一起浮起來才能辦的到 ```css= .child-one { position: relative; top: 10px; } .child-two { position: relative; top: 10px; } .child-three { position: relative; top: 10px; } ``` (這邊不設置 parent 比較好看出來) ![](https://i.imgur.com/Zk7FhTQ.png) ## position: absolute > absolute 會對使用的元素,像是從 document flow 中刪除,但可以因其特性可以做到把元素固定在某個位置上面,並且其他的元素都不會干擾到它 ```css= .child-one { position: absolute; } .child-two {} .child-three {} ``` 從下圖可以看出,one 元素整個浮在其他元素之上,就像是它不存在一樣 ![](https://i.imgur.com/3ZsBh08.png) ### position: absolute 一樣有top, right, bottom, left 四屬性 ```css= .parent{ } .child-one { position: absolute; top: 10px; } ``` ![](https://i.imgur.com/QC1zIeq.png) 奇怪的事情發生了,one 元素變成是基於整個瀏覽器的 top 10px 來做定位而不是 parent 了,從這邊就要談到 absolute 是如何做出元素定位,**它會定位於其父母層上面**,但是這邊的 child-one 的父母層卻不是 parent 因為,這時候的 parent 並沒有做任何定位還是預設值也就是 static,所以如果要使用 absolute 就必須給其父母層做好定位不管是 relatevie, absolute, sticky, fixed 都可以,這樣就可以使用 absolute 做好定位搂! (所以這邊因為都沒有定位出現所以,定位到最外層也就是整個 html 瀏覽器的部分) ```css= .parent { position: relative; } .child-one { position: absolute; top: 10px; } ``` 從下圖可以觀察出,因為 .parent 做好定位了,因此 child-one 的定位就已父母層的方式做絕對定位瞜! ![](https://i.imgur.com/ZU6dUxN.png) ### 結論 使用 absolute 定位,一定得針對其父母層做好定位,然後元素本身就可以被定位在父母層之中做四方向操作定位,如果父母層沒有做好定位則會一直往外找可能是上面一層或是一直找到 html 瀏覽器本身去定位為止(除了 static 以外的定位都可以),就跟範例一樣。 ## position: fixed > fixed 就很直觀它綁定的父母層定位一定是 html 瀏覽器本身,並且當使用 scroll 時,元素本身也不會跟著移動 ```css= .parent { position: relative; } .child-one { position: fixed; top: 10px; } ``` 從下圖可以看出,fixed定位直接忽略 .parent 的 relative 定位,而是直接定位在瀏覽器上 ![](https://i.imgur.com/KkR5w23.png) 並且使用 scroll 時,元素本身也不會跟著移動 ![](https://i.imgur.com/S144zIF.gif) ## position:sticky 假設我們要實作一個 navbar 會固定在頂部就算使用 scroll 往下,一般我們會操作使用 fiexed 做處理,並且對 content 加上 margin-top 給他一點距離 ```css= <style> .main-nav { position: fixed; top: 0; } .content { margin-top: 30px; } </style> ``` ```html= <div class="main-nav"> <div>HOME</div> <div>ABOUT</div> <div>CONTACT</div> </div> <p class="content"> Lorem ipsum dolor, sit amet consectetur adipisicing elit. Modi doloremque ducimus eaque mollitia dolore nesciunt deleniti! Incidunt et, cupiditate ducimus aliquam fugiat magnam. Eligendi impedit vitae incidunt placeat ullam tempora? Asperiores nam amet accusantium distinctio cum possimus excepturi sed consequuntur tempora dignissimos cumque soluta porro vero recusandae nesciunt, nulla exercitationem obcaecati unde similique velit corrupti fugit earum architecto eligendi. Recusandae reiciendis exercitationem tempora impedit ipsum laudantium. Molestiae sed exercitationem facilis sunt autem maxime quidem doloribus numquam? Repellat praesentium nesciunt porro, qui ducimus maxime harum suscipit accusamus ex velit, facere assumenda officiis. Cupiditate odio reiciendis ipsum eligendi accusantium pariatur! Illo, quis error, voluptatibus dolorum nesciunt laborum rerum fuga dolores voluptate nulla minus cupiditate incidunt expedita aspernatur fugiat quo. Fugit eius perspiciatis sequi. Error tempora accusantium amet. Iste amet beatae, doloremque dolor ratione ut placeat illo illum distinctio quibusdam unde? Temporibus repellendus nam aspernatur eum asperiores quibusdam sit, enim ex nesciunt placeat labore ducimus autem! Soluta fugit alias et temporibus nulla aperiam tempore, repellendus ullam animi ea id esse delectus ab quae officia harum voluptatum quaerat corrupti impedit distinctio, est facilis laborum atque! Recusandae ratione provident dolor, voluptatem cumque repudiandae, consequuntur aut dolore magni commodi vitae totam. Nam, in atque. Reprehenderit sapiente cum exercitationem molestias temporibus quia cupiditate nisi a. Maxime, eius deserunt. Harum nisi quaerat quae, magnam natus, sequi ratione voluptatibus esse alias numquam tenetur eum recusandae praesentium temporibus error, explicabo facilis deleniti impedit unde dolore nesciunt modi ab perspiciatis. Deserunt reiciendis optio cum ab beatae distinctio odit corporis rem delectus, est quos facere laborum! Repudiandae earum voluptatibus nihil rem illo cum neque iste officia eius, perspiciatis hic. Fuga excepturi molestiae harum ipsam veniam eum ipsum cum eius sed a modi illum beatae maxime commodi voluptate, quae dolor quod quasi cupiditate iure labore repellat voluptatum dolore. Sed odio eius officiis iure. </p> ``` 可以達到這樣的效果 ![](https://i.imgur.com/0Bgssjl.gif) ### 範例一 但是當我們想做到做 navbar 上面還有一張大張的圖片的時候該怎麼處理呢?就是 sticky 來救場了 (想要做到這樣的效果可以使用 sticky 定位) ![](https://i.imgur.com/V2mPIkp.png) ```css= <style> .main-nav { position: sticky; top: 0; } </style> ``` ![](https://i.imgur.com/uUEWANh.gif) 可以做到這樣的事情是因為,sticky 有著 fixed, relative 兩種屬性的結合,並且可以透過四屬性定位來觸發,以上面的範例說明: * 當 .main-nav 只撰寫 sitcky 沒有加上定位時則只有 relative 屬性 * 當 .main-nav 的位置(也就是 navbar )跟 top 距離為 0時(不為0時也是 relative ),才會觸發變成 fixed 屬性,也就是可以達到影片的效果 * 並且因為它有個 relative 的屬性,所以他不需要對 .content 做 margin-top ### 範例二 [codepen 在此](https://codepen.io/WebDevSimplified/pen/pxLOVp) 我們在 list 也可以使用到 sticky 屬性 ![](https://i.imgur.com/46sv3EZ.gif) 這邊的使用方式就是針對每個 title (A, B, C, D) 做 sticky ,所以當下一個 list-header 碰到彼此時也就是 top 為 0 的狀態就會觸發下一個的 fixed ,就可以做出這樣的效果來 ```css= .list-header { position: sticky; top: 0; } ``` ### 相容性問題 因為 sticky 只支援百分之九十的瀏覽器,所以可以像下面這寫撰寫,預設狀態是 relative 當遇到不支援的瀏覽器時,不然一般狀態就是使用 supports 內部的 sticky 屬性 ```css= <style> .list-header { position: relative; } @supports (position: sticky) { .list-header { position: sticky; top: 0; } } </style> ``` ## 重點分析 ### static * 預設值 * 讓元素照 html 順序排列且緊貼其他元素 * 可以去computed 內建的 filter 功能搜尋它 * 沒有定位 ### relative * 特性跟 static 很像 * 多了四屬性可以操作位置(不使用的則跟 static 一樣) * 定位方式是基於 static ,透過四方位去做偏移 * relative 會浮出 document flow * 一般不會使用這四個屬性在 relative 上 ### absolute * 像是從 document flow 中刪除一般 * 一樣有top, right, bottom, left 四屬性 * 定位方式是基於父母層(但父母層必須要具有定位 relative, absolute, fixed, sticky) * 如果父母層沒有定位會一直往外找,如果都沒有則定位在瀏覽器 html 上 * 使用 scroll 往下滾定位置會跟著移動 ### fixed * 定位方式是基於 html 瀏覽器本身(會忽略父母層) * 使用 scroll 往下滾定位置會固定不動 ### sticky * sticky 有著 fixed, relative 兩種屬性的結合 * 一樣有top, right, bottom, left 四屬性 * 只撰寫 sitcky 沒有加上定位時則只有 relative 屬性 * 使用情況再當 navbar 上面有大片的圖示又必須使用 fixed 的情況 * 使用情況當需要使用 title 隨著 title 跟著螢幕滾動 * sticky 只支援百分之九十的瀏覽器需使用相容性寫在在某些瀏覽器上