使用這種技巧,可以大大地提高前端布局效率
在布局中,對于每塊功能的 DOM 結構,我們一般使用一個帶有 wrapper 類元素把它包裹起來,讓代碼或者網頁內容更易于閱讀。為此,我們一般使用wrapper 或者container。在CSS 中使用wrapper可能有多種方式,這些方式中,有些會帶來一些問題。
在本文中,將介紹 CSS中 的 wrapper 布局,它們如何工作,如何使用它們以及何時不使用它們。請注意,在本文中,可能會提到wrapper 和container這兩個術語,它們的含義相同。
wrapper 簡介
當我們說到 wrapper 或container,實際上是指一組元素被包裝或包含在另一個元素內。我們可以為 元素添加一個 wrapper類,這樣我們就不用額外元素,如下所示:
- body {
- max-width: 1170px;
- margin-left: auto;
- margin-right: auto;
- padding-left: 16px;
- padding-right: 16px;
- }
但是,將 wrapper添加到元素是不切實際。 wrapper元素可以防止子項超出其邊界。考慮下圖:
我們這里有aside和main元素,它們被放在了wrapper 元素中。當然,.wrapper元素有一個寬度
- <div class="wrapper">
- <aside>...</aside>
- <main>...</main>
- </div>
如果沒有wrapper,子元素將粘附在屏幕的邊緣。這可能會讓用戶非常惱火,尤其是在大屏幕上。
上圖顯示了當沒有用wrapper進行包裹時元素是如何展開的,用戶不應該體驗這種行為。我們來解釋一下背后的原因。
為什么頁面上 wrapper 有必要的
通過多加一層 wrapper 布局,有很多好處:
- 使內容更具可讀性。沒有多加一層 wrapper,文本和圖像之類的內容就可以拉伸以占據整個屏幕寬度。對于小屏幕,這似乎可以。但是,對于大屏幕,這是非常煩人的。
- 對設計元素進行分組可以更好地增加間距。
- 在沒有wrapper的情況下,將設計元素劃分為列是不容易完成的。
在CSS中實現 wrapper
目前我們已經了解了wrapper基礎知識和優點,接下來我們來具體的看看在 CSS 如何使用它。
設置寬度
實現wrapper第一件事就是要確認它的寬度。而寬度如何這取決于 UI 的設計。一般來說,最常用寬度是1000px-1300px。例如,流行的框架Bootstrap使用1170px的寬度。
- .wrapper {
- width: 1170px;
- }
但是,不建議使用width屬性,因為當屏幕尺寸小于1170像素時,會出現水平滾動。可以max-width 來解決這個問題。
- .wrapper {
- width: 1170px;
- max-width: 100%;
- }
我們還可以更簡單點,僅使用 max-width。
- .wrapper {
- max-width: 1170px;
- }
現在有了寬度,我們可以將它居中 。
居中 wrapper
為了讓 wrapper 居中,使用讓左右外邊距的值為 auto,如下所示:
- .wrapper {
- max-width: 1170px;
- margin: 0 auto;
- }
根據 CSS 規范,下面是margin: 0 auto;的工作原理
如果'margin-left'和'margin-right'均為'auto',則它們的使用值相等。這會讓元素相對于包含塊的邊緣水平居中。
這里我使用margin:0 auto,這基本上將頂部和底部的margin重置為零,并使其左側和右側為auto。使用此功能會有一些后果,這將在本文后面介紹。目前,建議使用簡化版邊距:
- .wrapper {
- max-width: 1170px;
- margin-left: auto;
- margin-right: auto;
- }
在左側和右側添加 padding
要考慮的重要事項是在左側和右側添加padding。當視口大小小于 wrapper 的最大寬度時,這將導致 wrapper 邊緣粘在視口上。
- .wrapper {
- max-width: 1170px;
- margin-left: auto;
- margin-right: auto;
- padding-left: 16px;
- padding-right: 16px;
- }
通過添加padding,我們可以確保從左右兩邊得到一個16px的偏移量,即使視口的大小小于最大寬度。padding作為一種保護策略,避免在寬度不足時讓 wrapper 粘在視口邊緣。
使用百分比的 wrapper
我收到了有關使用百分比寬度(如max-width:90%)用于包裝器而不是使用padding-left和padding-right的答復。
我經常可以到直接在 'wrapper' 使用百分比寬度,如max-width: 90%。而不是使用padding-left和padding-right。
在大屏幕上,寬度90%太大了,我們可以使用媒體查詢來覆蓋它。
- .wrapper {
- max-width: 90%;
- margin-left: auto;
- margin-right: auto;
- }
- /* A media query for a large screen */
- @media (min-width: 1170px) {
- .wrapper {
- max-width: 1170px;
- }
- }
使用百分比寬度,我們多添加了一個額外的步驟。通過使用固定的寬度值,我們可以輕松地避免此步驟。對應于這種方案,我們可以將width: 90%與max-width:1170px屬性結合在一起。
- .wrapper {
- width: 90%;
- max-width: 1170px;
- margin-left: auto;
- margin-right: auto;
- }
這是一個有趣的方法,但我更喜歡自己添加padding,而不是依賴于百分比寬度。
Wrapper 的display類型
由于wrapper 是<div>,因此默認情況下它是塊級元素。問題是,當要將wrapper內的內容放置在grid中時,該怎么辦?我們直接在 wrapper 上添加 display: grid ?
我不建議您這樣做,因為這與關注點分離的概念背道而馳。wrapper用于包裹其內容,僅此而已。如果需要使用grid布局,則在多添加一層
專門用來 grid 布局會更容易也更清晰還容易維護。
- <div class="wrapper">
- <!-- Content -->
- </div>
不建議這樣做,因為wrapper元素可以在另一頁上使用,這可能會無意間破壞布局。
- .wrapper {
- display: grid;
- grid-template-columns: 2fr 1fr;
- grid-gap: 16px;
- }
更好的解決方案如下:
- <div class="wrapper">
- <div class="featured-news">
- <!-- Elements that needs to be placed in a grid -->
- </div>
- </div>
- .featured-news {
- display: grid;
- grid-template-columns: 2fr 1fr;
- grid-gap: 16px;
- }
在 wrapper 之間添加 margin
上面我們說到不建議使用簡寫版本來居中wrapper 元素:
- .wrapper {
- margin: 0 auto;
- }
雖然它可以工作,但當頁面上有多個wrapper ,并且需要在它們之間添加間距時,它可能會令人困惑。由于布局需要,我們需要在 wrapper 上多添加一個類,如 wrapper-variation,那么margin有可能無法正常工作。
- .wrapper-variation {
- margin-top: 50px;
- }
- .wrapper {
- max-width: 1170px;
- margin-left: auto;
- margin-right: auto;
- padding-left: 16px;
- padding-right: 16px;
- }
.wrapper-variation元素的margin無法使用,因為它已被margin: 0 auto覆蓋。為避免此類混淆,建議在這種情況下使用非簡寫格式 。
現在讓我們來添加頁邊距。在每個項目中,我都準備了一組用于margin和padding的實用工具類,在必要時使用它們,考慮下圖。
- <div class="wrapper mb-5"></div>
- <section>
- <div class="wrapper"></div>
- </section>
- <div class="wrapper"></div>
- .mb-5 {
- margin-bottom: 3rem !important;
- }
這樣,wrapper 的 CSS保持原樣,并且使用附加的 CSS 類添加了間距。現在,你可能會問,為什么可以在一個頁面上添加多個wrapper?在上面的HTML中,兩個wrapper之間有一個<section>
在這里使用!important很好,因為實用程序類的要點是強制屬性,通過添加!important,我們可以確保做到這一點。
全屏中的 Wrapper
在某些情況下,如果某個部分的背景視口寬度為100%,并且其中包含wrapper`,則可能會出現這種情況。與上一個示例中介紹的類似。
- <section>
- <div class="wrapper"></div>
- </section>
- <section>
- <div class="wrapper"></div>
- </section>
主內容需要添加 wrapper 嗎?
這要看情況。讓我們探討兩種最常用內容區間的設計。
第一個以其內容為中心,并受特定寬度限制。
第二個將其內容擴展到主內容的邊緣。
為了更好地理解這兩種模式,我們來一起探討如何構建其中的每種模式。
內容居中
你可能想在不使用 wrapper前提下讓內容居中。
- <section class="hero">
- <h2>How to make bread at home</h2>
- <p>....</p>
- <p><a href="/sign-up">Sign up</a></p>
- </section>
在上面的 HTML 中,可以使用text-align將內容居中
- .hero { text-align: center; }
除非你調整瀏覽器窗口的大小,不然你可能會忽略掉這個問題。
內容緊貼邊緣
由于左側和右側沒有padding,因此內容將粘在邊緣上。這對用戶是不友好的,因為使內容瀏覽變得更加困難。
大屏幕的行長
在大屏幕上,由于行長太長,段落文本可能很難看清。根據應用于 Web 的版式樣式元素,行的建議字符數為45到75。超出該范圍的任何字符都會使閱讀更加困難。
為避免上述問題,可以使用wrapper來防止文本長度變得過長并在移動設備中增加間距。
- <section class="hero">
- <div class="hero__wrapper">
- <h2>How to make bread at home</h2>
- <p>...</p>
- <p><a href="/sign-up">Sign up</a></p>
- </div>
- </section>
這里使用了hero__wrapper類,因為該wrapper可能僅是針對hero部分定制的,因此它可以具有一定的寬度,該寬度小于通用的wrapper元素。
- .hero__wrapper {
- max-width: 720px;
- margin-left: auto;
- margin-right: auto;
- padding-left: 16px;
- padding-right: 16px;
- }
為了使內容居中,可以根據具體情況使用具體的屬性。對于此示例,使用text-align:center足以使內容居中。
對wrapper使用 CSS 變量
只用一種尺寸的wrapper很少。wrapper的寬度可以小也可以大,具體取決于內容。通過利用 CSS 變量,我們可以創建一個更現代的wrapper,它擁有極大的靈活性。考慮以下內容:
- <div class="wrapper"></div>
- .wrapper {
- max-width: var(--wrapper-width, 1170px);
- margin-left: auto;
- margin-right: auto;
- padding-left: 16px;
- padding-right: 16px;
- }
var有兩個值,第一個值是變量--wrapper-width,第二個值是1170px,如果未設置--wrapper-width變量,則將使用1170px。
當然,我們可以直接在標簽內對 --wrapper-width 進行賦值,這樣就能動態設置我們想要的值。
- <div class="wrapper" style="--wrapper-width: 720px"></div>
如果你不使用 CSS 變量的方式,也可以通過多加一個類來解決:
- <div class="wrapper wrapper--small"></div>
- .wrapper--small {
- --wrapper-width: 720px;
- /* this will override the default wrapper width. */
- }
使用 display: contents
首先,簡要介紹一下這個屬性。CSS中的每個元素都是一個盒子,該盒子包含content、padding、margin和border。display: contents樣式規則使div元素不產生任何邊界框,因此元素的margin、border和padding部分都不會渲染。然而,繼承的屬性如顏色(color)和字體(font)卻能照常影響到子元素。
- <header class="site-header">
- <div class="wrapper site-header__wrapper">
- <!-- Header content -->
- </div>
- </header>
- .site-header__wrapper {
- display: flex;
- flex-wrap: wrap;
- justify-content: space-between;
- }
在上面的示例中,你可能需要讓標題擴展到整個頁面的寬度,而不是受wrapper寬度的限制。
- .site-header__wrapper {
- display: contents;
- }
- .site-header {
- display: flex;
- flex-wrap: wrap;
- justify-content: space-between;
- }
這樣,.wrapper元素將被隱藏(類似)。現在,當將display:flex應用于.site-header元素時,.wrapper的后代項將成為.site-header的子項。
流動背景,固定內容
Lea Verou 在她的《CSS Secrets》一書中介紹了一種有趣的技巧,該技巧可用于流動背景(占據整個視口寬度)且內部帶有wrapper部分。讓我們回顧一下常見的做法。
- <section>
- <div class="wrapper"></div>
- </section>
- section {
- background-color: #ccc;
- }
- .wrapper {
- max-width: 1170px;
- margin-left: auto;
- margin-right: auto;
- padding-left: 16px;
- padding-right: 16px;
- }
margin-left: auto和margin-right: auto的工作方式是計算視口寬度的一半減去內容寬度。使用padding也可以做到。

- section {
- padding: 1rem calc(50% - 585px);
- }
這樣還有問題,在移動設上內容將粘貼備的邊緣,一種解決方案如下:
- section {
- padding: 1rem;
- }
- @media (min-width: 1170px) {
- section {
- padding: 1rem calc(50% - 585px);
- }
- }
作者:Ahmad shaded 譯者:前端小智 來源:sitepoint 原文:https://ishaded.com/article/styling-css/
本文轉載自微信公眾號「大遷世界」,可以通過以下二維碼關注。轉載本文請聯系大遷世界公眾號。