如何在限寬的容器中實現全屏效果
在Web布局中,特別是在PC端中,常常可以看到這樣的設計風格: 內容居中,然后Banner區全屏 。這也就是標題所說的效果,限寬的容器中實現全屏效果。那么問題來了,在實際中如何實現在限寬的容器中實現全屏效果。比如下面的設計風格:
作為一名前端開發人員,上圖的效果并不陌生。假設我們內容區域是 960px ,然后水平居中。而其中Banner區域是全屏效果。如下所示:
那么實際開發中以什么方式來做更為方便靈活呢?這就是這篇文章需要介紹的內容。
頁面結構
針對這樣的設計風格,前端人員考慮的結構會有:
<div class="header">
<div class="container"></div>
</div>
<div class="banner">
<div class="container">
<img src="" alt="">
</div>
</div>
...
這種結構要實現上述的需求,并不復雜。
.container {
width: 960px;
margin-left: auto;
margin-right: auto;
}
.banner .container {
width: 100%;
}
.banner img {
width: 100%;
max-width: 100%
}
但很多時候,全屏圖片的效果并不僅僅是在Banner區域。比如說在文章中插入的圖片也需要全屏效果。那么針對上面的結構,咱們就有點蛋疼了。比如:
<div class="main">
<div class="container">
<p>....</p>
<figure class="full-width">
<img src="" alt="">
</figure>
<p>...</p>
</div>
</div>
這才是問題的關鍵,如何讓 .full-width 中的 img 能實現全屏的效果。正如文章開頭的示意效果圖。
CSS解決方案
針對上面描述的情況,首先能考慮到的方案就是采用我們常能看到的水平居中的一個效果。比如我們有一個元素(元素大小未知),要其水平居中。首先想到的是:
.full-width{
position: absolute;
left: 50%;
transform: translateX(-50%);
}
在此思路上進行一下擴展。 .full-width 容器寬度是瀏覽器全屏寬度,在你腦海中立馬浮現的是 100% ,但問題是,該元素是放置在 .container 容器中,而它的寬度又是 960px 。如果僅僅在 .full-width 上設置 100% ,那它的寬度并不等于瀏覽器視窗的全屏寬度,而是一個 960px 。如此一來,并不是我們想要的效果。
既然如此,有什么方法可以讓 .full-width 的寬度是瀏覽器視窗的全屏寬度。給大家推薦一個視窗單位 vw 。在這種情況下,視窗,指的是瀏覽器屏幕。 1vw 就意味著 1% 的瀏覽器的寬度。 100vw 將意味著整個瀏覽器寬度。
如此一來, .full-width 要拿到瀏覽器全屏的寬度就很容易了。只需要設置其 width 值為 100vw 。要實現文章開頭示意的效果,有一個這樣的思路。那就是把 .full-width 容器向右推 50% ,然后使用 margin-left: -50vw 拉回去。以同樣的原理,把容器向左推 50% ,并使用 margin-right: -50vw 向右拉出去。如此一來, .full-width 就占據瀏覽器全屏寬度。不過需要注意的是,這里不能使用 position:absolute; 。因為使用 absolute 會讓容器脫離文檔流,至于這個問題,只需要將其值換成 relative ,就搞定了。根據上述描述,其效果變化過程如下所示:
這樣我們就可以這樣來寫樣式:
.full-width {
width: 100vw;
position: relative;
left: 50%;
right: 50%;
margin-left: -50vw;
margin-right: -50vw;
}
結過上面的處理,容器 .full-width 雖然其父容器有寬度限制水平居中,但經過上面的代碼拉伸推移,就實現了容器的全屏效果。如下所示:
.full-width 容器已實現在限制寬度的容器中實現瀏覽器全屏寬度的效果。如果里面有 img ,只需要添加下面的樣式代碼:
.full-width img {
width: 100%;
max-width: 100%;
}
如此一來,實現的效果如下面錄制的效果一樣:
再思考一下,是不是這樣就完美了呢?或者說有沒有別的方案。我還是想到了 transform 中的 translateX 。既然 left 和 right 推移能實現,那我們是不是也可以考慮使用 translateX 。那問題來了,應該向左拉多少才合適呢?
簡單分析一下,容器的寬度是 960px ,全屏的寬度是 100vw ,他們之間相差就是 960px - 100vw , 但我們只需要向左拉出其值的一半,也就是 (960px - 100vw) / 2 。知道原理就好辦了,咱們借助CSS的 calc() 函數 ,就解決一切問題了。
.full-width {
width: 100vw;
transform: translateX(calc(( 960px - 100vw ) / 2));
}
在CSS中 translateX 可以實現拉伸效果。除此之外,在CSS中 margin-left 和 margin-right 取值為負值時,也一樣能實現位置變化。這樣我們的代碼可以調整為:
.full-width {
margin-left: calc( (960px - 100vw) / 2);
margin-right: calc( (960px - 100vw) / 2);
}
上面的代碼,還可以優化一下。 960px 相當于 100% ,這樣一來 960px / 2 也就相當于 50% ;對應的 100vw / 2 就變成了 50vw 。這樣上面的代碼就變成了:
.full-width {
margin-left: calc(50% - 50vw);
margin-right: calc(50% - 50vw);
}
效果如下:
上面使用了三種CSS方案實現限制寬度實現全屏效果。
Sass改造
為了上面的方案可以在需要使用的時候可隨時使用。我們可以通過CSS處理器,比如說Sass的混合宏對其進行封裝。比如我們創建一個 full-width 的混合宏,并且給這個混合宏傳遞兩個參數,第一是實現方案的類似 $support-type ,可以給他傳遞三個值:
- margin :對應CSS中 margin-left 和 margin-right 的方案
- position : 對應CSS中 position 定位的方案
- translate : 對應CSS中 translateX 的方案
并且給 $support-type 一個默認值,那就是 margin 。另外在給 full-width 傳遞一個 $min-width 的參數,其參數值默認設置為 null 。其在實際調用的時候,就是對應其容器的寬度值。比如前面示例中所演示的 960px 。
針對上述描述,采用Sass的 @if 打件控制來做一個判斷,最終我們需要的混合宏如下所示:
@mixin full-width($support-type: margin,$min-width:null){
@if $support-type == 'margin' {
margin-left: calc(-50vw + 50%);
margin-right: calc(-50vw + 50%);
// margin-left: calc(-100vw / 2 + #{$min-width} / 2);
// margin-right: calc(-100vw / 2 + #{$min-width} / 2);
}
@if $support-type == 'position' {
width: 100vw;
position: relative;
left: 50%;
right: 50%;
margin-left: -50vw;
margin-right: -50vw;
}
@if $support-type == 'translate' {
width: 100vw;
transform: translateX(calc((#{$min-width} - 100vw)/2));
}
}
有了上述定義的混合宏,在實際使用的時候,只需要向下面這樣調用:
.full-width {
@include full-width(margin,960px);
}
最終我們的效果如文章開頭的示意圖:
在調用 full-width 混合宏的時候,你只需要改變其第一個參數,就能選擇對應的實現方案。感興趣的可以去嘗試一下。
在平時工作或者學習的過程中,你可以像這篇文章介紹的一樣,不斷的積累一些實用的Sass混合宏。如果你感興趣的話,你可以下載Sass的混合宏和函數集合: SassMagic 。
總結
在限寬的容器中實現全屏效果可以說在Web設計中是非常常見的。這篇文章通過CSS使用了三種不同的方案實現了我們想要的效果,最后使用Sass的混合宏將CSS中介紹的三種方案集合在一起。在實際項目中可以通過調用參數,采取對應的CSS解決方案。讓你的操作變得更為簡便。
來自:http://www.w3cplus.com/css/full-width-containers-limited-width-parents.html