我是一名剛畢業的程序媛,面試的崗位是前端開發工程師,從17年初找實習開始,前後面試了50多家公司,加上123面,總共經歷了上百場面試,其中包括百度,騰訊,阿里,滴滴,網易,美團等等,也面了一些中小公司的社招。javascript
總結一下面試遇到的問題,但願對你們助,本文很長很長很長(省略n個很長),可是看完的話,確實能夠加深前端基礎知識的理解,原文連接能夠跳轉(若是對您有幫助,請幫我點個star,定時更新):php
同時個人博客地址是:https://github.com/forthealll... 會定時更新一些學習心得,也歡迎star和forkcss
誤區:咱們常常說get請求參數的大小存在限制,而post請求的參數大小是無限制的。html
實際上HTTP 協議從未規定 GET/POST 的請求長度限制是多少。對get請求參數的限制是來源與瀏覽器或web服務器,瀏覽器或web服務器限制了url的長度。爲了明確這個概念,咱們必須再次強調下面幾點:前端
post/get的請求區別,具體再也不贅述。html5
補充補充一個get和post在緩存方面的區別:java
一句話能夠歸納:閉包就是可以讀取其餘函數內部變量的函數,或者子函數在外調用,子函數所在的父函數的做用域不會被釋放。node
(1)類的建立(es5):new一個function,在這個function的prototype裏面增長屬性和方法。ios
下面來建立一個Animal類:css3
// 定義一個動物類 function Animal (name) { // 屬性 this.name = name || 'Animal'; // 實例方法 this.sleep = function(){ console.log(this.name + '正在睡覺!'); } } // 原型方法 Animal.prototype.eat = function(food) { console.log(this.name + '正在吃:' + food); };
這樣就生成了一個Animal類,實力化生成對象後,有方法和屬性。
(2)類的繼承——原型鏈繼承
--原型鏈繼承 function Cat(){ } Cat.prototype = new Animal(); Cat.prototype.name = 'cat'; // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.eat('fish')); console.log(cat.sleep()); console.log(cat instanceof Animal); //true console.log(cat instanceof Cat); //true
(3)構造繼承:使用父類的構造函數來加強子類實例,等因而複製父類的實例屬性給子類(沒用到原型)
function Cat(name){ Animal.call(this); this.name = name || 'Tom'; } // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // false console.log(cat instanceof Cat); // true
(4)實例繼承和拷貝繼承
實例繼承:爲父類實例添加新特性,做爲子類實例返回
拷貝繼承:拷貝父類元素上的屬性和方法
上述兩個實用性不強,不一一舉例。
(5)組合繼承:至關於構造繼承和原型鏈繼承的組合體。經過調用父類構造,繼承父類的屬性並保留傳參的優勢,而後經過將父類實例做爲子類原型,實現函數複用
function Cat(name){ Animal.call(this); this.name = name || 'Tom'; } Cat.prototype = new Animal(); Cat.prototype.constructor = Cat; // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); // true
(6)寄生組合繼承:經過寄生方式,砍掉父類的實例屬性,這樣,在調用兩次父類的構造的時候,就不會初始化兩次實例方法/屬性
function Cat(name){ Animal.call(this); this.name = name || 'Tom'; } (function(){ // 建立一個沒有實例方法的類 var Super = function(){}; Super.prototype = Animal.prototype; //將實例做爲子類的原型 Cat.prototype = new Super(); })(); // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); //true
promise、generator、async/await
HTML中與javascript交互是經過事件驅動來實現的,例如鼠標點擊事件onclick、頁面的滾動事件onscroll等等,能夠向文檔或者文檔中的元素添加事件偵聽器來預訂事件。想要知道這些事件是在何時進行調用的,就須要瞭解一下「事件流」的概念。
什麼是事件流:事件流描述的是從頁面中接收事件的順序,DOM2級事件流包括下面幾個階段。
addEventListener:addEventListener 是DOM2 級事件新增的指定事件處理程序的操做,這個方法接收3個參數:要處理的事件名、做爲事件處理程序的函數和一個布爾值。最後這個布爾值參數若是是true,表示在捕獲階段調用事件處理程序;若是是false,表示在冒泡階段調用事件處理程序。
IE只支持事件冒泡。
在DOM標準事件模型中,是先捕獲後冒泡。可是若是要實現先冒泡後捕獲的效果,對於同一個事件,監聽捕獲和冒泡,分別對應相應的處理函數,監聽到捕獲事件,先暫緩執行,直到冒泡事件被捕獲後再執行捕獲之間。
兩種技術的本質:二者的行爲是相反的,一個是提早加載,一個是遲緩甚至不加載。
懶加載對服務器前端有必定的緩解壓力做用,預加載則會增長服務器前端壓力。
new 操做符新建了一個空對象,這個對象原型指向構造函數的prototype,執行構造函數後返回這個對象。
當鼠標點擊按下的時候,須要一個tag標識此時已經按下,能夠執行mousemove裏面的具體方法。
鼠標移動時候的座標-鼠標按下去時候的座標。
也就是說定位信息爲:
鼠標移動時候的座標-鼠標按下去時候的座標+元素初始狀況下的offetLeft.
補充:也能夠經過html5的拖放(Drag 和 drop)來實現
原理:經過apply或者call方法來實現。
Function.prototype.bind=function(obj,arg){ var arg=Array.prototype.slice.call(arguments,1); var context=this; return function(newArg){ arg=arg.concat(Array.prototype.slice.call(newArg)); return context.apply(obj,arg); } }
爲何要考慮?由於在new 一個bind過生成的新函數的時候,必須的條件是要繼承原函數的原型
Function.prototype.bind=function(obj,arg){ var arg=Array.prototype.slice.call(arguments,1); var context=this; var bound=function(newArg){ arg=arg.concat(Array.prototype.slice.call(newArg)); return context.apply(obj,arg); } var F=function(){} //這裏須要一個寄生組合繼承 F.prototype=context.prototype; bound.prototype=new F(); return bound; }
首先來看setInterval的缺陷,使用setInterval()建立的定時器確保了定時器代碼規則地插入隊列中。這個問題在於:若是定時器代碼在代碼再次添加到隊列以前還沒完成執行,結果就會致使定時器代碼連續運行好幾回。而之間沒有間隔。不過幸運的是:javascript引擎足夠聰明,可以避免這個問題。當且僅當沒有該定時器的如何代碼實例時,纔會將定時器代碼添加到隊列中。這確保了定時器代碼加入隊列中最小的時間間隔爲指定時間。
這種重複定時器的規則有兩個問題:1.某些間隔會被跳過 2.多個定時器的代碼執行時間可能會比預期小。
下面舉例子說明:
假設,某個onclick事件處理程序使用啦setInterval()來設置了一個200ms的重複定時器。若是事件處理程序花了300ms多一點的時間完成。
<img width="626" alt="2018-07-10 11 36 43" src="https://user-gold-cdn.xitu.io...;h=498&f=png&s=326047">
這個例子中的第一個定時器是在205ms處添加到隊列中,可是要過300ms才能執行。在405ms又添加了一個副本。在一個間隔,605ms處,第一個定時器代碼還在執行中,並且隊列中已經有了一個定時器實例,結果是605ms的定時器代碼不會添加到隊列中。結果是在5ms處添加的定時器代碼執行結束後,405處的代碼當即執行。
function say(){ //something setTimeout(say,200); } setTimeout(say,200)
或者
setTimeout(function(){ //do something setTimeout(arguments.callee,200); },200);
<script type="text/javascript"> var obj=new Image(); obj.src="http://www.phpernote.com/uploadfiles/editor/201107240502201179.jpg"; obj.onload=function(){ alert('圖片的寬度爲:'+obj.width+';圖片的高度爲:'+obj.height); document.getElementById("mypic").innnerHTML="<img src='"+this.src+"' />"; } </script> <div id="mypic">onloading……</div>
<script type="text/javascript"> var obj=new Image(); obj.src="http://www.phpernote.com/uploadfiles/editor/201107240502201179.jpg"; obj.onreadystatechange=function(){ if(this.readyState=="complete"){ alert('圖片的寬度爲:'+obj.width+';圖片的高度爲:'+obj.height); document.getElementById("mypic").innnerHTML="<img src='"+this.src+"' />"; } } </script> <div id="mypic">onloading……</div>
setTimeout(function(){console.log(1)},0); new Promise(function(resolve,reject){ console.log(2); resolve(); }).then(function(){console.log(3) }).then(function(){console.log(4)}); process.nextTick(function(){console.log(5)}); console.log(6); //輸出2,6,5,3,4,1
爲何呢?具體請參考個人文章:[
從promise、process.nextTick、setTimeout出發,談談Event Loop中的Job queue](https://github.com/forthealll...
function sleep(ms){ var start=Date.now(),expire=start+ms; while(Date.now()<expire); console.log('1111'); return; }
執行sleep(1000)以後,休眠了1000ms以後輸出了1111。上述循環的方式缺點很明顯,容易形成死循環。
function sleep(ms){ var temple=new Promise( (resolve)=>{ console.log(111);setTimeout(resolve,ms) }); return temple } sleep(500).then(function(){ //console.log(222) }) //先輸出了111,延遲500ms後輸出222
function sleep(ms){ return new Promise((resolve)=>setTimeout(resolve,ms)); } async function test(){ var temple=await sleep(1000); console.log(1111) return temple } test(); //延遲1000ms輸出了1111
function* sleep(ms){ yield new Promise(function(resolve,reject){ console.log(111); setTimeout(resolve,ms); }) } sleep(500).next().value.then(function(){console.log(2222)})
首先明確什麼是promiseA+規範,參考規範的地址:
如何實現一個promise,參考個人文章:
通常不會問的很詳細,只要能寫出上述文章中的v1.0版本的簡單promise便可。
獲取一個對象的原型,在chrome中能夠經過__proto__的形式,或者在ES6中能夠經過Object.getPrototypeOf的形式。
那麼Function.proto是什麼麼?也就是說Function由什麼對象繼承而來,咱們來作以下判別。
Function.__proto__==Object.prototype //false Function.__proto__==Function.prototype//true
咱們發現Function的原型也是Function。
咱們用圖能夠來明確這個關係:
<img width="646" alt="2018-07-10 2 38 27" src="https://user-gold-cdn.xitu.io...;h=1028&f=png&s=183106">
經過遞歸能夠簡單實現對象的深度克隆,可是這種方法無論是ES6仍是ES5實現,都有一樣的缺陷,就是隻能實現特定的object的深度複製(好比數組和函數),不能實現包裝對象Number,String , Boolean,以及Date對象,RegExp對象的複製。
function deepClone(obj){ var newObj= obj instanceof Array?[]:{}; for(var i in obj){ newObj[i]=typeof obj[i]=='object'? deepClone(obj[i]):obj[i]; } return newObj; }
這種方法能夠實現通常對象和數組對象的克隆,好比:
var arr=[1,2,3]; var newArr=deepClone(arr); // newArr->[1,2,3] var obj={ x:1, y:2 } var newObj=deepClone(obj); // newObj={x:1,y:2}
可是不能實現例如包裝對象Number,String,Boolean,以及正則對象RegExp和Date對象的克隆,好比:
//Number包裝對象 var num=new Number(1); typeof num // "object" var newNum=deepClone(num); //newNum -> {} 空對象 //String包裝對象 var str=new String("hello"); typeof str //"object" var newStr=deepClone(str); //newStr-> {0:'h',1:'e',2:'l',3:'l',4:'o'}; //Boolean包裝對象 var bol=new Boolean(true); typeof bol //"object" var newBol=deepClone(bol); // newBol ->{} 空對象 ....
全部對象都有valueOf方法,valueOf方法對於:若是存在任意原始值,它就默認將對象轉換爲表示它的原始值。對象是複合值,並且大多數對象沒法真正表示爲一個原始值,所以默認的valueOf()方法簡單地返回對象自己,而不是返回一個原始值。數組、函數和正則表達式簡單地繼承了這個默認方法,調用這些類型的實例的valueOf()方法只是簡單返回這個對象自己。
對於原始值或者包裝類:
function baseClone(base){ return base.valueOf(); } //Number var num=new Number(1); var newNum=baseClone(num); //newNum->1 //String var str=new String('hello'); var newStr=baseClone(str); // newStr->"hello" //Boolean var bol=new Boolean(true); var newBol=baseClone(bol); //newBol-> true
其實對於包裝類,徹底能夠用=號來進行克隆,其實沒有深度克隆一說,
這裏用valueOf實現,語法上比較符合規範。
對於Date類型:
由於valueOf方法,日期類定義的valueOf()方法會返回它的一個內部表示:1970年1月1日以來的毫秒數.所以咱們能夠在Date的原型上定義克隆的方法:
Date.prototype.clone=function(){ return new Date(this.valueOf()); } var date=new Date('2010'); var newDate=date.clone(); // newDate-> Fri Jan 01 2010 08:00:00 GMT+0800
對於正則對象RegExp:
RegExp.prototype.clone = function() { var pattern = this.valueOf(); var flags = ''; flags += pattern.global ? 'g' : ''; flags += pattern.ignoreCase ? 'i' : ''; flags += pattern.multiline ? 'm' : ''; return new RegExp(pattern.source, flags); }; var reg=new RegExp('/111/'); var newReg=reg.clone(); //newReg-> /\/111\//
簡介:觀察者模式或者說訂閱模式,它定義了對象間的一種一對多的關係,讓多個觀察者對象同時監聽某一個主題對象,當一個對象發生改變時,全部依賴於它的對象都將獲得通知。
node中的Events模塊就是經過觀察者模式來實現的:
var events=require('events'); var eventEmitter=new events.EventEmitter(); eventEmitter.on('say',function(name){ console.log('Hello',name); }) eventEmitter.emit('say','Jony yu');
這樣,eventEmitter發出say事件,經過On接收,而且輸出結果,這就是一個訂閱模式的實現,下面咱們來簡單的實現一個Events模塊的EventEmitter。
function Events(){ this.on=function(eventName,callBack){ if(!this.handles){ this.handles={}; } if(!this.handles[eventName]){ this.handles[eventName]=[]; } this.handles[eventName].push(callBack); } this.emit=function(eventName,obj){ if(this.handles[eventName]){ for(var i=0;o<this.handles[eventName].length;i++){ this.handles[eventName][i](obj); } } } return this; }
這樣咱們就定義了Events,如今咱們能夠開始來調用:
var events=new Events(); events.on('say',function(name){ console.log('Hello',nama) }); events.emit('say','Jony yu'); //結果就是經過emit調用以後,輸出了Jony yu
由於是經過new的方式,每次生成的對象都是不相同的,所以:
var event1=new Events(); var event2=new Events(); event1.on('say',function(){ console.log('Jony event1'); }); event2.on('say',function(){ console.log('Jony event2'); }) event1.emit('say'); event2.emit('say'); //event一、event2之間的事件監聽互相不影響 //輸出結果爲'Jony event1' 'Jony event2'
var a=11; function test2(){ this.a=22; let b=()=>{console.log(this.a)} b(); } var x=new test2(); //輸出22
定義時綁定。
https的SSL加密是在傳輸層實現的。
http: 超文本傳輸協議,是互聯網上應用最爲普遍的一種網絡協議,是一個客戶端和服務器端請求和應答的標準(TCP),用於從WWW服務器傳輸超文本到本地瀏覽器的傳輸協議,它可使瀏覽器更加高效,使網絡傳輸減小。
https: 是以安全爲目標的HTTP通道,簡單講是HTTP的安全版,即HTTP下加入SSL層,HTTPS的安全基礎是SSL,所以加密的詳細內容就須要SSL。
https協議的主要做用是:創建一個信息安全通道,來確保數組的傳輸,確保網站的真實性。
http傳輸的數據都是未加密的,也就是明文的,網景公司設置了SSL協議來對http協議傳輸的數據進行加密處理,簡單來講https協議是由http和ssl協議構建的可進行加密傳輸和身份認證的網絡協議,比http協議的安全性更高。
主要的區別以下:
客戶端在使用HTTPS方式與Web服務器通訊時有如下幾個步驟,如圖所示。
客戶端和服務端都須要直到各自可收發,所以須要三次握手。
簡化三次握手:
<img width="487" alt="2018-07-10 3 42 11" src="https://user-gold-cdn.xitu.io...;h=1038&f=png&s=94703">
從圖片能夠獲得三次握手能夠簡化爲:C發起請求鏈接S確認,也發起鏈接C確認咱們再看看每次握手的做用:第一次握手:S只能夠確認 本身能夠接受C發送的報文段第二次握手:C能夠確認 S收到了本身發送的報文段,而且能夠確認 本身能夠接受S發送的報文段第三次握手:S能夠確認 C收到了本身發送的報文段
(1)TCP是面向鏈接的,udp是無鏈接的即發送數據前不須要先創建連接。
(2)TCP提供可靠的服務。也就是說,經過TCP鏈接傳送的數據,無差錯,不丟失,不重複,且按序到達;UDP盡最大努力交付,即不保證可靠交付。 而且由於tcp可靠,面向鏈接,不會丟失數據所以適合大數據量的交換。
(3)TCP是面向字節流,UDP面向報文,而且網絡出現擁塞不會使得發送速率下降(所以會出現丟包,對實時的應用好比IP電話和視頻會議等)。
(4)TCP只能是1對1的,UDP支持1對1,1對多。
(5)TCP的首部較大爲20字節,而UDP只有8字節。
(6)TCP是面向鏈接的可靠性傳輸,而UDP是不可靠的。
WebSocket是HTML5中的協議,支持持久連續,http協議不支持持久性鏈接。Http1.0和HTTP1.1都不支持持久性的連接,HTTP1.1中的keep-alive,將多個http請求合併爲1個
基本請求以下:
GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13 Origin: http://example.com
多了下面2個屬性:
Upgrade:webSocket Connection:Upgrade 告訴服務器發送的是websocket Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13
請求的返回頭裏面,用於瀏覽器解析的重要參數就是OSS的API文檔裏面的返回http頭,決定用戶下載行爲的參數。
下載的狀況下:
1. x-oss-object-type: Normal 2. x-oss-request-id: 598D5ED34F29D01FE2925F41 3. x-oss-storage-class: Standard
可以被殘障人士使用的網站才能稱得上一個易用的(易訪問的)網站。
殘障人士指的是那些帶有殘疾或者身體不健康的用戶。
使用alt屬性:
<img src="person.jpg" alt="this is a person"/>
有時候瀏覽器會沒法顯示圖像。具體的緣由有:
若是您使用了 alt 屬性,那麼瀏覽器至少能夠顯示或讀出有關圖像的描述。
什麼是Bom? Bom是瀏覽器對象。有哪些經常使用的Bom屬性呢?
location.href-- 返回或設置當前文檔的URL
location.search -- 返回URL中的查詢字符串部分。例如 http://www.dreamdu.com/dreamd... 返回包括(?)後面的內容?id=5&name=dreamdu
location.hash -- 返回URL#後面的內容,若是沒有#,返回空
location.host -- 返回URL中的域名部分,例如www.dreamdu.com
location.hostname -- 返回URL中的主域名部分,例如dreamdu.com
location.pathname -- 返回URL的域名後的部分。例如 http://www.dreamdu.com/xhtml/ 返回/xhtml/
location.port -- 返回URL中的端口部分。例如 http://www.dreamdu.com:8080/xhtml/ 返回8080
location.protocol -- 返回URL中的協議部分。例如 http://www.dreamdu.com:8080/xhtml/ 返回(//)前面的內容http:
location.assign -- 設置當前文檔的URL
location.replace() -- 設置當前文檔的URL,而且在history對象的地址列表中移除這個URL location.replace(url);
location.reload() -- 重載當前頁面
history.go() -- 前進或後退指定的頁面數 history.go(num);
history.back() -- 後退一頁
history.forward() -- 前進一頁
navigator.userAgent -- 返回用戶代理頭的字符串表示(就是包括瀏覽器版本信息等的字符串)
navigator.cookieEnabled -- 返回瀏覽器是否支持(啓用)cookie
首先補充一下,http和https的區別,相比於http,https是基於ssl加密的http協議
簡要歸納:http2.0是基於1999年發佈的http1.0以後的首次更新。
產生緣由:
解決方法:
fetch發送post請求的時候,老是發送2次,第一次狀態碼是204,第二次才成功?
緣由很簡單,由於你用fetch的post請求的時候,致使fetch 第一次發送了一個Options請求,詢問服務器是否支持修改的請求頭,若是服務器支持,則在第二次中發送真正的請求。
共同點:都是保存在瀏覽器端,而且是同源的
補充說明一下cookie的做用:
在HTML頁面中,若是在執行腳本時,頁面的狀態是不可相應的,直到腳本執行完成後,頁面才變成可相應。web worker是運行在後臺的js,獨立於其餘腳本,不會影響頁面你的性能。而且經過postMessage將結果回傳到主線程。這樣在進行復雜操做的時候,就不會阻塞主線程了。
如何建立web worker:
HTML5語義化標籤是指正確的標籤包含了正確的內容,結構良好,便於閱讀,好比nav表示導航條,相似的還有article、header、footer等等標籤。
定義:iframe元素會建立包含另外一個文檔的內聯框架
提示:能夠將提示文字放在<iframe></iframe>之間,來提示某些不支持iframe的瀏覽器
缺點:
Doctype聲明於文檔最前面,告訴瀏覽器以何種方式來渲染頁面,這裏有兩種模式,嚴格模式和混雜模式。
XSS(跨站腳本攻擊)是指攻擊者在返回的HTML中嵌入javascript腳本,爲了減輕這些攻擊,須要在HTTP頭部配上,set-cookie:
結果應該是這樣的:Set-Cookie=<cookie-value>.....
HTTP是一個無狀態協議,所以Cookie的最大的做用就是存儲sessionId用來惟一標識用戶
就是用URL定位資源,用HTTP描述操做
能夠參考個人這篇文章:
響應式佈局的經常使用解決方案對比(媒體查詢、百分比、rem和vw/vh)
<meta name="viewport" content="width=device-width, user-scalable=no">
檢測到touchend事件後,馬上出發模擬click事件,而且把瀏覽器300毫秒以後真正出發的事件給阻斷掉
簡介:就是用來裝頁面上的元素的矩形區域。CSS中的盒子模型包括IE盒子模型和標準的W3C盒子模型。
border-sizing(有3個值哦):border-box,padding-box,content-box.
<img width="624" alt="2018-07-10 4 24 03" src="https://user-gold-cdn.xitu.io...;h=686&f=png&s=963248">
<img width="620" alt="2018-07-10 4 24 12" src="https://user-gold-cdn.xitu.io...;h=656&f=png&s=1023920">
區別:從圖中咱們能夠看出,這兩種盒子模型最主要的區別就是width的包含範圍,在標準的盒子模型中,width指content部分的寬度,在IE盒子模型中,width表示content+padding+border這三個部分的寬度,故這使得在計算整個盒子的寬度時存在着差別:
標準盒子模型的盒子寬度:左右border+左右padding+width
IE盒子模型的盒子寬度:width
在CSS3中引入了box-sizing屬性,box-sizing:content-box;表示標準的盒子模型,box-sizing:border-box表示的是IE盒子模型
最後,前面咱們還提到了,box-sizing:padding-box,這個屬性值的寬度包含了左右padding+width
也很好理解性記憶,包含什麼,width就從什麼開始算起。
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
Animation和transition大部分屬性是相同的,他們都是隨時間改變元素的屬性值,他們的主要區別是transition須要觸發一個事件才能改變屬性,而animation不須要觸發任何事件的狀況下才會隨時間改變屬性值,而且transition爲2幀,從from .... to,而animation能夠一幀一幀的。
文章連接:
http://www.ruanyifeng.com/blo...(語法篇)
http://www.ruanyifeng.com/blo...(實例篇)
Flex是Flexible Box的縮寫,意爲"彈性佈局",用來爲盒狀模型提供最大的靈活性。
佈局的傳統解決方案,基於盒狀模型,依賴 display屬性 + position屬性 + float屬性。它對於那些特殊佈局很是不方便,好比,垂直居中就不容易實現。
簡單的分爲容器屬性和元素屬性
容器的屬性:
.box {
flex-direction: row | row-reverse | column | column-reverse;
}
.box{
flex-wrap: nowrap | wrap | wrap-reverse;
}
.box {
flex-flow: <flex-direction> || <flex-wrap>;
}
項目的屬性(元素的屬性):
好比說,用flex實現聖盃佈局
直譯成:塊級格式化上下文,是一個獨立的渲染區域,而且有必定的佈局規則。
那些元素會生成BFC:
css:
div{ width: 400px; height: 400px; position: relative; border: 1px solid #465468; } img{ position: absolute; margin: auto; top: 0; left: 0; right: 0; bottom: 0; }
html:
<div> <img src="mm.jpg"> </div>
定位爲上下左右爲0,margin:0能夠實現脫離文檔流的居中.
.container{ width: 500px; height: 400px; border: 2px solid #379; position: relative; } .inner{ width: 480px; height: 380px; background-color: #746; position: absolute; top: 50%; left: 50%; margin-top: -190px; /*height的一半*/ margin-left: -240px; /*width的一半*/ }
補充:其實這裏也能夠將marin-top和margin-left負值替換成,
transform:translateX(-50%)和transform:translateY(-50%)
設置父元素的display:table-cell,而且vertical-align:middle,這樣子元素能夠實現垂直居中。
css: div{ width: 300px; height: 300px; border: 3px solid #555; display: table-cell; vertical-align: middle; text-align: center; } img{ vertical-align: middle; }
將父元素設置爲display:flex,而且設置align-items:center;justify-content:center;
css: .container{ width: 300px; height: 200px; border: 3px solid #546461; display: -webkit-flex; display: flex; -webkit-align-items: center; align-items: center; -webkit-justify-content: center; justify-content: center; } .inner{ border: 3px solid #458761; padding: 20px; }
渲染線程分爲main thread和compositor thread,若是css動畫只改變transform和opacity,這時整個CSS動畫得以在compositor trhead完成(而js動畫則會在main thread執行,而後出發compositor thread進行下一步操做),特別注意的是若是改變transform和opacity是不會layout或者paint的。
區別:
塊元素:獨佔一行,而且有自動填滿父元素,能夠設置margin和pading以及高度和寬度
行元素:不會獨佔一行,width和height會失效,而且在垂直方向的padding和margin會失
效。
display: -webkit-box -webkit-box-orient:vertical -web-line-clamp:3 overflow:hidden
opacity=0,該元素隱藏起來了,但不會改變頁面佈局,而且,若是該元素已經綁定一些事件,如click事件,那麼點擊該區域,也能觸發點擊事件的visibility=hidden,該元素隱藏起來了,但不會改變頁面佈局,可是不會觸發該元素已經綁定的事件display=none,把元素隱藏起來,而且會改變頁面佈局,能夠理解成在頁面中把該元素刪除掉同樣。
多個相鄰(兄弟或者父子關係)普通流的塊元素垂直方向marigin會重疊
摺疊的結果爲:
兩個相鄰的外邊距都是正數時,摺疊結果是它們二者之間較大的值。兩個相鄰的外邊距都是負數時,摺疊結果是二者絕對值的較大值。兩個外邊距一正一負時,摺疊結果是二者的相加的和。