自從圖形界面操做系統問世以來,之上的應用軟件基本都會繪製界面,這也是用戶使用軟件的接口,叫作 UI (user interface)。涉及到用戶體驗、設計、具體界面的開發,是軟件中和用戶最近的一部分,也是多個職能的崗位交集最多的部分。css
根據操做系統不一樣,會有不一樣的界面的開發方式。安卓、ios、windows 等都有各自的建立 ui 的庫,可是更底層的繪圖庫倒是有標準的:跨平臺的繪圖 api 接口標準 OpenGL 以及 windows 下的 DirectX。html
由於各個操做系統繪製 ui 的方式不一樣,因此跨平臺的繪製方案逐漸流行開來,也就是瀏覽器。基於瀏覽器服務器的軟件架構叫作 B/S 架構,而基於客戶端的叫作 C/S 架構。前端
在一段時間內,B/S 架構的應用愈來愈多,C/S 架構的應用也更多的混合 B/S 的方案來實現。vue
在移動互聯網時代來臨以後,你們發現網頁的體驗比不上原生,雖而後面發展出了 PWA (漸進式WebApp)等技術,但離原生的體驗仍是有差距的,因此原生開發應用的方案又佔了上風。react
可是安卓、ios 繪製界面、書寫邏輯的方式都不一樣,雙端要分別實現,開發、測試的人力都是雙份的,這樣的成本是比較高的。爲了節省成本,你們又摸索出了跨端引擎的方案,也就是說仍是經過網頁來寫渲染和交互的邏輯,可是渲染用的 api 是由安卓、ios 分別實現,這樣就實現了跨端的渲染,邏輯部分也是由 JS 來寫,一些須要的設備能力 api 分別由安卓、ios 實現而後注入到 JS 引擎裏。ios
和安卓、ios 的跨端方案逐漸流行同樣,桌面端也出現了 electron 的方案,經過網頁來渲染界面和寫邏輯,須要用的 api 注入到 JS 引擎中,並且 electron 是直接把 Node.js 的 api 注入到了 JS 引擎中,在網頁裏實現一些原生功能的時候能夠直接使用 Node.js 的 api,此外還有一些 api 是 elctron 額外注入的,好比剪貼板、電源監視器等。web
發展到如今,UI 的繪製方案逐步向網頁靠攏,基於 html、css、js 的 web 技術成爲了建立 UI 界面的主流方案。canvas
你們用過 canvas 的 api 應該知道,若是直接繪製的話須要指定什麼內容繪製到什麼地方,每一部分都要計算,而這是比較繁瑣的,因此瀏覽器提供了一些佈局用的樣式,而且提供了 css 來描述,而內容部分則是經過 html 描述。windows
開發者只須要使用 html 描述內容的結構,而後用 css 來描述佈局和如何渲染,就能夠完成界面的繪製。網頁會把 html 解析成 dom 樹,把 css 解析成 cssom 樹,以後把二者合併成 render 樹,自動計算出什麼內容繪製到什麼位置,實現最終的渲染。api
dom 是有 id、class、tagName 等標識的,邏輯的部分就經過這些標識給具體 dom 綁定一些事件處理函數,而後在函數裏面操做 dom 來實現的界面的交互。
dom api 是最終瀏覽器提供給開發者的構建 web 應用的接口,算是 web 應用的物理層。
固然,如今開發 web 應用並不會直接基於 dom api,而是會選擇某一個前端框架,好比 vue、react、angular 等。
這些框架實現了組件的功能,也就是對頁面作的邏輯的拆分,把相同功能的 html、css、js 聚合在一塊兒,使之能夠複用。而且提供了 mvvm 的功能,自動作數據到具體 dom 的映射,而再也不須要開發者手動操做 dom。
前端框架作的事情至關因而 web 應用的邏輯層,最終的渲染和交互仍是經過 dom api,可是用戶不須要直接操做,而是在邏輯層描述組件和數據,由前端框架完成數據到 dom 的自動映射。
如今的跨端方案基本都是對物理層的 dom api 作了替換,而後上層對接一個邏輯層的前端框架來支持跨端的應用開發。
css 是瀏覽器提供給開發者的描述界面的方式,而描述界面分爲兩部分:
內容繪製在什麼地方
內容怎麼繪製
內容繪製在什麼地方就是佈局的部分,主要是 display 和 position 的樣式。而內容怎麼繪製則跟具體內容相關,font、text、image 等內容都有各自的一些樣式。
本文咱們主要來探究 css 作佈局的部分。
首先,全部的內容都會有一些空白和與其餘元素的間距,因此 css 抽象出了盒模型的概念,也就是任何一個塊都是由 content、padding(空白)、border、margin(間距)這幾部分構成。
可是盒與盒之間也是有區別的,有的盒能夠在同一行顯示,有的則是獨佔一行,並且對內容的位置的計算方式也不同。因而提供了 display 樣式來設置盒類型,好比 block、inline、inline-block、flex、table-cell、grid 等,分別設置成不一樣的盒類型,就會使用不一樣的計算規則。
block 的元素會獨佔一行、能夠設置內容的寬高,具體計算規則叫作 BFC。
inline 的元素寬高由內容撐開不可設置,不會獨佔一行,具體計算規則叫作 IFC。
flex 的子元素能夠自動計算空白部分,由 flex 樣式指定分配比例,具體計算規則叫作 FFC。
grid 的子元素則是能夠拆分紅多個行列來計算位置,具體計算規則叫 GFC。
這些都是不一樣盒類型的佈局計算規則。
根據不一樣盒類型的佈局計算規則每每不夠用,不少場景下須要一些用戶自定義的佈局規則,因此 css 提供了 position 樣式,包括 static、relative、absolute、fixed、sticky。
默認盒的定位方式就是 static,也就是流式的,上個盒子顯示到什麼地方了,下個盒子就在下面繼續計算位置,顯示在什麼位置是由內容多少來決定的。
最開始的時候網頁主要是用來顯示一些文本,因此流式的位置計算規則就很方便。
流式的規則是根據上個盒子的位置自動計算出下個盒子的位置,但有的時候想作一些偏移,這種就能夠經過 relative 來指定,設置 position 爲 relative,而後經過 top、bottom、left、right 來指定如何偏移。
相對佈局給流式佈局增長一些靈活性,能夠在流式計算規則的基礎上作一些偏移。
流式的計算規則具體什麼內容顯示在什麼位置是不固定的,只適合文字、圖片等內容的佈局。可是好比一些面板須要固定下來,就在某個位置不要動,就能夠經過 position 設置爲 absolute,就能夠脫離文檔流了。這時候就能夠根據上個非流式的 position 來計算如今的 position。
absolute 是根據上一個脫離了文檔流的 position 來計算位置的,最外層的 absolute 的元素是根據窗口定位。若是想直接根據窗口來定位能夠指定 position 爲 fixed。這個時候的 top、bottom、left、right 就是相對於窗口的。
sticky 的效果在滾動的時候若是超過了必定的高度就 fixed 在一個位置,不然的話就 static。至關於基於 static 和 fixed 作的一層封裝,實現導航條吸頂效果的時候能夠直接用。
或許就是由於太經常使用,才封裝出了這樣一個 position 的屬性值吧,以前都是經過 js 監聽滾動條位置來分別設置 static 和 fixed 的。
脫離文檔流還能夠經過 float,文檔流內的塊盒會佔據一行,能夠經過 float 讓元素先脫離文檔流,再也不佔據一行,等設置完改行的樣式,再用 clear 清除浮動,讓後面的元素繼續在文檔流中佈局。
可是有了 flex 的盒以後,再也不須要這樣 float、clear 了,直接在文檔流中放個 flex 盒,flex 盒內就能夠在同一行內作彈性的佈局。
所謂的佈局就是肯定元素的位置,設置了盒的類型(display)以後對於內容如何渲染會有不一樣的規則,好比 BFC、IFC、FFC、GFC 等。
盒與盒之間默認是流式的,也就是 position 爲 static,但有的時候想在流中作下偏移,用 relative。當不想跟隨文檔流了,能夠設置 absolute 來相對於上個非 static 位置來計算一個固定的位置,若是想直接相對於窗口,就用 fixed。
當須要作吸頂效果的時候,要根據滾動位置切換 static 和 fixed,這時候 css 還有一個 sticky 的定位方式能夠直接用。
也就是說,盒內部的佈局計算規則根據 display 來肯定,還能夠用 position 作一些調整。以前塊盒須要先用 float 脫離文檔流,佈局完再 clear,如今用 flex 盒就能夠了。
講了 css 的佈局方式(也就是 display 配合 position)以後,咱們來看一個具體的案例: vscode 是如何佈局的。
vscode 是咱們常常用的 ide,它基於 electron,也就是經過網頁來繪製界面,那麼它是怎麼作佈局的呢?
vscode 分爲了標題欄、狀態欄、內容區,是上中下結構,而內容區又分爲了活動欄、側邊欄、編輯區,是左中右結構。窗口能夠調整大小,而這個上中下嵌套左中右的結構是不變的。
這種佈局如何實現呢?
css 的佈局就是 display 配合 position 來肯定每一塊內容的位置。咱們的需求是窗口放縮但每一塊的相對位置不變,這種用 absolute 的佈局就能夠實現。
首先,最外層是上中下的結構,能夠把每一塊設置爲 absolute,而後分別設置 top 值,而後中間部分由分爲了左中右,能夠再分別設置左中右部分的 left 值,這樣就完成了每一塊的佈局。
這是總體的佈局,每一塊內部則根據不一樣的佈局需求分別使用流式、彈性等不一樣的盒,配合絕對、相對等定位方式來佈局。
可是,絕對定位是要指定具體的 top、bottom、left、right 值,是靜態的,而窗口大小改變的時候須要動態的設置具體的值。這時候就須要監聽窗口的 resize 事件來從新佈局,分別計算不一樣塊的位置。
並且 vscode 每一塊的大小是也是能夠拖動改變大小的,也要在拖動的時候從新計算 left、top 的值。
現代軟件基本都是有用戶界面的,而不一樣操做系統下構建 UI 的方式不一樣,因此跨平臺渲染的瀏覽器的方案逐漸流行開來。移動互聯網時代以後,爲了綜合原生的體驗和網頁的跨平臺,出現了跨端引擎的方案,也就是基於安卓、ios 分別實現 dom api 並注入一些設備能力的 api 給 JS 引擎,業務代碼經過 dom api 來描述 UI。
dom api 是瀏覽器提供給開發者的描述 UI 的方式,是物理層。如今的前端框架能夠完成組件的封裝和數據到 dom 的映射,再也不須要直接操做 dom,算是邏輯層。
由於跨端引擎實現了 dom api,因此上層能夠對接前端框架。
UI 是經過 css 來描述的,而 css 能夠分爲兩部分: 佈局和具體元素的渲染。
具體 font、text、image 等分別有不一樣的樣式來描述如何渲染,而佈局是肯定每一個元素的位置,由 display 配合 position 來肯定。
網頁的每個內容都是一個盒,由 content、padding、border、margin 構成,而 display 是設置盒的類型,不一樣的盒有不一樣的佈局規則,好比 BFC、IFC、FFC、GFC 等。
當有一些須要定製的佈局規則,可使用 position。默認的 position 是 static,也就是流式的,根據上個盒來肯定下個盒的位置,可使用 relative 作一些偏移,若是想相對於某個位置固定,可使用 absolute,當直接相對窗口的時候使用 fixed。此外,在作吸頂效果的時候,可使用 sticky,它是基於 static 和 fixed 的封裝。
由於文檔流的侷限性,塊盒要在同一行的時候須要用 float 脫離文檔流,但有了 flex 盒以後就不用脫離了,在流中放一個 flex 盒就行,內部能夠作彈性的橫向豎向佈局。
知道了 display 和 position 都怎麼作佈局,也就是計算盒的位置之後,咱們看了下 vscode 是怎麼佈局的。
vscode 是上中下嵌套左中右的結構,窗口改變或者拖動均可以調整每塊大小,因此使用嵌套的 absolute 的方式來作總體的佈局。每一塊的內部則綜合使用流式、彈性等方式配合 position 分別作更細節的佈局。
css layout 的本質就是肯定元素的位置,以前的 css layout 能夠說是 display + float + position,如今是 display + position 就能夠了。display: flex 能夠替代 float 作到更強的佈局效果。
網頁的 css 佈局方案已經應用在愈來愈多的領域,好比跨端引擎經過安卓、ios 實現 css,kraken 基於 flutter 實現 css,因此 css 的佈局方式是咱們必須掌握的技能。但願這篇文章能幫你們梳理清楚 css 佈局的思路,對各類佈局都可以分析清楚特性,而後用合適的方案來實現。