CSS布局奇淫巧計之 強大的負邊距

2021-08-20 01:30:51 字數 4339 閱讀 5202

css中的負邊距

(negative margin)

是布局中的乙個常用技巧,只要運用得合理常常會有意想不到的效果。很多特殊的

css布局方法都依賴於負邊距,所以掌握它的用法對於前端的同學來說,那是必須的。本文非常基礎,老鳥可以略過。

負邊距在普通文件流中的作用和效果

那些沒有脫離文件流的元素(指不是浮動元素也不是絕對定位、固定定位的元素等),其在頁面中的位置是跟隨者文件流的變化而變化的。看下面這幅圖:

負邊距對這些由文件流控制的元素的作用是,會使它們在文件流中的位置發生偏移,但這種偏移不同於相對定位,通過相對定位偏移後,其仍然會堅守著它原來佔據的空間,不會讓文件流的其它元素乘虛而入。而通過負邊距進行偏移的元素,它會放棄偏移前佔據的空間,這樣它後面文件流中的其它元素就會「流

」過來填充這部分空間。還是通過例子來說明吧。現在我們把上圖中的塊狀元素、行內元素以及

inline-block

元素都設乙個負邊距

margin:-10px;

看看會發生什麼:

我們看到,黑灰色的塊狀元素好像向左和向上都分別嵌入了瀏覽器視窗的邊界裡10px,然後塊狀元素下面的文字也爬到了它身上,行內元素向左移動蓋住了它前面的乙個字,它後面的文字也有一部分覆蓋在了它身上,

inline-block

的位置變化也很明顯。

好了,這點相信大家早就心知肚明了,就是負的邊距好像能減小元素在文件流中的尺寸一樣,但事實上,它的尺寸大小並沒變,只是文件流在計算元素位置的時候,會認為負邊距把元素的尺寸減小了,因為位置也就發生變化了。這只是打個很形象的比喻,幫助大家理解一下。還要注意的是,文件流只能是後面的流向前面的,即文件流只能向左或向上流動,不能向下或向右移動。

所以,一切只要是由文件流決定的東西,負邊距就能起作用了。

比如,乙個沒有設定高度的塊狀元素,其高度是自動的,具體來說就是由它裡面的文件流最後的位置決定的。假設它裡面有乙個出於文件流中的子元素,高度為100px;那這時這個父元素的高度就等於子元素的高度

100px

了,如果子元素繼續增高,那麼父元素也會跟著增高。可是如果這時子元素設乙個負的

margin-bottom,

比如-20px

,因為負邊距會影響到文件流,本來文件流的高度是從父元素的最頂端到子元素的最底端這段高度,現在子元素有乙個

margin-bottom:-20px;

就相當於文件流要向上退後

20px,

這樣整個文件流的高度就減少了

20px

了,那麼父元素的高度也會跟著減少

20px

。在ie8+

以及那些標準瀏覽器中,這還需要父元素擁有乙個

overflow:hidden

的屬性,因為父元素的高度變了,但子元素的高度並沒有變,所以需要使子元素超出隱藏,但即使不設定

overflow:hidden

,父元素的高度也是變小了的,只不過這時子元素的高度會超出父元素。在

ie6中則不需要,但需要觸發它的

haslayout

屬性。所以以前所說的

多列等高布局

就是利用這個原理來實現的。

總之一句話,在文件流中,元素的最終邊界是由margin決定的,

margin

為負的時候就相當於元素的邊界向裡收,文件流認的只是這個邊界,不會管你實際的尺寸是多少。

左和右的負邊距對元素寬度的影響

負邊距不僅能影響元素在文件流中的位置,還能增加元素的寬度!

這個作用能實現的前提是:該元素沒有設定width屬性(當然

width:auto

是可以的)。

比如下圖的黑灰色部分是乙個塊狀元素,它沒有設定寬度。它被包裹在乙個寬度為400px,且水平居中的父元素中。

現在給這個元素的設乙個margin-right:-100px;

我們看到它的寬度的確變長100px;然後再給它設乙個

margin-left:-100px;

我們看到它變得更寬了。

負的margin會改變元素的寬度,這的確很讓人費解,如果說負邊距會改變元素在文件流中的位置還是很好理解的話,那改變寬度這種現象還真的蠻讓人不可思議的。

那這貨有什麼用途呢?我就舉乙個例子吧。

想要建立上圖中黑框內的幾個元素按順序排下來,中間帶些間隔的布局要怎麼做?,當然最簡單省事的方法就是利用浮動了。我們把黑框裡面的子元素向左浮動,然後設乙個合適的margin-right,是不是就辦到了呢?但因為外邊黑框的寬度是固定的,就是裡面四個子元素的寬度加上三列間隔的寬度,所以靠近右邊邊界的子元素就不應該有正向的

margin-right

了,否則這一行就只能容納三個子元素了。有人說那這還不簡單,給靠近右邊界的那些子元素加乙個

class

,把它的

margin-right設為0

不就行了。這當然可以,但如果這些子元素是在模板中通過迴圈動態輸出的,那在迴圈的時候還得判斷哪些子元素是靠近右邊邊界的,如果是就加上乙個

class

。這樣做的話是不是就有點麻煩了?所以解決辦法是加大子元素的父容器的寬度,讓它能夠容納一行中有四個子元素加上四列間隔的寬度,然後最外面的的黑框的那個容器設乙個

overflow:hidden

就行了。上面說了負的左右邊距能加大元素的寬度,所以給子元素的父容器設乙個合適的負的

margin-right

就可以了。當然你也可以直接在

css中把子元素的父容器的寬度設寬一些,舉這個例子只是為了說明負邊距也是一種方法。看下完整的**:12

3456

78910

1112

1314

1516

1718

19<

style

>

body,ul,li

ul,li

.container

ul/*乙個負的margin-right,相當於把ul的寬度增加了20px*/

listyle

>

<

divclass="container">

<

ul>

<

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>

div>

負邊距對浮動元素的影響

負邊距對浮動元素的影響與負邊距對文件流中元素的影響其實是差不多的。文件流中元素的位置由文件流的走向決定,浮動的元素也可以看成有乙個「浮動流

」存在,不過浮動流既可以向左,也可以向右。

比如下圖是三個向左浮動的元素,寬高都是100px:

現在把它們都設乙個margin-right:-50px; 然後會變成這樣子:

我們看到後面的元素疊到了前面的元素上。

再看下面的圖:

我們把瀏覽器縮小了,然後因為寬度不夠,元素3掉下來了。我們給元素

3設乙個

margin-left:-80px;

看看會怎麼樣

這時我們看到元素3上去了,而且還覆蓋了元素

2的一部分。繼續元素3設為

margin-left:-100px

這時元素3完全覆蓋住了元素

2,當元素

3設為:

margin-left:-200px

時:我們看到元素3繼續向左移動並覆蓋住了元素1。

現在想必大家都明白了負邊距對浮動元素位置的影響了吧。所以那些說得很好聽的什麼聖杯布局、雙飛翼布局啊什麼的,都是利用這個原理實現的。就是某個元素雖然是寫在了後面,但可以通過負邊距讓它在瀏覽器顯示的時候是在前面的。這個以後可以再慢慢講。

負邊距對絕對定位元素的影響

絕對定位的元素定義的top、

right

、bottom

、left

等值是元素自身的邊界到最近的已定位的祖先元素的距離,這個元素自身的邊界指的就是

margin

定義的邊界,所以,如果

margin

為正的時候,那它的邊界是向外擴的,如果

margin

為負的時候,則它的邊界是向裡收的。利用這點,就有了經典的利用絕對定位來居中的方法:

看下效果:

但該方法的缺點是必須要知道要居中元素的高度和寬度。

關於linux程式設計的奇淫巧計系列的FAQ

自從發布linux程式設計的奇淫巧計系列以後,很多讀者給我寫來郵件,這裡我一併作答。1 你寫的內容有多少是實踐中可以用到的?還是只是花裡胡哨的東西?答 我負責的告訴你,大部分都是工程實踐中用到的,否則我哪能想到這麼些個花招,大部分都是我在工作實踐和知名開源 中看來得,如果有長期看開源 的朋友應該能體...

關於linux程式設計的奇淫巧計系列的FAQ

自從發布linux程式設計的奇淫巧計系列以後,很多讀者給我寫來郵件,這裡我一併作答。1 你寫的內容有多少是實踐中可以用到的?還是只是花裡胡哨的東西?答 我負責的告訴你,大部分都是工程實踐中用到的,否則我哪能想到這麼些個花招,大部分都是我在工作實踐和知名開源 中看來得,如果有長期看開源 的朋友應該能體...

linux程式設計的108種奇淫巧計 12 儲存計算

有時候,我們可以將計算好的值進行儲存,需要的時候取出,這樣可以大大降低計算量,用空間代替時間。我們從乙個問題出發,農夫john和他的朋友們一同去參加cownty展會,這個展會的門票是50元,排隊購票的人 有2n個人,其中n個人拿著100元的鈔票,另外n個人拿著50元的鈔票,農夫john想知道在這種情...