css菜雞的自我救贖

0. 前言

做爲一個不喜歡寫樣式的前端,遇到了直接對外的活動頁面的需求,一下炸出一堆問題:css

  • 單位亂用,rem、vh、vw、px亂用甚至混在一塊兒用
  • html冗餘,有時候一個div只是爲了取margin
  • 一個頁面用多種佈局方案,flex、float、relative+top、absolute+top、margin,本身坑本身
  • 各類隨意,不嚴格按照視覺稿 理論卻是熟悉,但用起來仍是一塌糊塗。因而,回頭自我救贖一波,好好複習基礎。flex、grid後面很少做研究,尤爲是grid這種一兩行就能夠搞定不少複雜樣式。若是咱們不知道新技術是爲了什麼而來的,解決什麼痛點,沒有體驗一下刀耕火種的時代,又沒有一個良好的團隊合做能力,作起項目來還真的不必定是「寫頁面太簡單了」這種事情。

1. 一些實踐方案深刻淺出

1.1 padding

看到百度的頂部,你會想到什麼方案呢? html

咱們看百度搜索的頂部,頂部的#head(搜索框這一行都是)是fixed的,緊接着的那個div是一個tab。固然fixed脫離文本流,就用padding把本身的主要內容頂到下面去,否則內容就直接置頂了。前端

沒錯,就是很簡單的一個css,實現的方法有不少。而後咱們再看一下這個視覺效果要怎麼實現: 程序員

img+脫離文本流的方法?雙div+定位?

其實,一個div+padding立刻解決,div背景100%而後center+padding-top,div裏面的文字就天然到下面去了,而後定位定準就行了。另外,文字換成僞元素也能夠。bash

控制寬高比

一些人也知道,padding的百分比相對於width,那麼這樣就能夠實現了一個等比例的盒子,而後隨便縮放均可以了。好比作一個正方形,邊長是屏幕寬度一半:佈局

.scale50 {
  background: #aaa;
  width: 50%;
  height: 0;
  text-align: center;
  padding-top: 50%;
}
複製代碼

不少時候,咱們須要什麼4:3,16:9的圖片,就能夠用這樣的方法解決了。測試

1.2 margin

再看看百度的右邊欄 flex

對於這個欄的左邊部分,用margin仍是padding呢?這個狀況固然是padding,由於有一個邊線😊。對於這個欄的上面,是padding仍是margin呢?實際上,在這個狀況下都是同樣的,可是有一個潛在問題:若是有兩行,並且垂直方向還有其餘盒子的margin,那麼就會發生垂直方向的margin坍塌(取較大值);或者當有父盒子包裹,他的margin會走到外面影響外面。這時候,又要加上轉化爲bfc的代碼。ui

  • case1:
    image
  • case2:
    1

還敢亂來居中嗎

好比,有一個設計稿是這樣的: spa

可能看起來是居中,而後很快寫出來子絕父相的萬金油居中。而後設計忽然走過來講,怎麼老是感受有點不對啊,因而看一下下半部分:
真的不是居中啊,水平方向的也是。那麼,這時候,寫死margin不就搞定了,保證視覺不來找你。

🐦...許多天後,測試說,某某手機視覺就出問題了。固然,寫死px確定藥丸啊,因此移動端就是要用rem解決。我這裏一個rem等於50px,那換算一下,圖上第一個div(綠色的鉤)的margin就是176 148 0 151,換成rem是3.52 2.96 0 3.02,後面的樣式問題只要不是橫屏或者ipad的(無視覺稿的前提)都不是你的鍋了。

負的margin

正的就是撐開整個margin-box,那負的咱們就能夠想象出來,吃掉這個margin-box。通常的狀況下,就是平移。若是加上了float就神奇了,還能跨行平移。雙飛翼和聖盃佈局其中一部分就是利用這個原理

前面都是廢話,不就是一個盒子模型嘛。沒錯,盒子模型,誰都知道,可是用起來誰用的好,這就難說了

2. 開始試試水

接下來,準備用n種方法實現三列布局,中間自適應,兩邊固定寬度

絕對定位

html:

<div class="container">  
   <div class="m">中間</div>
  <div class="l">左邊</div>
  <div class="r">右邊</div>
 </div>
複製代碼

css:

.container{
  position: relative;
  height: 100px;
}
.l, .m, .r {
  height: 100px;
  position: absolute;
}

.l {
  background: #f00;
  width: 100px;
}

.m {
  background: #0f0;
  width: calc(100% - 150px);
  margin: 0 50px 0 100px;
}

.r {
  background: #00f;
  width: 50px;
  right: 0;
}
複製代碼

分析:不論順序,流式佈局,中間先加載,但用了calc

"calc?! 避免recalculate啊"

這時候,去吧,ie盒模型:

.m {
  background: #0f0;
  width: 100%;
  box-sizing: border-box;
  padding: 0 50px 0 100px;
}
複製代碼

看一下對比:

聖盃與雙飛翼佈局

仍是同樣的html

.container {
  height: 100px;
  width: 100%;
  padding: 0 50px 0 100px;
}

.m, .l, .r {
  height: 100px;
  float:left;
}

.m {
  background: #f00;
  width: 100%;
}

.l {
  background: #0f0;
  width: 100px;
  margin-left: -100%;
  position: relative;
  left: -100px;
}

.r {
  background: #00f;
  width: 50px;
  margin-right: -50px;
}
複製代碼

不少人說這個難懂,其實咱們能夠一步步來:先放好容器設好寬高背景,三個div是mlr順序。而後float,顯然m本身佔一行,其餘兩個佔一行。

接着,用到負margin,先把左邊到移動一行,便是-100%,右邊就移動一個身位-50px就ok,如今已是視覺上的3列。最後,中間部分開頭被遮住,並且佔了100%行寬。那麼咱們只能用容器的padding或者本身的margin壓本身。

若是是用容器padding,將左右兩邊騰出來,剛恰好放下lr兩個div。最後,l和r仍是在m裏面,因此還要移一下,relative就好。這就是聖盃佈局

若是是用本身的margin壓本身,那麼就須要多一個div包住本身。前面步驟同樣,包住本身的div佔滿一行,可是自身有margin,完美解決。這就是雙飛翼佈局。圖示和上圖基本如出一轍,只是最外那層不是container而是m,真正的展現出來的中間部分是m裏面的div,另外,l和r也不用relative了。

<div class="m">
  <div class="margin-setting">
  中間
  </div>
</div>
複製代碼

這是傳統css+div的一套比較好的解決方案,不過咱們愁的是高的問題了,須要本身設

float+calc

<div class="container">
    <div class="l">左邊</div>
    <div class="m">這是中間內容</div>
    <div class="r">右邊</div>
  </div>
複製代碼

此次的html不能調換順序寫了

.container {
  height: 100px;
  width: 100%;
}

.m, .l, .r {
  height: 100px;
  float: left;
}

.m {
  background: #f00;
  width: calc(100% - 150px);
}

.l {
  background: #0f0;
  width: 100px;
}

.r {
  background: #00f;
  width: 50px;
}
複製代碼

相似於前面的absolute方案,calc能夠用ie盒子替代

行內元素

是否是遇到過行內元素老是有間隔的問題,html加註釋就能夠去掉分隔符,固然這裏要實現3列布局:

<div class="l">左邊</div><!-- --><div class="m">中間</div><!-- --><div class="r">右邊</div>
複製代碼

css:

.l, .m, .r {
  height: 100px;
  display: inline-block;
}

.l {
  background: #f00;
  width: 50px;
}

.m {
  background: #0f0;
  width: calc(100% - 150px);
}

.r {
  background: #00f;
  width: 100px;
}
複製代碼

特色:樣式及其脆弱,內容換行立刻崩了,只能在沒文字的狀況好一點。calc仍是同樣的方法,ie盒子完美解決

兩個div實現三列

<div class="container" l="左邊">中間</div>
  <div class="r">右邊</div>
複製代碼

左邊的內容用attr抓

.container {
  float: left;
  height: 100px;
  background: #f00;
}

.container::before {
  content: attr(l);
  display: block;
  width: 100px;
  float: left;
  height: 100px;
  background: #0f0;
}

.r {
  height: 100px;
  width: 50px;
  float: left;
  background: #00f;
  margin-right: -100%;
}
複製代碼

用content作的內容,註定了左邊不能再放html元素了

flex與grid

html仍是按順序:

<div class="container">
    <div class="l">左邊</div>
    <div class="m">這是中間內容
    </div>
    <div class="r">右邊</div>
</div>
複製代碼

你們都知道的flex實現:

.container {
  display: flex;
  height: 100px;
}

.l {
  background: #f00;
  min-width: 100px;
}

.m {
  background: #0f0;
}

.r {
  background: #00f;
  min-width: 50px;
}
複製代碼

不過,我更看好grid,符合程序員思惟,一個配置,兩行代碼,基本搞定大部分場景

.container {
  display: grid;
  grid-template-columns: 100px auto 50px;
  grid-template-rows: 100px;
}

.container div:nth-of-type(1) {
  background: #f00;
}

.container div:nth-of-type(2) {
  background: #0f0;
}

.container div:nth-of-type(3) {
  background: #00f;
}
複製代碼

一個div實現

css:

div {
  background: #f00;
  height: 100px;
  margin: 0 50px 0 100px;
  position: relative;
}

div::before {
  content: '左邊';
  display: block;
  background: #0f0;
  height: 100px;
  width: 100px;
  position: absolute;
  left: -100px;
}

div::after {
  content: '右邊';
  display: block;
  background: #00f;
  height: 100px;
  width: 50px;
  position: absolute;
  right: -50px;
  top: 0;
}
複製代碼

固然,只是娛樂而已,項目上誰會寫這個。某些小裝飾可能有機會上

又瞎搞一堆亂七八糟的,先冷靜一下

個人博客即將同步至騰訊雲+社區,邀請你們一同入駐:cloud.tencent.com/developer/s…

相關文章
相關標籤/搜索