> 原文出處:http://www.w3cplus.com/css3/css-secrets/flexible-background-positioning.html
## 問題
我們經常遇見的一個問題就是,需要將背景圖片定位到不同的位置,往往不僅是左上角,比如右下角。在 CSS 2.1 中,只能指定圖片相對左上角的偏移量,或者使用關鍵字定位到其他的角落。不過,通常希望在背景圖片和邊角之間保留一些空間,避免類下圖的效果。

*因為圖像和邊緣之間沒有間隔,所以?`background-position: bottom right;`?實現的效果通常并不美觀*
對于具有固定尺寸的容器,在 CSS 2.1 中是可以解決這個問題的,但是使用的技術比較雜亂:我們需要計算出背景圖片相對左上角的偏移量,模擬出背景圖片和左下角之間的間隙。但是,對于尺寸不固定的元素(由于內容不固定導致的尺寸不固定),這種方法就無能為力了。開發者通常喜歡使用百分比設置背景位置,通常是略小于?`100%`?的值,比如?`95%`。當然,使用最新的 CSS,我們對這個問題有更優雅的解決方法。
## 解決方案:增強型?`background-position`
在?[CSS Backgrounds & Borders Level 3](http://w3.org/TR/css3-background)?中,增強型的?`background-position`?屬性已經開始支持針對每個邊角的偏移量了,開發者需要做的就是在偏移量之前加上邊角的信息。比如,如果我們想要背景圖片距離右側邊界?`20px`,距離底部邊界?`10px`,那么就可以這么做:
~~~
background: url(code-pirate.svg) no-repeat #58a;
background-position: right 20px bottom 10px;
~~~
完成后的效果如下圖所示:

*不同的邊上指定偏移量,如圖所示的虛線輪廓*
最后需要做的就是設置降級措施。目前,大多數的瀏覽器尚不支持新式的?`background-position`?語法,雖然編寫了上述代碼,在某些瀏覽器背景圖片仍然會被定位到左上角,看起來非常難看,并且遮擋住部分文字,如下圖所示效果:

*如果我們不希望低版本瀏覽器的用戶看到這樣的效果,就需要提供一種降級處理*
一個簡單降級方式是在?`background`?縮寫屬性中添加定位屬性?**bottom right**?:
~~~
background: url(code-pirate.svg)
no-repeat bottom right #58a;
background-position: right 20px bottom 10px;
~~~
## 解決方案:`background-origin`
通常,我們只需要給容器添加內邊距就可以模擬背景圖片和邊界之間的偏移。如果使用上一節講述的?`background-positon`?來做這件事,那么代碼就會像這樣:
~~~
padding: 10px;
background: url(code-pirate.svg) no-repeat #58a;
background-position: right 10px bottom 10px;
~~~
最終效果如下圖所示:

*為背景圖添加的偏移量正好等于內邊距的值*
如你所見,效果還不錯,但是這些代碼并不夠簡潔:如果需求發生變化需要修改代碼,那么我們需要修改三處代碼才能完成。所幸還有一種簡單的方式可以代替它,無需重復聲明內邊距即可讓背景圖片根據內邊距調整偏移量。
在你的web開發生涯中,你可能會寫許多次類似?`background-position: top left;`?的屬性。那么你是否思考過:哪里是左上角(`top-left corner`)?或許你已經知道了,每一個元素都有四個盒模型(如下圖所示):外邊距盒模型(margin box)、邊框盒模型(border box)、內邊距盒模型(padding box)以及內容盒模型(content box)。那么 background-position 中所指的 top left 指的是哪一個盒模型呢?

實際上,`background-position`默認上值得就是內邊距盒模型,所以邊框最終遮蓋了背景圖片。因此,`top left`?默認上指的就是內邊距盒模型的左上角。不過在?[Backgrounds & Borders Level 3](http://www.w3.org/TR/css3-background/)?中,我們擁有了新的屬性用來改變這種默認行為:`background-origin`。你可能已經猜測到了 ,它的默認值也是?`padding-box`。如果我們就像下面的代碼一樣=將其更改為?`content-box`,那么?`background-pisition`?就會將`content-box`?視為背景圖片的存在范圍(實際上,這意味著所有的背景圖片將會根據內邊距實現和邊框的偏移):
~~~
padding: 10px;
background: url("code-pirate.svg") no-repeat #58a
bottom right; /* or 100% 100% */
background-origin: content-box;
~~~
現在視覺效果和前面示例相同了,不過更勝一籌的是現在的代碼更簡潔。一定要牢記,如有需要你可以將上述的兩種方法組合起來使用。如果你想使用不同的內邊距,同時又想讓其向外突出或向內嵌入,那么就可以組合使用?`background-origin: content-box`?和?`background-position`。
## 解決方案:`calc()`
讓我們重新審視一下我們遇到的挑戰:我們需要將背景圖片定位到離右邊框?`20px`、離底部邊框?`10px`的位置。不過,使用這樣解決方案,我們需要將其視為從左上角的偏移量,所以可以視為在水平方向偏移?`100% - 20px`、在垂直方向偏移?`100% - 10px`。所幸的是,`calc()`?函數就可以幫我們完成這種計算,并且可以完美地融入?`background-position`?屬性:
~~~
background: url("code-pirate.svg") no-repeat;
background-position: calc(100% - 20px) calc(100% - 10px);
~~~
> 在?`calc()`?中,不要忘記在加減號操作符左右添加空格,否則就會發生解析錯誤!這種奇怪的規則是為了兼容性:因為在未來,`calc()`?中可能會允許使用關鍵字,而這些關鍵字中就有可能會包含連字符。
## 總結
在 CSS 2.1 中,只能指定圖片相對左上角的偏移量,或者使用關鍵字定位到其他的角落。如果需要讓背景圖距離元素四邊距有一定的偏移量,相對而言是較為麻煩。在這篇文章中,作者通過`background-position`新特性、修改`background-origin`以及`calc()`函數等三種方法,實現了一種靈活型的背景圖定位。希望這篇文章對大家有所幫助。