小蘑菇

小蘑菇 查看完整檔案

填寫現居城市  |  填寫畢業院校  |  填寫所在公司/組織填寫個人主網站
編輯
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 個人簡介什么都沒有

個人動態

小蘑菇 發布了文章 · 3月1日

JS 文件base64、File、Blob、ArrayBuffer互轉

二進制互轉

1. file對象轉base64

 let reader = new FileReader();
 reader.readAsDataURL(file[0])
 console.log(reader)

2. base64 轉成blob 上傳

function dataURItoBlob(dataURI) {  
    var byteString = atob(dataURI.split(',')[1]);  
    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];  
    var ab = new ArrayBuffer(byteString.length);  
    var ia = new Uint8Array(ab);  
    for (var i = 0; i < byteString.length; i++) {  
        ia[i] = byteString.charCodeAt(i);  
    }  
    return new Blob([ab], {type: mimeString});  
}

3. blob 轉成ArrayBuffer

let blob = new Blob([1,2,3,4])
let reader = new FileReader();
reader.onload = function(result) {
    console.log(result);
}
reader.readAsArrayBuffer(blob);

4. buffer 轉成blob

let blob = new Blob([buffer])

5. base64 轉 file

const base64ConvertFile = function (urlData, filename) { // 64轉file
  if (typeof urlData != 'string') {
    this.$toast("urlData不是字符串")
    return;
  }
  var arr = urlData.split(',')
  var type = arr[0].match(/:(.*?);/)[1]
  var fileExt = type.split('/')[1]
  var bstr = atob(arr[1])
  var n = bstr.length
  var u8arr = new Uint8Array(n)
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new File([u8arr], 'filename.' + fileExt, {
    type: type
  });
}
查看原文

贊 33 收藏 28 評論 0

小蘑菇 發布了文章 · 3月1日

js深拷貝和淺拷貝及其實現方式

淺拷貝

var m = { a: 10, b: 20 }
var n = m; 
n.a = 15; // 這時m.a的值是多少

m.a會輸出15,因為這是淺拷貝,n和m指向的是同一個堆,對象復制只是復制的對象的引用。

深拷貝

var m = { a: 10, b: 20 } 
var n = {a:m.a,b:m.b}; 
n.a = 15;

深拷貝和上面淺拷貝不同,就是徹底copy一個對象,而不是copy對象的引用。
這次,我們再來輸出m.a ,發現m.a的值還是10,并沒有改變,m對象和n對象是雖然所有的值都是一樣的,但是在堆里面,對應的不是同一個了,這個就是深拷貝。

深拷貝和淺拷貝

深拷貝和淺拷貝的示意圖大致如下:

image.png

淺拷貝只復制指向某個對象的指針,而不復制對象本身,新舊對象還是共享同一塊內存。但深拷貝會另外創造一個一模一樣的對象,新對象跟原對象不共享內存,修改新對象不會改到原對象。

淺拷貝的實現方式

1、可以通過簡單的賦值實現

function simpleClone(initalObj) { 
    var obj = {}; 
    for ( var i in initalObj) { 
        obj[i] = initalObj[i]; 
    } 
    return obj; 
} 
var obj = { 
    a: "hello", 
    b:{ a: "world", b: 21 }, 
    c:["Bob", "Tom", "Jenny"], 
    d:function() { 
        alert("hello world"); 
    } 
} 
var cloneObj = simpleClone(obj); 
console.log(cloneObj.b); 
console.log(cloneObj.c); 
console.log(cloneObj.d); 
cloneObj.b.a = "changed"; 
cloneObj.c = [1, 2, 3]; 
cloneObj.d = function() { 
    alert("changed"); 
}; 
console.log(obj.b); 
console.log(obj.c); 
console.log(obj.d);

2、Object.assign()實現

Object.assign() 方法可以把任意多個的源對象自身的可枚舉屬性拷貝給目標對象,然后返回目標對象。但是 Object.assign() 進行的是淺拷貝,拷貝的是對象的屬性的引用,而不是對象本身。

var obj = { a: {a: "hello", b: 21} };
var initalObj = Object.assign({}, obj);
initalObj.a.a = "changed";
console.log(obj.a.a); //  "changed"

注意:當object只有一層的時候,是深拷貝,例如如下:

var obj1 = { a: 10, b: 20, c: 30 };
var obj2 = Object.assign({}, obj1);
obj2.b = 100;
console.log(obj1);
// { a: 10, b: 20, c: 30 } <-- 沒被改到
console.log(obj2);
// { a: 10, b: 100, c: 30 }

3、函數庫lodash的_.clone方法

該函數庫也有提供_.clone用來做 Shallow Copy,后面我們會再介紹利用這個庫實現深拷貝。

var _ = require('lodash');
var obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};
var obj2 = _.clone(obj1);
console.log(obj1.b.f === obj2.b.f);// true

4、展開運算符...

展開運算符是一個 es6 / es2015特性,它提供了一種非常方便的方式來執行淺拷貝,這與 Object.assign ()的功能相同。

let obj1 = { name: 'Kobe', address:{x:100,y:100}}
let obj2= {... obj1}
obj1.address.x = 200;
obj1.name = 'wade'
console.log('obj2',obj2) // obj2 { name: 'Kobe', address: { x: 200, y: 100 } }

5、Array.prototype.concat()

let arr = [1, 3, {
    username: 'kobe'
    }];
let arr2 = arr.concat();    
arr2[2].username = 'wade';
console.log(arr); //[ 1, 3, { username: 'wade' } ]

6、Array.prototype.slice()

let arr = [1, 3, {
    username: ' kobe'
    }];
let arr3 = arr.slice();
arr3[2].username = 'wade'
console.log(arr); // [ 1, 3, { username: 'wade' } ]

深拷貝的實現方式

1、方法一還是手動復制

和上面的舉例一樣,手動復制可以實現深拷貝。

2、對象只有一層的話可以使用上面的:Object.assign()函數

3、轉成 JSON 再轉回來

var obj1 = { body: { a: 10 } };
var obj2 = JSON.parse(JSON.stringify(obj1));
obj2.body.a = 20;
console.log(obj1);
// { body: { a: 10 } } <-- 沒被改到
console.log(obj2);
// { body: { a: 20 } }
console.log(obj1 === obj2);
// false
console.log(obj1.body === obj2.body);
// false

用JSON.stringify把對象轉成字符串,再用JSON.parse把字符串轉成新的對象。

可以封裝如下函數

var cloneObj = function(obj){
    var str, newobj = obj.constructor === Array ? [] : {};
    if(typeof obj !== 'object'){
        return;
    } else if(window.JSON){
        str = JSON.stringify(obj), //系列化對象
        newobj = JSON.parse(str); //還原
    } else {
        for(var i in obj){
            newobj[i] = typeof obj[i] === 'object' ? 
            cloneObj(obj[i]) : obj[i]; 
        }
    }
    return newobj;
};

4、函數庫lodash的_.cloneDeep方法

該函數庫也有提供_.cloneDeep用來做 Deep Copy

var _ = require('lodash');
var obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};
var obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f);// false

5、遞歸拷貝

function deepClone(initalObj, finalObj) {    
  var obj = finalObj || {};    
  for (var i in initalObj) {        
    var prop = initalObj[i];        // 避免相互引用對象導致死循環,如initalObj.a = initalObj的情況
    if(prop === obj) {            
      continue;
    }        
    if (typeof prop === 'object') {
      obj[i] = (prop.constructor === Array) ? [] : {};            
      arguments.callee(prop, obj[i]);
    } else {
      obj[i] = prop;
    }
  }    
  return obj;
}
var str = {};
var obj = { a: {a: "hello", b: 21} };
deepClone(obj, str);
console.log(str.a);

6、使用Object.create()方法

直接使用var newObj = Object.create(oldObj),可以達到深拷貝的效果。

function deepClone(initalObj, finalObj) {    
  var obj = finalObj || {};    
  for (var i in initalObj) {        
    var prop = initalObj[i];        // 避免相互引用對象導致死循環,如initalObj.a = initalObj的情況
    if(prop === obj) {            
      continue;
    }        
    if (typeof prop === 'object') {
      obj[i] = (prop.constructor === Array) ? [] : Object.create(prop);
    } else {
      obj[i] = prop;
    }
  }    
  return obj;
}

7、jquery

jquery 有提供一個$.extend可以用來做 Deep Copy。

var $ = require('jquery');
var obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};
var obj2 = $.extend(true, {}, obj1);
console.log(obj1.b.f === obj2.b.f);
// false

8、lodash

另外一個很熱門的函數庫lodash,也有提供_.cloneDeep用來做 Deep Copy。

var _ = require('lodash');
var obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};
var obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f);
// false
查看原文

贊 9 收藏 9 評論 0

小蘑菇 發布了文章 · 2月18日

常用的前端JavaScript方法封裝

1、輸入一個值,返回其數據類型
function type(para) {
    return Object.prototype.toString.call(para)
}
2、數組去重
function unique1(arr) {
    return [...new Set(arr)]
}

function unique2(arr) {
    var obj = {};
    return arr.filter(ele => {
        if (!obj[ele]) {
            obj[ele] = true;
            return true;
        }
    })
}

function unique3(arr) {
    var result = [];
    arr.forEach(ele => {
        if (result.indexOf(ele) == -1) {
            result.push(ele)
        }
    })
    return result;
}
3、字符串去重
String.prototype.unique = function () {
    var obj = {},
        str = '',
        len = this.length;
    for (var i = 0; i < len; i++) {
        if (!obj[this[i]]) {
            str += this[i];
            obj[this[i]] = true;
        }
    }
    return str;
}

###### //去除連續的字符串 
function uniq(str) {
    return str.replace(/(\w)\1+/g, '$1')
}
4、深拷貝 淺拷貝
//深克?。ㄉ羁寺〔豢紤]函數)
function deepClone(obj, result) {
    var result = result || {};
    for (var prop in obj) {
        if (obj.hasOwnProperty(prop)) {
            if (typeof obj[prop] == 'object' && obj[prop] !== null) {
                // 引用值(obj/array)且不為null
                if (Object.prototype.toString.call(obj[prop]) == '[object Object]') {
                    // 對象
                    result[prop] = {};
                } else {
                    // 數組
                    result[prop] = [];
                }
                deepClone(obj[prop], result[prop])
    } else {
        // 原始值或func
        result[prop] = obj[prop]
    }
  }
}
return result;
}

// 深淺克隆是針對引用值
function deepClone(target) {
    if (typeof (target) !== 'object') {
        return target;
    }
    var result;
    if (Object.prototype.toString.call(target) == '[object Array]') {
        // 數組
        result = []
    } else {
        // 對象
        result = {};
    }
    for (var prop in target) {
        if (target.hasOwnProperty(prop)) {
            result[prop] = deepClone(target[prop])
        }
    }
    return result;
}
// 無法復制函數
var o1 = jsON.parse(jsON.stringify(obj1));
5、reverse底層原理和擴展
// 改變原數組
Array.prototype.myReverse = function () {
    var len = this.length;
    for (var i = 0; i < len; i++) {
        var temp = this[i];
        this[i] = this[len - 1 - i];
        this[len - 1 - i] = temp;
    }
    return this;
}
6、圣杯模式的繼承
function inherit(Target, Origin) {
    function F() {};
    F.prototype = Origin.prototype;
    Target.prototype = new F();
    Target.prototype.constructor = Target;
    // 最終的原型指向
    Target.prop.uber = Origin.prototype;
}
7、找出字符串中第一次只出現一次的字母
String.prototype.firstAppear = function () {
    var obj = {},
        len = this.length;
    for (var i = 0; i < len; i++) {
        if (obj[this[i]]) {
            obj[this[i]]++;
        } else {
            obj[this[i]] = 1;
        }
    }
    for (var prop in obj) {
       if (obj[prop] == 1) {
         return prop;
       }
    }
}
8、找元素的第n級父元素
function parents(ele, n) {
    while (ele && n) {
        ele = ele.parentElement ? ele.parentElement : ele.parentNode;
        n--;
    }
    return ele;
}
9、?返回元素的第n個兄弟節點
function retSibling(e, n) {
    while (e && n) {
        if (n > 0) {
            if (e.nextElementSibling) {
                e = e.nextElementSibling;
            } else {
                for (e = e.nextSibling; e && e.nodeType !== 1; e = e.nextSibling);
            }
            n--;
        } else {
            if (e.previousElementSibling) {
                e = e.previousElementSibling;
            } else {
                for (e = e.previousElementSibling; e && e.nodeType !== 1; e = e.previousElementSibling);
            }
            n++;
        }
    }
    return e;
}
10、封裝mychildren,解決瀏覽器的兼容問題
function myChildren(e) {
    var children = e.childNodes,
        arr = [],
        len = children.length;
    for (var i = 0; i < len; i++) {
        if (children[i].nodeType === 1) {
            arr.push(children[i])
        }
    }
    return arr;
}
11、判斷元素有沒有子元素
function hasChildren(e) {
    var children = e.childNodes,
        len = children.length;
    for (var i = 0; i < len; i++) {
        if (children[i].nodeType === 1) {
            return true;
        }
    }
    return false;
}
12、我一個元素插入到另一個元素的后面
Element.prototype.insertAfter = function (target, elen) {
    var nextElen = elen.nextElenmentSibling;
    if (nextElen == null) {
        this.appendChild(target);
    } else {
        this.insertBefore(target, nextElen);
    }
}
13、返回當前的時間(年月日時分秒)
function getDateTime() {
    var date = new Date(),
        year = date.getFullYear(),
        month = date.getMonth() + 1,
        day = date.getDate(),
        hour = date.getHours() + 1,
        minute = date.getMinutes(),
        second = date.getSeconds();
        month = checkTime(month);
        day = checkTime(day);
        hour = checkTime(hour);
        minute = checkTime(minute);
        second = checkTime(second);
     function checkTime(i) {
        if (i < 10) {
                i = "0" + i;
       }
      return i;
    }
    return "" + year + "年" + month + "月" + day + "日" + hour + "時" + minute + "分" + second + "秒"
}
14、獲得滾動條的滾動距離
function getScrollOffset() {
    if (window.pageXOffset) {
        return {
            x: window.pageXOffset,
            y: window.pageYOffset
        }
    } else {
        return {
            x: document.body.scrollLeft + document.documentElement.scrollLeft,
            y: document.body.scrollTop + document.documentElement.scrollTop
        }
    }
}
15、獲得視口的尺寸
function getViewportOffset() {
    if (window.innerWidth) {
        return {
            w: window.innerWidth,
            h: window.innerHeight
        }
    } else {
        // ie8及其以下
        if (document.compatMode === "BackCompat") {
            // 怪異模式
            return {
                w: document.body.clientWidth,
                h: document.body.clientHeight
            }
        } else {
            // 標準模式
            return {
                w: document.documentElement.clientWidth,
                h: document.documentElement.clientHeight
            }
        }
    }
}
16、獲取任一元素的任意屬性
function getStyle(elem, prop) {
    return window.getComputedStyle ? window.getComputedStyle(elem, null)[prop] : elem.currentStyle[prop]
}
17、綁定事件的兼容代碼
function addEvent(elem, type, handle) {
    if (elem.addEventListener) { //非ie和非ie9
        elem.addEventListener(type, handle, false);
    } else if (elem.attachEvent) { //ie6到ie8
        elem.attachEvent('on' + type, function () {
            handle.call(elem);
        })
    } else {
        elem['on' + type] = handle;
    }
}
18、解綁事件
function removeEvent(elem, type, handle) {
    if (elem.removeEventListener) { //非ie和非ie9
        elem.removeEventListener(type, handle, false);
    } else if (elem.detachEvent) { //ie6到ie8
        elem.detachEvent('on' + type, handle);
    } else {
        elem['on' + type] = null;
    }
}
19、取消冒泡的兼容代碼
function stopBubble(e) {
    if (e && e.stopPropagation) {
        e.stopPropagation();
    } else {
        window.event.cancelBubble = true;
    }
}
20、檢驗字符串是否是回文
function isPalina(str) {
    if (Object.prototype.toString.call(str) !== '[object String]') {
        return false;
    }
    var len = str.length;
    for (var i = 0; i < len / 2; i++) {
        if (str[i] != str[len - 1 - i]) {
            return false;
        }
    }
    return true;
}
21、檢驗字符串是否是回文
function isPalindrome(str) {
    str = str.replace(/\W/g, '').toLowerCase();
    console.log(str)
    return (str == str.split('').reverse().join(''))
}
22、兼容getElementsByClassName方法
Element.prototype.getElementsByClassName = Document.prototype.getElementsByClassName = function (_className) {
    var allDomArray = document.getElementsByTagName('*');
    var lastDomArray = [];
    function trimSpace(strClass) {
        var reg = /\s+/g;
        return strClass.replace(reg, ' ').trim()
    }
    for (var i = 0; i < allDomArray.length; i++) {
        var classArray = trimSpace(allDomArray[i].className).split(' ');
        for (var j = 0; j < classArray.length; j++) {
            if (classArray[j] == _className) {
                lastDomArray.push(allDomArray[i]);
                break;
            }
        }
    }
    return lastDomArray;
}
23、運動函數
function animate(obj, json, callback) {
    clearInterval(obj.timer);
    var speed,
        current;
    obj.timer = setInterval(function () {
        var lock = true;
        for (var prop in json) {
            if (prop == 'opacity') {
                current = parseFloat(window.getComputedStyle(obj, null)[prop]) * 100;
            } else {
                current = parseInt(window.getComputedStyle(obj, null)[prop]);
            }
            speed = (json[prop] - current) / 7;
            speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);

            if (prop == 'opacity') {
                obj.style[prop] = (current + speed) / 100;
            } else {
                obj.style[prop] = current + speed + 'px';
            }
            if (current != json[prop]) {
                lock = false;
            }
        }
        if (lock) {
            clearInterval(obj.timer);
            typeof callback == 'function' ? callback() : '';
        }
    }, 30)
}
24、彈性運動
function ElasticMovement(obj, target) {
    clearInterval(obj.timer);
    var iSpeed = 40,
        a, u = 0.8;
    obj.timer = setInterval(function () {
        a = (target - obj.offsetLeft) / 8;
        iSpeed = iSpeed + a;
        iSpeed = iSpeed * u;
        if (Math.abs(iSpeed) <= 1 && Math.abs(a) <= 1) {
            console.log('over')
            clearInterval(obj.timer);
            obj.style.left = target + 'px';
        } else {
            obj.style.left = obj.offsetLeft + iSpeed + 'px';
        }
    }, 30);
}
25、封裝自己的forEach方法
Array.prototype.myForEach = function (func, obj) {
    var len = this.length;
    var _this = arguments[1] ? arguments[1] : window;
    // var _this=arguments[1]||window;
    for (var i = 0; i < len; i++) {
        func.call(_this, this[i], i, this)
    }
}
26、封裝自己的filter方法
Array.prototype.myFilter = function (func, obj) {
    var len = this.length;
    var arr = [];
    var _this = arguments[1] || window;
    for (var i = 0; i < len; i++) {
        func.call(_this, this[i], i, this) && arr.push(this[i]);
    }
    return arr;
}
27、數組map方法
Array.prototype.myMap = function (func) {
    var arr = [];
    var len = this.length;
    var _this = arguments[1] || window;
    for (var i = 0; i < len; i++) {
        arr.push(func.call(_this, this[i], i, this));
    }
    return arr;
}
28、數組every方法
Array.prototype.myEvery = function (func) {
    var flag = true;
    var len = this.length;
    var _this = arguments[1] || window;
    for (var i = 0; i < len; i++) {
        if (func.apply(_this, [this[i], i, this]) == false) {
            flag = false;
            break;
        }
    }
    return flag;
}
29、數組reduce方法
Array.prototype.myReduce = function (func, initialValue) {
    var len = this.length,
        nextValue,
        i;
    if (!initialValue) {
        // 沒有傳第二個參數
        nextValue = this[0];
        i = 1;
    } else {
        // 傳了第二個參數
        nextValue = initialValue;
        i = 0;
    }
    for (; i < len; i++) {
        nextValue = func(nextValue, this[i], i, this);
    }
    return nextValue;
}
30、獲取url中的參數
function getWindonHref() {
    var sHref = window.location.href;
    var args = sHref.split('?');
    if (args[0] === sHref) {
        return '';
    }
    var hrefarr = args[1].split('#')[0].split('&');
    var obj = {};
    for (var i = 0; i < hrefarr.length; i++) {
        hrefarr[i] = hrefarr[i].split('=');
        obj[hrefarr[i][0]] = hrefarr[i][1];
    }
    return obj;
}
31、數組排序
// 快排 [left] + min + [right]
function quickArr(arr) {
    if (arr.length <= 1) {
        return arr;
    }
    var left = [],
        right = [];
    var pIndex = Math.floor(arr.length / 2);
    var p = arr.splice(pIndex, 1)[0];
    for (var i = 0; i < arr.length; i++) {
        if (arr[i] <= p) {
            left.push(arr[i]);
        } else {
            right.push(arr[i]);
        }
    }
    // 遞歸
    return quickArr(left).concat([p], quickArr(right));
}

// 冒泡
function bubbleSort(arr) {
    for (var i = 0; i < arr.length - 1; i++) {
        for (var j = i + 1; j < arr.length; j++) {
            if (arr[i] > arr[j]) {
                var temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
    }
    return arr;
}

function bubbleSort(arr) {
    var len = arr.length;
    for (var i = 0; i < len - 1; i++) {
        for (var j = 0; j < len - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                var temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
    return arr;
}
32、遍歷Dom樹
// 給定頁面上的DOM元素,將訪問元素本身及其所有后代(不僅僅是它的直接子元素)
// 對于每個訪問的元素,函數講元素傳遞給提供的回調函數
function traverse(element, callback) {
    callback(element);
    var list = element.children;
    for (var i = 0; i < list.length; i++) {
        traverse(list[i], callback);
    }
}
33、原生js封裝ajax
function ajax(method, url, callback, data, flag) {
    var xhr;
    flag = flag || true;
    method = method.toUpperCase();
    if (window.XMLHttpRequest) {
        xhr = new XMLHttpRequest();
    } else {
        xhr = new ActiveXObject('Microsoft.XMLHttp');
    }
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4 && xhr.status == 200) {
            console.log(2)
            callback(xhr.responseText);
        }
    }

    if (method == 'GET') {
        var date = new Date(),
        timer = date.getTime();
        xhr.open('GET', url + '?' + data + '&timer' + timer, flag);
        xhr.send()
        } else if (method == 'POST') {
        xhr.open('POST', url, flag);
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xhr.send(data);
    }
}
34、異步加載script
function loadScript(url, callback) {
    var oscript = document.createElement('script');
    if (oscript.readyState) { // ie8及以下版本
        oscript.onreadystatechange = function () {
            if (oscript.readyState === 'complete' || oscript.readyState === 'loaded') {
                callback();
            }
        }
    } else {
        oscript.onload = function () {
            callback()
        };
    }
    oscript.src = url;
    document.body.appendChild(oscript);
}
35、cookie管理
var cookie = {
    set: function (name, value, time) {
        document.cookie = name + '=' + value + '; max-age=' + time;
        return this;
    },
    remove: function (name) {
        return this.setCookie(name, '', -1);
    },
    get: function (name, callback) {
        var allCookieArr = document.cookie.split('; ');
        for (var i = 0; i < allCookieArr.length; i++) {
            var itemCookieArr = allCookieArr[i].split('=');
            if (itemCookieArr[0] === name) {
                return itemCookieArr[1]
            }
        }
        return undefined;
    }
}
36、實現bind()方法
Function.prototype.myBind = function (target) {
    var target = target || window;
    var _args1 = [].slice.call(arguments, 1);
    var self = this;
    var temp = function () {};
    var F = function () {
        var _args2 = [].slice.call(arguments, 0);
        var parasArr = _args1.concat(_args2);
        return self.apply(this instanceof temp ? this : target, parasArr)
    }
    temp.prototype = self.prototype;
    F.prototype = new temp();
    return F;
}
37、實現call()方法
Function.prototype.myCall = function () {
    var ctx = arguments[0] || window;
    ctx.fn = this;
    var args = [];
    for (var i = 1; i < arguments.length; i++) {
        args.push(arguments[i])
    }
    var result = ctx.fn(...args);
    delete ctx.fn;
    return result;
}
38、實現apply()方法
Function.prototype.myApply = function () {
    var ctx = arguments[0] || window;
    ctx.fn = this;
    if (!arguments[1]) {
        var result = ctx.fn();
        delete ctx.fn;
        return result;
    }
    var result = ctx.fn(...arguments[1]);
    delete ctx.fn;
    return result;
}
39、防抖
function debounce(handle, delay) {
    var timer = null;
    return function () {
        var _self = this,
            _args = arguments;
        clearTimeout(timer);
        timer = setTimeout(function () {
            handle.apply(_self, _args)
        }, delay)
    }
}
40、節流
function throttle(handler, wait) {
    var lastTime = 0;
    return function (e) {
        var nowTime = new Date().getTime();
        if (nowTime - lastTime > wait) {
            handler.apply(this, arguments);
            lastTime = nowTime;
        }
    }
}
41、requestAnimFrame兼容性方法
window.requestAnimFrame = (function () {
    return window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        function (callback) {
            window.setTimeout(callback, 1000 / 60);
        };
})();
42、cancelAnimFrame兼容性方法
window.cancelAnimFrame = (function () {
    return window.cancelAnimationFrame ||
        window.webkitCancelAnimationFrame ||
        window.mozCancelAnimationFrame ||
        function (id) {
            window.clearTimeout(id);
        };
})();
43、jsonp底層方法
function jsonp(url, callback) {
    var oscript = document.createElement('script');
    if (oscript.readyState) { // ie8及以下版本
        oscript.onreadystatechange = function () {
            if (oscript.readyState === 'complete' || oscript.readyState === 'loaded') {
                callback();
            }
        }
    } else {
        oscript.onload = function () {
            callback()
        };
    }
    oscript.src = url;
    document.body.appendChild(oscript);
}
44、獲取url上的參數
function getUrlParam(sUrl, sKey) {
    var result = {};
    sUrl.replace(/(\w+)=(\w+)(?=[&|#])/g, function (ele, key, val) {
        if (!result[key]) {
            result[key] = val;
        } else {
            var temp = result[key];
            result[key] = [].concat(temp, val);
        }
    })
    if (!sKey) {
        return result;
    } else {
        return result[sKey] || '';
    }
}
45、格式化時間
function formatDate(t, str) {
    var obj = {
        yyyy: t.getFullYear(),
        yy: ("" + t.getFullYear()).slice(-2),
        M: t.getMonth() + 1,
        MM: ("0" + (t.getMonth() + 1)).slice(-2),
        d: t.getDate(),
        dd: ("0" + t.getDate()).slice(-2),
        H: t.getHours(),
        HH: ("0" + t.getHours()).slice(-2),
        h: t.getHours() % 12,
        hh: ("0" + t.getHours() % 12).slice(-2),
        m: t.getMinutes(),
        mm: ("0" + t.getMinutes()).slice(-2),
        s: t.getSeconds(),
        ss: ("0" + t.getSeconds()).slice(-2),
        w: ['日', '一', '二', '三', '四', '五', '六'][t.getDay()]
    };
    return str.replace(/([a-z]+)/ig, function ($1) {
        return obj[$1]
    });
}
46、驗證郵箱的正則表達式
function isAvailableEmail(sEmail) {
    var reg = /^([\w+\.])+@\w+([.]\w+)+$/
    return reg.test(sEmail)
}
47、函數柯里化
//是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,并且返回接受余下的參數且返回結果的新函數的技術

function curryIt(fn) {
    var length = fn.length,
        args = [];
    var result = function (arg) {
        args.push(arg);
        length--;
        if (length <= 0) {
            return fn.apply(this, args);
        } else {
            return result;
        }
    }
    return result;
}
48、大數相加
function sumBigNumber(a, b) {
    var res = '', //結果
        temp = 0; //按位加的結果及進位
    a = a.split('');
    b = b.split('');
    while (a.length || b.length || temp) {
        //~~按位非 1.類型轉換,轉換成數字 2.~~undefined==0 
        temp += ~~a.pop() + ~~b.pop();
        res = (temp % 10) + res;
        temp = temp > 9;
    }
    return res.replace(/^0+/, '');
}
49、單例模式
function getSingle(func) {
    var result;
    return function () {
        if (!result) {
            result = new func(arguments);
        }
        return result;
    }
}
查看原文

贊 93 收藏 84 評論 13

小蘑菇 發布了文章 · 2月8日

52道CSS 面試知識點總結(二)

1.設備像素、css?像素、設備獨立像素、dpr、ppi?之間的區別?

設備像素指的是物理像素,一般手機的分辨率指的就是設備像素,一個設備的設備像素是不可變的。
css像素和設備獨立像素是等價的,不管在何種分辨率的設備上,css像素的大小應該是一致的,css像素是一個相對單位,它是相
對于設備像素的,一個css像素的大小取決于頁面縮放程度和dpr的大小。
dpr指的是設備像素和設備獨立像素的比值,一般的pc屏幕,dpr=1。在iphone4時,蘋果推出了retina屏幕,它的dpr
為2。屏幕的縮放會改變dpr的值。
ppi指的是每英寸的物理像素的密度,ppi越大,屏幕的分辨率越大。

詳細資料可以參考:?《什么是物理像素、虛擬像素、邏輯像素、設備像素,什么又是 PPI,DPI,DPR 和 DIP》?《前端工程師需要明白的「像素」》?《CSS 像素、物理像素、邏輯像素、設備像素比、PPI、Viewport》?《前端開發中像素的概念》

2、layout viewport、visual viewport 和 ideal viewport 的區別?

相關知識點:

如果把移動設備上瀏覽器的可視區域設為viewport的話,某些網站就會因為viewport太窄而顯示錯亂,所以這些瀏覽器就決定
默認情況下把viewport設為一個較寬的值,比如980px,這樣的話即使是那些為桌面設計的網站也能在移動瀏覽器上正常顯示了。
ppk把這個瀏覽器默認的viewport叫做layout viewport。
layout viewport的寬度是大于瀏覽器可視區域的寬度的,所以我們還需要一個viewport來代表瀏覽器可視區域的大小,ppk把
這個viewport叫做visual viewport。
ideal viewport是最適合移動設備的viewport,ideal viewport的寬度等于移動設備的屏幕寬度,只要在css中把某一元
素的寬度設為ideal viewport的寬度(單位用px),那么這個元素的寬度就是設備屏幕的寬度了,也就是寬度為100%的效果。i
deal viewport的意義在于,無論在何種分辨率的屏幕下,那些針對ideal viewport而設計的網站,不需要用戶手動縮放,也
不需要出現橫向滾動條,都可以完美的呈現給用戶。

回答:

移動端一共需要理解三個viewport的概念的理解。
第一個視口是布局視口,在移動端顯示網頁時,由于移動端的屏幕尺寸比較小,如果網頁使用移動端的屏幕尺寸進行布局的話,那么整
個頁面的布局都會顯示錯亂。所以移動端瀏覽器提供了一個layout viewport布局視口的概念,使用這個視口來對頁面進行布局展
示,一般layout viewport的大小為980px,因此頁面布局不會有太大的變化,我們可以通過拖動和縮放來查看到這個頁面。
第二個視口指的是視覺視口,visual viewport指的是移動設備上我們可見的區域的視口大小,一般為屏幕的分辨率的大小。visu
al viewport和layout viewport的關系,就像是我們通過窗戶看外面的風景,視覺視口就是窗戶,而外面的風景就是布局視口
中的網頁內容。
第三個視口是理想視口,由于layout viewport一般比visual viewport要大,所以想要看到整個頁面必須通過拖動和縮放才
能實現。所以又提出了ideal viewport的概念,ideal viewport下用戶不用縮放和滾動條就能夠查看到整個頁面,并且頁面在
不同分辨率下顯示的內容大小相同。ideal viewport其實就是通過修改layout viewport的大小,讓它等于設備的寬度,這個
寬度可以理解為是設備獨立像素,因此根據ideal viewport設計的頁面,在不同分辨率的屏幕下,顯示應該相同。

詳細資料可以參考:?《移動前端開發之 viewport 的深入理解》?《說說移動前端中 viewport(視口)》?《移動端適配知識你到底知多少》

3、position:fixed;在 android 下無效怎么處理?

因為移動端瀏覽器默認的viewport叫做layout viewport。在移動端顯示時,因為layout viewport的寬度大于移動端屏幕
的寬度,所以頁面會出現滾動條左右移動,fixed的元素是相對layout viewport來固定位置的,而不是移動端屏幕來固定位置的
,所以會出現感覺fixed無效的情況。
如果想實現fixed相對于屏幕的固定效果,我們需要改變的是viewport的大小為ideal viewport,可以如下設置:
<metaname="viewport"content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-sca
le=1.0,user-scalable=no"/>

4、如果需要手動寫動畫,你認為最小時間間隔是多久,為什么?(阿里)

多數顯示器默認頻率是60Hz,即1秒刷新60次,所以理論上最小間隔為1/60*1000ms=16.7ms

5、如何讓去除?inline-block?元素間間距?

移除空格、使用margin負值、使用font-size:0、letter-spacing、word-spacing

詳細資料可以參考:?《去除 inline-block 元素間間距的 N 種方法》

6、overflow:scroll 時不能平滑滾動的問題怎么處理?

以下代碼可解決這種卡頓的問題:-webkit-overflow-scrolling:touch;是因為這行代碼啟用了硬件加速特性,所以滑動很流
暢。

詳細資料可以參考:?《解決頁面使用 overflow:scroll 在 iOS 上滑動卡頓的問題》

7、有一個高度自適應的 div,里面有兩個 div,一個高度 100px,希望另一個填滿剩下的高度。

(1)外層div使用position:relative;高度要求自適應的div使用position:absolute;top:100px;bottom:0;
left:0;right:0;
(2)使用flex布局,設置主軸為豎軸,第二個div的flex-grow為1。

詳細資料可以參考:?《有一個高度自適應的 div,里面有兩個 div,一個高度 100px,希望另一個填滿剩下的高度(三種方案)》

8、png、jpg、gif 這些圖片格式解釋一下,分別什么時候用。有沒有了解過 webp?

相關知識點:

(1)BMP,是無損的、既支持索引色也支持直接色的、點陣圖。這種圖片格式幾乎沒有對數據進行壓縮,所以BMP格式的圖片通常
具有較大的文件大小。
(2)GIF是無損的、采用索引色的、點陣圖。采用LZW壓縮算法進行編碼。文件小,是GIF格式的優點,同時,GIF格式還具
有支持動畫以及透明的優點。但,GIF格式僅支持8bit的索引色,所以GIF格式適用于對色彩要求不高同時需要文件體積
較小的場景。
(3)JPEG是有損的、采用直接色的、點陣圖。JPEG的圖片的優點,是采用了直接色,得益于更豐富的色彩,JPEG非常適合用來
存儲照片,與GIF相比,JPEG不適合用來存儲企業Logo、線框類的圖。因為有損壓縮會導致圖片模糊,而直接色的選用,
又會導致圖片文件較GIF更大。
(4)PNG-8是無損的、使用索引色的、點陣圖。PNG是一種比較新的圖片格式,PNG-8是非常好的GIF格式替代者,在可能的
情況下,應該盡可能的使用PNG-8而不是GIF,因為在相同的圖片效果下,PNG-8具有更小的文件體積。除此之外,PNG-8
還支持透明度的調節,而GIF并不支持?,F在,除非需要動畫的支持,否則我們沒有理由使用GIF而不是PNG-8。
(5)PNG-24是無損的、使用直接色的、點陣圖。PNG-24的優點在于,它壓縮了圖片的數據,使得同樣效果的圖片,PNG-24格
式的文件大小要比BMP小得多。當然,PNG24的圖片還是要比JPEG、GIF、PNG-8大得多。
(6)SVG是無損的、矢量圖。SVG是矢量圖。這意味著SVG圖片由直線和曲線以及繪制它們的方法組成。當你放大一個SVG圖
片的時候,你看到的還是線和曲線,而不會出現像素點。這意味著SVG圖片在放大時,不會失真,所以它非常適合用來繪制企
業Logo、Icon等。
(7)WebP是谷歌開發的一種新圖片格式,WebP是同時支持有損和無損壓縮的、使用直接色的、點陣圖。從名字就可以看出來它是
為Web而生的,什么叫為Web而生呢?就是說相同質量的圖片,WebP具有更小的文件體積?,F在網站上充滿了大量的圖片,
如果能夠降低每一個圖片的文件大小,那么將大大減少瀏覽器和服務器之間的數據傳輸量,進而降低訪問延遲,提升訪問體驗。
?在無損壓縮的情況下,相同質量的WebP圖片,文件大小要比PNG小26%;
?在有損壓縮的情況下,具有相同圖片精度的WebP圖片,文件大小要比JPEG小25%~34%;
?WebP圖片格式支持圖片透明度,一個無損壓縮的WebP圖片,如果要支持透明度只需要22%的格外文件大小。
但是目前只有Chrome瀏覽器和Opera瀏覽器支持WebP格式,兼容性不太好。

回答:

我了解到的一共有七種常見的圖片的格式。
(1)第一種是BMP格式,它是無損壓縮的,支持索引色和直接色的點陣圖。由于它基本上沒有進行壓縮,因此它的文件體積一般比
較大。
(2)第二種是GIF格式,它是無損壓縮的使用索引色的點陣圖。由于使用了LZW壓縮方法,因此文件的體積很小。并且GIF還
支持動畫和透明度。但因為它使用的是索引色,所以它適用于一些對顏色要求不高且需要文件體積小的場景。
(3)第三種是JPEG格式,它是有損壓縮的使用直接色的點陣圖。由于使用了直接色,色彩較為豐富,一般適用于來存儲照片。但
由于使用的是直接色,可能文件的體積相對于GIF格式來說更大。
(4)第四種是PNG-8格式,它是無損壓縮的使用索引色的點陣圖。它是GIF的一種很好的替代格式,它也支持透明度的調整,并
且文件的體積相對于GIF格式更小。一般來說如果不是需要動畫的情況,我們都可以使用PNG-8格式代替GIF格式。
(5)第五種是PNG-24格式,它是無損壓縮的使用直接色的點陣圖。PNG-24的優點是它使用了壓縮算法,所以它的體積比BMP
格式的文件要小得多,但是相對于其他的幾種格式,還是要大一些。
(6)第六種格式是svg格式,它是矢量圖,它記錄的圖片的繪制方式,因此對矢量圖進行放大和縮小不會產生鋸齒和失真。它一般
適合于用來制作一些網站logo或者圖標之類的圖片。
(7)第七種格式是webp格式,它是支持有損和無損兩種壓縮方式的使用直接色的點陣圖。使用webp格式的最大的優點是,在相
同質量的文件下,它擁有更小的文件體積。因此它非常適合于網絡圖片的傳輸,因為圖片體積的減少,意味著請求時間的減小,
這樣會提高用戶的體驗。這是谷歌開發的一種新的圖片格式,目前在兼容性上還不是太好。

詳細資料可以參考:?《圖片格式那么多,哪種更適合你?》

9、瀏覽器如何判斷是否支持 webp 格式圖片

(1)寬高判斷法。通過創建image對象,將其src屬性設置為webp格式的圖片,然后在onload事件中獲取圖片的寬高,如
果能夠獲取,則說明瀏覽器支持webp格式圖片。如果不能獲取或者觸發了onerror函數,那么就說明瀏覽器不支持webp格
式的圖片。
(2)canvas判斷方法。我們可以動態的創建一個canvas對象,通過canvas的toDataURL將設置為webp格式,然后判斷
返回值中是否含有image/webp字段,如果包含則說明支持WebP,反之則不支持。

詳細資料可以參考:?《判斷瀏覽器是否支持 WebP 圖片》?《toDataURL()》

10、什么是 Cookie 隔離?(或者說:請求資源的時候不要讓它帶 cookie 怎么做)

網站向服務器請求的時候,會自動帶上cookie這樣增加表頭信息量,使請求變慢。
如果靜態文件都放在主域名下,那靜態文件請求的時候都帶有的cookie的數據提交給server的,非常浪費流量,所以不如隔離開
,靜態資源放CDN。
因為cookie有域的限制,因此不能跨域提交請求,故使用非主要域名的時候,請求頭中就不會帶有cookie數據,這樣可以降低請
求頭的大小,降低請求時間,從而達到降低整體請求延時的目的。
同時這種方式不會將cookie傳入WebServer,也減少了WebServer對cookie的處理分析環節,提高了webserver的
http請求的解析速度。

詳細資料可以參考:?《CDN 是什么?使用 CDN 有什么優勢?》

11、style 標簽寫在 body 后與 body 前有什么區別?

頁面加載自上而下當然是先加載樣式。寫在body標簽后由于瀏覽器以逐行方式對HTML文檔進行解析,當解析到寫在尾部的樣式
表(外聯或寫在style標簽)會導致瀏覽器停止之前的渲染,等待加載且解析樣式表完成之后重新渲染,在windows的IE下可
能會出現FOUC現象(即樣式失效導致的頁面閃爍問題)

12、什么是?CSS?預處理器/后處理器?

CSS預處理器定義了一種新的語言,其基本思想是,用一種專門的編程語言,為CSS增加了一些編程的特性,將CSS作為目標生成
文件,然后開發者就只要使用這種語言進行編碼工作。通俗的說,CSS預處理器用一種專門的編程語言,進行Web頁面樣式設計,然
后再編譯成正常的CSS文件。
預處理器例如:LESS、Sass、Stylus,用來預編譯Sass或less csssprite,增強了css代碼的復用性,還有層級、mixin、
變量、循環、函數等,具有很方便的UI組件模塊化開發能力,極大的提高工作效率。
CSS后處理器是對CSS進行處理,并最終生成CSS的預處理器,它屬于廣義上的CSS預處理器。我們很久以前就在用CSS后
處理器了,最典型的例子是CSS壓縮工具(如clean-css),只不過以前沒單獨拿出來說過。還有最近比較火的Autoprefixer,
以CanIUse上的瀏覽器支持數據為基礎,自動處理兼容性問題。
后處理器例如:PostCSS,通常被視為在完成的樣式表中根據CSS規范處理CSS,讓其更有效;目前最常做的是給CSS屬性添加瀏
覽器私有前綴,實現跨瀏覽器兼容性的問題。

詳細資料可以參考:?《CSS 預處理器和后處理器》

13、闡述一下 CSSSprites

將一個頁面涉及到的所有圖片都包含到一張大圖中去,然后利用CSS的background-image,background-repeat,background
-position的組合進行背景定位。利用CSSSprites能很好地減少網頁的http請求,從而很好的提高頁面的性能;CSSSprites
能減少圖片的字節。
優點:
減少HTTP請求數,極大地提高頁面加載速度
增加圖片信息重復度,提高壓縮比,減少圖片大小
更換風格方便,只需在一張或幾張圖片上修改顏色或樣式即可實現
缺點:
圖片合并麻煩
維護麻煩,修改一個圖片可能需要重新布局整個圖片,樣式

14、使用?rem?布局的優缺點?

優點:
在屏幕分辨率千差萬別的時代,只要將rem與屏幕分辨率關聯起來就可以實現頁面的整體縮放,使得在設備上的展現都統一起來了。
而且現在瀏覽器基本都已經支持rem了,兼容性也非常的好。
缺點:
(1)在奇葩的dpr設備上表現效果不太好,比如一些華為的高端機型用rem布局會出現錯亂。
(2)使用iframe引用也會出現問題。
(3)rem在多屏幕尺寸適配上與當前兩大平臺的設計哲學不一致。即大屏的出現到底是為了看得又大又清楚,還是為了看的更多的問
題。

詳細資料可以參考:?《css3 的字體大小單位 rem 到底好在哪?》?《VW:是時候放棄 REM 布局了》?《為什么設計稿是 750px》?《使用 Flexible 實現手淘 H5 頁面的終端適配》

15、transition 和 animation 的區別

transition關注的是CSS property的變化,property值和時間的關系是一個三次貝塞爾曲線。
animation作用于元素本身而不是樣式屬性,可以使用關鍵幀的概念,應該說可以實現更自由的動畫效果。

詳細資料可以參考:?《CSSanimation 與 CSStransition 有何區別?》?《CSS3Transition 和 Animation 區別及比較》?《CSS 動畫簡介》?《CSS 動畫:animation、transition、transform、translate》

16、什么是首選最小寬度?

“首選最小寬度”,指的是元素最適合的最小寬度。
東亞文字(如中文)最小寬度為每個漢字的寬度。
西方文字最小寬度由特定的連續的英文字符單元決定。并不是所有的英文字符都會組成連續單元,一般會終止于空格(普通空格)、短
橫線、問號以及其他非英文字符等。
如果想讓英文字符和中文一樣,每一個字符都用最小寬度單元,可以試試使用CSS中的word-break:break-all。

17、為什么?height:100%會無效?

對于普通文檔流中的元素,百分比高度值要想起作用,其父級必須有一個可以生效的高度值。
原因是如果包含塊的高度沒有顯式指定(即高度由內容決定),并且該元素不是絕對定位,則計算值為auto,因為解釋成了auto,
所以無法參與計算。
使用絕對定位的元素會有計算值,即使祖先元素的height計算為auto也是如此。

18、min-width/max-width?和?min-height/max-height?屬性間的覆蓋規則?

(1)max-width會覆蓋width,即使width是行類樣式或者設置了!important。
(2)min-width會覆蓋max-width,此規則發生在min-width和max-width沖突的時候。

19、內聯盒模型基本概念

(1)內容區域(content area)。內容區域指一種圍繞文字看不見的盒子,其大小僅受字符本身特性控制,本質上是一個字符盒子
(character box);但是有些元素,如圖片這樣的替換元素,其內容顯然不是文字,不存在字符盒子之類的,因此,對于這些
元素,內容區域可以看成元素自身。
(2)內聯盒子(inline box)?!皟嚷摵凶印辈粫寖热莩蓧K顯示,而是排成一行,這里的“內聯盒子”實際指的就是元素的“外在盒
子”,用來決定元素是內聯還是塊級。該盒子又可以細分為“內聯盒子”和“匿名內聯盒子”兩類。
(3)行框盒子(line box),每一行就是一個“行框盒子”(實線框標注),每個“行框盒子”又是由一個一個“內聯盒子”組成的。
(4)包含塊(containing box),由一行一行的“行框盒子”組成。

20、什么是幽靈空白節點?

“幽靈空白節點”是內聯盒模型中非常重要的一個概念,具體指的是:在HTML5文檔聲明中,內聯元素的所有解析和渲染表現就如同
每個行框盒子的前面有一個“空白節點”一樣。這個“空白節點”永遠透明,不占據任何寬度,看不見也無法通過腳本獲取,就好像幽靈
一樣,但又確確實實地存在,表現如同文本節點一樣,因此,我稱之為“幽靈空白節點”。

21、什么是替換元素?

通過修改某個屬性值呈現的內容就可以被替換的元素就稱為“替換元素”。因此,<img>、<object>、<video>、<iframe>或者表
單元素<textarea>和<input>和<select>都是典型的替換元素。

替換元素除了內容可替換這一特性以外,還有以下一些特性。

(1)內容的外觀不受頁面上的CSS的影響。用專業的話講就是在樣式表現在CSS作用域之外。如何更改替換元素本身的外觀需要
類似appearance屬性,或者瀏覽器自身暴露的一些樣式接口,

(2)有自己的尺寸。在Web中,很多替換元素在沒有明確尺寸設定的情況下,其默認的尺寸(不包括邊框)是300像素×150像
素,如<video>、<iframe>或者<canvas>等,也有少部分替換元素為0像素,如<img>圖片,而表單元素的替換元素
的尺寸則和瀏覽器有關,沒有明顯的規律。

(3)在很多CSS屬性上有自己的一套表現規則。比較具有代表性的就是vertical-align屬性,對于替換元素和非替換元素,ve
rtical-align屬性值的解釋是不一樣的。比方說vertical-align的默認值的baseline,很簡單的屬性值,基線之意,
被定義為字符x的下邊緣,而替換元素的基線卻被硬生生定義成了元素的下邊緣。

(4)所有的替換元素都是內聯水平元素,也就是替換元素和替換元素、替換元素和文字都是可以在一行顯示的。但是,替換元素默認
的display值卻是不一樣的,有的是inline,有的是inline-block。

22、替換元素的計算規則?

替換元素的尺寸從內而外分為3類:固有尺寸、HTML尺寸和CSS尺寸。

(1)固有尺寸指的是替換內容原本的尺寸。例如,圖片、視頻作為一個獨立文件存在的時候,都是有著自己的寬度和高度的。

(2)HTML尺寸只能通過HTML原生屬性改變,這些HTML原生屬性包括<img>的width和height屬性、<input>的s
ize屬性、<textarea>的cols和rows屬性等。

(3)CSS尺寸特指可以通過CSS的width和height或者max-width/min-width和max-height/min-height設置的
尺寸,對應盒尺寸中的content box。

這3層結構的計算規則具體如下

(1)如果沒有CSS尺寸和HTML尺寸,則使用固有尺寸作為最終的寬高。

(2)如果沒有CSS尺寸,則使用HTML尺寸作為最終的寬高。

(3)如果有CSS尺寸,則最終尺寸由CSS屬性決定。

(4)如果“固有尺寸”含有固有的寬高比例,同時僅設置了寬度或僅設置了高度,則元素依然按照固有的寬高比例顯示。

(5)如果上面的條件都不符合,則最終寬度表現為300像素,高度為150像素。

(6)內聯替換元素和塊級替換元素使用上面同一套尺寸計算規則。

23、content?與替換元素的關系?

content屬性生成的對象稱為“匿名替換元素”。
(1)我們使用content生成的文本是無法選中、無法復制的,好像設置了user select:none聲明一般,但是普通元素的文本
卻可以被輕松選中。同時,content生成的文本無法被屏幕閱讀設備讀取,也無法被搜索引擎抓取,因此,千萬不要自以為是
地把重要的文本信息使用content屬性生成,因為這對可訪問性和SEO都很不友好。
(2)content生成的內容不能左右:empty偽類。
(3)content動態生成值無法獲取。

24、margin:auto?的填充規則?

margin的'auto'可不是擺設,是具有強烈的計算意味的關鍵字,用來計算元素對應方向應該獲得的剩余間距大小。但是觸發mar
gin:auto計算有一個前提條件,就是width或height為auto時,元素是具有對應方向的自動填充特性的。
(1)如果一側定值,一側auto,則auto為剩余空間大小。
(2)如果兩側均是auto,則平分剩余空間。

25、margin?無效的情形

(1)display計算值inline的非替換元素的垂直margin是無效的。對于內聯替換元素,垂直margin有效,并且沒有ma
rgin合并的問題。
(2)表格中的<tr>和<td>元素或者設置display計算值是table-cell或table-row的元素的margin都是無效的。
(3)絕對定位元素非定位方位的margin值“無效”。
(4)定高容器的子元素的margin-bottom或者寬度定死的子元素的margin-right的定位“失效”。

26、border?的特殊性?

(1)border-width卻不支持百分比。
(2)border-style的默認值是none,有一部分人可能會誤以為是solid。這也是單純設置border-width或border-col
or沒有邊框顯示的原因。
(3)border-style:double的表現規則:雙線寬度永遠相等,中間間隔±1。
(4)border-color默認顏色就是color色值。
(5)默認background背景圖片是相對于padding box定位的。

27、什么是基線和?x-height?

字母x的下邊緣(線)就是我們的基線。
x-height指的就是小寫字母x的高度,術語描述就是基線和等分線(meanline)(也稱作中線,midline)之間的距離。在C
SS世界中,middle指的是基線往上1/2x-height高度。我們可以近似理解為字母x交叉點那個位置。
ex是CSS中的一個相對單位,指的是小寫字母x的高度,沒錯,就是指x-height。ex的價值就在其副業上不受字體和字號影
響的內聯元素的垂直居中對齊效果。內聯元素默認是基線對齊的,而基線就是x的底部,而1ex就是一個x的高度。

28、line-height?的特殊性?

(1)對于非替換元素的純內聯元素,其可視高度完全由line-height決定。對于文本這樣的純內聯元素,line-height就是高
度計算的基石,用專業說法就是指定了用來計算行框盒子高度的基礎高度。
(2)內聯元素的高度由固定高度和不固定高度組成,這個不固定的部分就是這里的“行距”。換句話說,line-height之所以起作
用,就是通過改變“行距”來實現的。在CSS中,“行距”分散在當前文字的上方和下方,也就是即使是第一行文字,其上方也是
有“行距”的,只不過這個“行距”的高度僅僅是完整“行距”高度的一半,因此,也被稱為“半行距”。
(3)行距=line-height-font-size。
(4)border以及line-height等傳統CSS屬性并沒有小數像素的概念。如果標注的是文字上邊距,則向下取整;如果是文字下
邊距,則向上取整。
(5)對于純文本元素,line-height直接決定了最終的高度。但是,如果同時有替換元素,則line-height只能決定最小高度。
(6)對于塊級元素,line-height對其本身是沒有任何作用的,我們平時改變line-height,塊級元素的高度跟著變化實際上是
通過改變塊級元素里面內聯級別元素占據的高度實現的。
(7)line-height的默認值是normal,還支持數值、百分比值以及長度值。為數值類型時,其最終的計算值是和當前font-si
ze相乘后的值。為百分比值時,其最終的計算值是和當前font-size相乘后的值。為長度值時原意不變。
(8)如果使用數值作為line-height的屬性值,那么所有的子元素繼承的都是這個值;但是,如果使用百分比值或者長度值作為
屬性值,那么所有的子元素繼承的是最終的計算值。
(9)無論內聯元素line-height如何設置,最終父級元素的高度都是由數值大的那個line-height決定的。
(10)只要有“內聯盒子”在,就一定會有“行框盒子”,就是每一行內聯元素外面包裹的一層看不見的盒子。然后,重點來了,在每個
“行框盒子”前面有一個寬度為0的具有該元素的字體和行高屬性的看不見的“幽靈空白節點”。

29、vertical-align?的特殊性?

(1)vertical-align的默認值是baseline,即基線對齊,而基線的定義是字母x的下邊緣。因此,內聯元素默認都是沿著字
母x的下邊緣對齊的。對于圖片等替換元素,往往使用元素本身的下邊緣作為基線。:一個inline-block元素,如果里面
沒有內聯元素,或者overflow不是visible,則該元素的基線就是其margin底邊緣;否則其基線就是元素里面最后一行
內聯元素的基線。
(2)vertical-align:top就是垂直上邊緣對齊,如果是內聯元素,則和這一行位置最高的內聯元素的頂部對齊;如果display
計算值是table-cell的元素,我們不妨腦補成<td>元素,則和<tr>元素上邊緣對齊。
(3)vertical-align:middle是中間對齊,對于內聯元素,元素的垂直中心點和行框盒子基線往上1/2x-height處對齊。對
于table-cell元素,單元格填充盒子相對于外面的表格行居中對齊。
(4)vertical-align支持數值屬性,根據數值的不同,相對于基線往上或往下偏移,如果是負值,往下偏移,如果是正值,往上
偏移。
(5)vertical-align屬性的百分比值則是相對于line-height的計算值計算的。
(6)vertical-align起作用是有前提條件的,這個前提條件就是:只能應用于內聯元素以及display值為table-cell的元
素。
(7)table-cell元素設置vertical-align垂直對齊的是子元素,但是其作用的并不是子元素,而是table-cell元素自身。

30、overflow?的特殊性?

(1)一個設置了overflow:hidden聲明的元素,假設同時存在border屬性和padding屬性,則當子元素內容超出容器寬度
高度限制的時候,剪裁的邊界是border box的內邊緣,而非padding box的內邊緣。
(2)HTML中有兩個標簽是默認可以產生滾動條的,一個是根元素<html>,另一個是文本域<textarea>。
(3)滾動條會占用容器的可用寬度或高度。
(4)元素設置了overflow:hidden聲明,里面內容高度溢出的時候,滾動依然存在,僅僅滾動條不存在!

31、無依賴絕對定位是什么?

沒有設置left/top/right/bottom屬性值的絕對定位稱為“無依賴絕對定位”。
無依賴絕對定位其定位的位置和沒有設置position:absolute時候的位置相關。

32、absolute?與?overflow?的關系?

(1)如果overflow不是定位元素,同時絕對定位元素和overflow容器之間也沒有定位元素,則overflow無法對absolute
元素進行剪裁。
(2)如果overflow的屬性值不是hidden而是auto或者scroll,即使絕對定位元素高寬比overflow元素高寬還要大,也
都不會出現滾動條。
(3)overflow元素自身transform的時候,Chrome和Opera瀏覽器下的overflow剪裁是無效的。

33、clip?裁剪是什么?

所謂“可訪問性隱藏”,指的是雖然內容肉眼看不見,但是其他輔助設備卻能夠進行識別和訪問的隱藏。
clip剪裁被我稱為“最佳可訪問性隱藏”的另外一個原因就是,它具有更強的普遍適應性,任何元素、任何場景都可以無障礙使用。

34、relative?的特殊性?

(1)相對定位元素的left/top/right/bottom的百分比值是相對于包含塊計算的,而不是自身。注意,雖然定位位移是相對自身,但是百分比值的計算值不是。
(2)top和bottom這兩個垂直方向的百分比值計算跟height的百分比值是一樣的,都是相對高度計算的。同時,如果包含塊的高度是auto,那么計算值是0,偏移無效,也就是說,如果父元素沒有設定高度或者不是“格式化高度”,那么relative類似top:20%的代碼等同于top:0。
(3)當相對定位元素同時應用對立方向定位值的時候,也就是top/bottom和left/right同時使用的時候,只有一個方向的定位屬性會起作用。而誰起作用則是與文檔流的順序有關的,默認的文檔流是自上而下、從左往右,因此top/bottom同時使用的時候,bottom失效;left/right同時使用的時候,right失效。

35、什么是層疊上下文?

層疊上下文,英文稱作stacking context,是HTML中的一個三維的概念。如果一個元素含有層疊上下文,我們可以理解為這個元
素在z軸上就“高人一等”。
層疊上下文元素有如下特性:
(1)層疊上下文的層疊水平要比普通元素高(原因后面會說明)。
(2)層疊上下文可以阻斷元素的混合模式。
(3)層疊上下文可以嵌套,內部層疊上下文及其所有子元素均受制于外部的“層疊上下文”。
(4)每個層疊上下文和兄弟元素獨立,也就是說,當進行層疊變化或渲染的時候,只需要考慮后代元素。
(5)每個層疊上下文是自成體系的,當元素發生層疊的時候,整個元素被認為是在父層疊上下文的層疊順序中。
層疊上下文的創建:
(1)頁面根元素天生具有層疊上下文,稱為根層疊上下文。根層疊上下文指的是頁面根元素,可以看成是<html>元素。因此,頁面中所有的元素一定處于至少一個“層疊結界”中。
(2)對于position值為relative/absolute以及Firefox/IE瀏覽器(不包括Chrome瀏覽器)下含有position:fixed聲明的定位元素,當其z-index值不是auto的時候,會創建層疊上下文。Chrome等WebKit內核瀏覽器下,position:fixed元素天然層疊上下文元素,無須z-index為數值。根據我的測試,目前IE和Firefox仍是老套路。
(3)其他一些CSS3屬性,比如元素的opacity值不是1。

36、什么是層疊水平?

層疊水平,英文稱作stacking level,決定了同一個層疊上下文中元素在z軸上的顯示順序。
顯而易見,所有的元素都有層疊水平,包括層疊上下文元素,也包括普通元素。然而,對普通元素的層疊水平探討只局限在當前層疊上
下文元素中。

37、層疊準則?

(1)誰大誰上:當具有明顯的層疊水平標識的時候,如生效的z-index屬性值,在同一個層疊上下文領域,層疊水平值大的那一個覆蓋小的那一個。
(2)后來居上:當元素的層疊水平一致、層疊順序相同的時候,在DOM流中處于后面的元素會覆蓋前面的元素。

38、font-weight?的特殊性?

如果使用數值作為font-weight屬性值,必須是100~900的整百數。因為這里的數值僅僅是外表長得像數值,實際上是一個具有特定含義的關鍵字,并且這里的數值關鍵字和字母關鍵字之間是有對應關系的。

39、text-indent?的特殊性?

(1)text-indent僅對第一行內聯盒子內容有效。
(2)非替換元素以外的display計算值為inline的內聯元素設置text-indent值無效,如果計算值inline-block/inli
ne-table則會生效。
(3)<input>標簽按鈕text-indent值無效。
(4)<button>標簽按鈕text-indent值有效。
(5)text-indent的百分比值是相對于當前元素的“包含塊”計算的,而不是當前元素。

40、letter-spacing?與字符間距?

letter-spacing可以用來控制字符之間的間距,這里說的“字符”包括英文字母、漢字以及空格等。
letter-spacing具有以下一些特性。
(1)繼承性。
(2)默認值是normal而不是0。雖然說正常情況下,normal的計算值就是0,但兩者還是有差別的,在有些場景下,letter-spacing會調整normal的計算值以實現更好的版面布局。
(3)支持負值,且值足夠大的時候,會讓字符形成重疊,甚至反向排列。
(4)和text-indent屬性一樣,無論值多大或多小,第一行一定會保留至少一個字符。
(5)支持小數值,即使0.1px也是支持的。
(6)暫不支持百分比值。

41、word-spacing?與單詞間距?

letter-spacing作用于所有字符,但word-spacing僅作用于空格字符。換句話說,word-spacing的作用就是增加空格的間隙
寬度。

42、white-space?與換行和空格的控制?

white-space屬性聲明了如何處理元素內的空白字符,這類空白字符包括Space(空格)鍵、Enter(回車)鍵、Tab(制表符)
鍵產生的空白。因此,white-space可以決定圖文內容是否在一行顯示(回車空格是否生效),是否顯示大段連續空白(空格是否
生效)等。
其屬性值包括下面這些。
?normal:合并空白字符和換行符。
?pre:空白字符不合并,并且內容只在有換行符的地方換行。
?nowrap:該值和normal一樣會合并空白字符,但不允許文本環繞。
?pre-wrap:空白字符不合并,并且內容只在有換行符的地方換行,同時允許文本環繞。
?pre-line:合并空白字符,但只在有換行符的地方換行,允許文本環繞。

43、隱藏元素的 background-image 到底加不加載?
相關知識點:

根據測試,一個元素如果display計算值為none,在IE瀏覽器下(IE8~IE11,更高版本不確定)依然會發送圖片請求,Fire
fox瀏覽器不會,至于Chrome和Safari瀏覽器則似乎更加智能一點:如果隱藏元素同時又設置了background-image,則圖片
依然會去加載;如果是父元素的display計算值為none,則背景圖不會請求,此時瀏覽器或許放心地認為這個背景圖暫時是不會使
用的。

如果不是background-image,而是<img>元素,則設置display:none在所有瀏覽器下依舊都會請求圖片資源。

還需要注意的是如果設置的樣式沒有對應的元素,則background-image也不會加載。hover情況下的background-image,在觸
發時加載。

回答:

-(1)元素的背景圖片

-元素本身設置 display:none,會請求圖片 -父級元素設置 display:none,不會請求圖片 -樣式沒有元素使用,不會請求 -:hover 樣式下,觸發時請求

-(2)img 標簽圖片任何情況下都會請求圖片

詳細資料可以參考: 《CSS 控制前端圖片 HTTP 請求的各種情況示例》

44、如何實現單行/多行文本溢出的省略(...)?

/*單行文本溢出*/
p {
 overflow: hidden;
 text-overflow: ellipsis;
 white-space: nowrap;
}
/*多行文本溢出*/
p {
 position: relative;
 line-height: 1.5em;
 /*高度為需要顯示的行數*行高,比如這里我們顯示兩行,則為3*/
 height: 3em;
 overflow: hidden;
}
p:after {
 content: '...';
 position: absolute;
 bottom: 0;
 right: 0;
 background-color: #fff;
}

詳細資料可以參考:?《【CSS/JS】如何實現單行/多行文本溢出的省略》?《CSS 多行文本溢出省略顯示》

45、常見的元素隱藏方式?

-(1)使用 display:none;隱藏元素,渲染樹不會包含該渲染對象,因此該元素不會在頁面中占據位置,也不會響應綁定的監聽事件。

-(2)使用 visibility:hidden;隱藏元素。元素在頁面中仍占據空間,但是不會響應綁定的監聽事件。

-(3)使用 opacity:0;將元素的透明度設置為 0,以此來實現元素的隱藏。元素在頁面中仍然占據空間,并且能夠響應元素綁定的監聽事件。

-(4)通過使用絕對定位將元素移除可視區域內,以此來實現元素的隱藏。

-(5)通過 z-index 負值,來使其他元素遮蓋住該元素,以此來實現隱藏。

-(6)通過 clip/clip-path 元素裁剪的方法來實現元素的隱藏,這種方法下,元素仍在頁面中占據位置,但是不會響應綁定的監聽事件。

-(7)通過 transform:scale(0,0)來將元素縮放為 0,以此來實現元素的隱藏。這種方法下,元素仍在頁面中占據位置,但是不會響應綁定的監聽事件。

詳細資料可以參考: 《CSS 隱藏元素的八種方法》

46、css 實現上下固定中間自適應布局?

利用絕對定位實現body {
 padding: 0;
 margin: 0;
}
.header {
 position: absolute;
 top: 0;
 width: 100%;
 height: 100px;
 background: red;
}
.container {
 position: absolute;
 top: 100px;
 bottom: 100px;
 width: 100%;
 background: green;
}
.footer {
 position: absolute;
 bottom: 0;
 height: 100px;
 width: 100%;
 background: red;
}
利用flex布局實現html,
body {
 height: 100%;
}
body {
 display: flex;
 padding: 0;
 margin: 0;
 flex-direction: column;
}
.header {
 height: 100px;
 background: red;
}
.container {
 flex-grow: 1;
 background: green;
}
.footer {
 height: 100px;
 background: red;
}

詳細資料可以參考:?《css 實現上下固定中間自適應布局》

47、css 兩欄布局的實現?

相關資料:

/*兩欄布局一般指的是頁面中一共兩欄,左邊固定,右邊自適應的布局,一共有四種實現的方式。*/
/*以左邊寬度固定為200px為例*/
/*(1)利用浮動,將左邊元素寬度設置為200px,并且設置向左浮動。將右邊元素的margin-left設置為200px,寬度設置為auto(默認為auto,撐滿整個父元素)。*/
.outer {
 height: 100px;
}
.left {
 float: left;
 height: 100px;
 width: 200px;
 background: tomato;
}
.right {
 margin-left: 200px;
 width: auto;
 height: 100px;
 background: gold;
}
/*(2)第二種是利用flex布局,將左邊元素的放大和縮小比例設置為0,基礎大小設置為200px。將右邊的元素的放大比例設置為1,縮小比例設置為1,基礎大小設置為auto。*/
.outer {
 display: flex;
 height: 100px;
}
.left {
 flex-shrink: 0;
 flex-grow: 0;
 flex-basis: 200px;
 background: tomato;
}
.right {
 flex: auto;
 /*11auto*/
 background: gold;
}
/*(3)第三種是利用絕對定位布局的方式,將父級元素設置相對定位。左邊元素設置為absolute定位,并且寬度設置為
200px。將右邊元素的margin-left的值設置為200px。*/
.outer {
 position: relative;
 height: 100px;
}
.left {
 position: absolute;
 width: 200px;
 height: 100px;
 background: tomato;
}
.right {
 margin-left: 200px;
 height: 100px;
 background: gold;
}
/*(4)第四種還是利用絕對定位的方式,將父級元素設置為相對定位。左邊元素寬度設置為200px,右邊元素設置為絕對定位,左邊定位為200px,其余方向定位為0。*/
.outer {
 position: relative;
 height: 100px;
}
.left {
 width: 200px;
 height: 100px;
 background: tomato;
}
.right {
 position: absolute;
 top: 0;
 right: 0;
 bottom: 0;
 left: 200px;
 background: gold;
}

《兩欄布局 demo 展示》

回答:

兩欄布局一般指的是頁面中一共兩欄,左邊固定,右邊自適應的布局,一共有四種實現的方式。

以左邊寬度固定為 200px 為例

-(1)利用浮動,將左邊元素寬度設置為 200px,并且設置向左浮動。將右邊元素的 margin-left 設置為 200px,寬度設置為 auto(默認為 auto,撐滿整個父元素)。

-(2)第二種是利用 flex 布局,將左邊元素的放大和縮小比例設置為 0,基礎大小設置為 200px。將右邊的元素的放大比例設置為 1,縮小比例設置為 1,基礎大小設置為 auto。

-(3)第三種是利用絕對定位布局的方式,將父級元素設置相對定位。左邊元素設置為 absolute 定位,并且寬度設置為 200px。將右邊元素的 margin-left 的值設置為 200px。

-(4)第四種還是利用絕對定位的方式,將父級元素設置為相對定位。左邊元素寬度設置為 200px,右邊元素設置為絕對定位,左邊定位為 200px,其余方向定位為 0。

48、CSS?三欄布局的實現?

相關資料:

/*三欄布局一般指的是頁面中一共有三欄,左右兩欄寬度固定,中間自適應的布局,一共有五種實現方式。
這里以左邊寬度固定為100px,右邊寬度固定為200px為例。*/
/*(1)利用絕對定位的方式,左右兩欄設置為絕對定位,中間設置對應方向大小的margin的值。*/
.outer {
 position: relative;
 height: 100px;
}
.left {
 position: absolute;
 width: 100px;
 height: 100px;
 background: tomato;
}
.right {
 position: absolute;
 top: 0;
 right: 0;
 width: 200px;
 height: 100px;
 background: gold;
}
.center {
 margin-left: 100px;
 margin-right: 200px;
 height: 100px;
 background: lightgreen;
}
/*(2)利用flex布局的方式,左右兩欄的放大和縮小比例都設置為0,基礎大小設置為固定的大小,中間一欄設置為auto*/
.outer {
 display: flex;
 height: 100px;
}
.left {
 flex: 00100px;
 background: tomato;
}
.right {
 flex: 00200px;
 background: gold;
}
.center {
 flex: auto;
 background: lightgreen;
}
/*(3)利用浮動的方式,左右兩欄設置固定大小,并設置對應方向的浮動。中間一欄設置左右兩個方向的margin值,注意這種方式,中間一欄必須放到最后。*/
.outer {
 height: 100px;
}
.left {
 float: left;
 width: 100px;
 height: 100px;
 background: tomato;
}
.right {
 float: right;
 width: 200px;
 height: 100px;
 background: gold;
}
.center {
 height: 100px;
 margin-left: 100px;
 margin-right: 200px;
 background: lightgreen;
}
/*(4)圣杯布局,利用浮動和負邊距來實現。父級元素設置左右的 padding,三列均設置向左浮動,中間一列放在最前面,寬度設置為父級元素的寬度,因此后面兩列都被擠到了下一行,通過設置 margin 負值將其移動到上一行,再利用相對定位,定位到兩邊。*/
.outer {
 height: 100px;
 padding-left: 100px;
 padding-right: 200px;
}
.left {
 position: relative;
 left: -100px;
 float: left;
 margin-left: -100%;
 width: 100px;
 height: 100px;
 background: tomato;
}
.right {
 position: relative;
 left: 200px;
 float: right;
 margin-left: -200px;
 width: 200px;
 height: 100px;
 background: gold;
}
.center {
 float: left;
 width: 100%;
 height: 100px;
 background: lightgreen;
}
/*(5)雙飛翼布局,雙飛翼布局相對于圣杯布局來說,左右位置的保留是通過中間列的 margin 值來實現的,而不是通過父元
素的 padding 來實現的。本質上來說,也是通過浮動和外邊距負值來實現的。*/
.outer {
 height: 100px;
}
.left {
 float: left;
 margin-left: -100%;
 width: 100px;
 height: 100px;
 background: tomato;
}
.right {
 float: left;
 margin-left: -200px;
 width: 200px;
 height: 100px;
 background: gold;
}
.wrapper {
 float: left;
 width: 100%;
 height: 100px;
 background: lightgreen;
}
.center {
 margin-left: 100px;
 margin-right: 200px;
 height: 100px;
}

《三欄布局 demo 展示》

回答:

三欄布局一般指的是頁面中一共有三欄,左右兩欄寬度固定,中間自適應的布局,一共有五種實現方式。
這里以左邊寬度固定為100px,右邊寬度固定為200px為例。
(1)利用絕對定位的方式,左右兩欄設置為絕對定位,中間設置對應方向大小的margin的值。
(2)利用flex布局的方式,左右兩欄的放大和縮小比例都設置為0,基礎大小設置為固定的大小,中間一欄設置為auto。
(3)利用浮動的方式,左右兩欄設置固定大小,并設置對應方向的浮動。中間一欄設置左右兩個方向的margin值,注意這種方式,中間一欄必須放到最后。
(4)圣杯布局,利用浮動和負邊距來實現。父級元素設置左右的padding,三列均設置向左浮動,中間一列放在最前面,寬度設置為父級元素的寬度,因此后面兩列都被擠到了下一行,通過設置margin負值將其移動到上一行,再利用相對定位,定位到兩邊。雙飛翼布局中間列的寬度不能小于兩邊任意列的寬度,而雙飛翼布局則不存在這個問題。
(5)雙飛翼布局,雙飛翼布局相對于圣杯布局來說,左右位置的保留是通過中間列的margin值來實現的,而不是通過父元素的padding來實現的。本質上來說,也是通過浮動和外邊距負值來實現的。

49、實現一個寬高自適應的正方形

/*1.第一種方式是利用vw來實現*/
.square {
 width: 10%;
 height: 10vw;
 background: tomato;
}
/*2.第二種方式是利用元素的margin/padding百分比是相對父元素width的性質來實現*/
.square {
 width: 20%;
 height: 0;
 padding-top: 20%;
 background: orange;
}
/*3.第三種方式是利用子元素的margin-top的值來實現的*/
.square {
 width: 30%;
 overflow: hidden;
 background: yellow;
}
.square::after {
 content: '';
 display: block;
 margin-top: 100%;
}

《自適應正方形 demo 展示》

50、實現一個三角形

/*三角形的實現原理是利用了元素邊框連接處的等分原理。*/
.triangle {
 width: 0;
 height: 0;
 border-width: 100px;
 border-style: solid;
 border-color: tomatotransparenttransparenttransparent;
}

《三角形 demo 展示》

51、一個自適應矩形,水平垂直居中,且寬高比為 2:1

/*實現原理參考自適應正方形和水平居中方式*/
.box {
 position: absolute;
 top: 0;
 right: 0;
 left: 0;
 bottom: 0;
 margin: auto;
 width: 10%;
 height: 0;
 padding-top: 20%;
 background: tomato;
}

52、你知道?CSS?中不同屬性設置為百分比%時對應的計算基準?

公式:當前元素某CSS屬性值 = 基準 * 對應的百分比
元素的 position 為 relative 和 absolute 時,top和bottom、left和right基準分別為包含塊的 height、width
元素的 position 為 fixed 時,top和bottom、left和right基準分別為初始包含塊(也就是視口)的 height、width,移動設備較為復雜,基準為 Layout viewport 的 height、width
元素的 height 和 width 設置為百分比時,基準分別為包含塊的 height 和 width
元素的 margin 和 padding 設置為百分比時,基準為包含塊的 width(易錯)
元素的 border-width,不支持百分比
元素的 text-indent,基準為包含塊的 width
元素的 border-radius,基準為分別為自身的height、width
元素的 background-size,基準為分別為自身的height、width
元素的 translateX、translateY,基準為分別為自身的height、width
元素的 line-height,基準為自身的 font-size
元素的 font-size,基準為父元素字體
查看原文

贊 0 收藏 0 評論 0

小蘑菇 發布了文章 · 2月8日

50道CSS 面試知識點總結(一)

1、介紹一下標準的 CSS 的盒子模型?低版本 IE 的盒子模型有什么不同的?

相關知識點:

(1)有兩種盒子模型:IE盒模型(border-box)、W3C標準盒模型(content-box)
(2)盒模型:分為內容(content)、填充(padding)、邊界(margin)、邊框(border)四個部分
IE盒模型和W3C標準盒模型的區別:
(1)W3C標準盒模型:屬性width,height只包含內容content,不包含border和padding
(2)IE盒模型:屬性width,height包含content、border和padding,指的是content
+padding+border。
在ie8+瀏覽器中使用哪個盒模型可以由box-sizing(CSS新增的屬性)控制,默認值為content-box,即標準盒模型;
如果將box-sizing設為border-box則用的是IE盒模型。如果在ie6,7,8中DOCTYPE缺失會將盒子模型解釋為IE
盒子模型。若在頁面中聲明了DOCTYPE類型,所有的瀏覽器都會把盒模型解釋為W3C盒模型。

回答:

盒模型都是由四個部分組成的,分別是margin、border、padding和content。
標準盒模型和IE盒模型的區別在于設置width和height時,所對應的范圍不同。標準盒模型的width和height屬性的
范圍只包含了content,而IE盒模型的width和height屬性的范圍包含了border、padding和content。
一般來說,我們可以通過修改元素的box-sizing屬性來改變元素的盒模型。

詳細的資料可以參考:?《CSS 盒模型詳解》

2、CSS 選擇符有哪些?

(1)id選擇器(#myid)
(2)類選擇器(.myclassname)
(3)標簽選擇器(div,h1,p)
(4)后代選擇器(h1 p)
(5)相鄰后代選擇器(子)選擇器(ul>li)
(6)兄弟選擇器(li~a)
(7)相鄰兄弟選擇器(li+a)
(8)屬性選擇器(a[rel="external"])
(9)偽類選擇器(a:hover,li:nth-child)
(10)偽元素選擇器(::before、::after)
(11)通配符選擇器(*)

3、::before 和:after 中雙冒號和單冒號有什么區別?解釋一下這 2 個偽元素的作用。

相關知識點:

單冒號(:)用于CSS3偽類,雙冒號(::)用于CSS3偽元素。(偽元素由雙冒號和偽元素名稱組成)
雙冒號是在當前規范中引入的,用于區分偽類和偽元素。不過瀏覽器需要同時支持舊的已經存在的偽元素寫法,
比如:first-line、:first-letter、:before、:after等,
而新的在CSS3中引入的偽元素則不允許再支持舊的單冒號的寫法。
想讓插入的內容出現在其它內容前,使用::before,否者,使用::after;
在代碼順序上,::after生成的內容也比::before生成的內容靠后。
如果按堆棧視角,::after生成的內容會在::before生成的內容之上。

回答:

在css3中使用單冒號來表示偽類,用雙冒號來表示偽元素。但是為了兼容已有的偽元素的寫法,在一些瀏覽器中也可以使用單冒號
來表示偽元素。
偽類一般匹配的是元素的一些特殊狀態,如hover、link等,而偽元素一般匹配的特殊的位置,比如after、before等。

4、偽類與偽元素的區別

css引入偽類和偽元素概念是為了格式化文檔樹以外的信息。也就是說,偽類和偽元素是用來修飾不在文檔樹中的部分,比如,一句
話中的第一個字母,或者是列表中的第一個元素。
偽類用于當已有的元素處于某個狀態時,為其添加對應的樣式,這個狀態是根據用戶行為而動態變化的。比如說,當用戶懸停在指定的
元素時,我們可以通過:hover來描述這個元素的狀態。
偽元素用于創建一些不在文檔樹中的元素,并為其添加樣式。它們允許我們為元素的某些部分設置樣式。比如說,我們可以通過::be
fore來在一個元素前增加一些文本,并為這些文本添加樣式。雖然用戶可以看到這些文本,但是這些文本實際上不在文檔樹中。
有時你會發現偽元素使用了兩個冒號(::)而不是一個冒號(:)。這是CSS3的一部分,并嘗試區分偽類和偽元素。大多數瀏覽
器都支持這兩個值。按照規則應該使用(::)而不是(:),從而區分偽類和偽元素。但是,由于在舊版本的W3C規范并未對此進行
特別區分,因此目前絕大多數的瀏覽器都支持使用這兩種方式表示偽元素。

詳細資料可以參考:?《總結偽類與偽元素》

5、CSS 中哪些屬性可以繼承?

相關資料:

每個CSS屬性定義的概述都指出了這個屬性是默認繼承的,還是默認不繼承的。這決定了當你沒有為元素的屬性指定值時該如何計算
值。
當元素的一個繼承屬性沒有指定值時,則取父元素的同屬性的計算值。只有文檔根元素取該屬性的概述中給定的初始值(這里的意思應
該是在該屬性本身的定義中的默認值)。
當元素的一個非繼承屬性(在Mozilla code里有時稱之為reset property)沒有指定值時,則取屬性的初始值initial v
alue(該值在該屬性的概述里被指定)。
有繼承性的屬性:
(1)字體系列屬性
font、font-family、font-weight、font-size、font-style、font-variant、font-stretch、font-size-adjust
(2)文本系列屬性
text-indent、text-align、text-shadow、line-height、word-spacing、letter-spacing、
text-transform、direction、color
(3)表格布局屬性
caption-side border-collapse empty-cells
(4)列表屬性
list-style-type、list-style-image、list-style-position、list-style
(5)光標屬性
cursor
(6)元素可見性
visibility
(7)還有一些不常用的;speak,page,設置嵌套引用的引號類型quotes等屬性
注意:當一個屬性不是繼承屬性時,可以使用inherit關鍵字指定一個屬性應從父元素繼承它的值,inherit關鍵字用于顯式地
指定繼承性,可用于任何繼承性/非繼承性屬性。

回答:

每一個屬性在定義中都給出了這個屬性是否具有繼承性,一個具有繼承性的屬性會在沒有指定值的時候,會使用父元素的同屬性的值
來作為自己的值。
一般具有繼承性的屬性有,字體相關的屬性,font-size和font-weight等。文本相關的屬性,color和text-align等。
表格的一些布局屬性、列表屬性如list-style等。還有光標屬性cursor、元素可見性visibility。
當一個屬性不是繼承屬性的時候,我們也可以通過將它的值設置為inherit來使它從父元素那獲取同名的屬性值來繼承。

詳細的資料可以參考:?《繼承屬性》?《CSS 有哪些屬性可以繼承?》

6、CSS 優先級算法如何計算?

相關知識點:

CSS的優先級是根據樣式聲明的特殊性值來判斷的。
選擇器的特殊性值分為四個等級,如下:
(1)標簽內選擇符x,0,0,0
(2)ID選擇符0,x,0,0
(3)class選擇符/屬性選擇符/偽類選擇符  0,0,x,0
(4)元素和偽元素選擇符0,0,0,x
計算方法:
(1)每個等級的初始值為0
(2)每個等級的疊加為選擇器出現的次數相加
(3)不可進位,比如0,99,99,99
(4)依次表示為:0,0,0,0
(5)每個等級計數之間沒關聯
(6)等級判斷從左向右,如果某一位數值相同,則判斷下一位數值
(7)如果兩個優先級相同,則最后出現的優先級高,!important也適用
(8)通配符選擇器的特殊性值為:0,0,0,0
(9)繼承樣式優先級最低,通配符樣式優先級高于繼承樣式
(10)!important(權重),它沒有特殊性值,但它的優先級是最高的,為了方便記憶,可以認為它的特殊性值為1,0,0,0,0。
計算實例:
(1)#demo a{color: orange;}/*特殊性值:0,1,0,1*/
(2)div#demo a{color: red;}/*特殊性值:0,1,0,2*/
注意:
(1)樣式應用時,css會先查看規則的權重(!important),加了權重的優先級最高,當權重相同的時候,會比較規則的特殊性。
(2)特殊性值越大的聲明優先級越高。
(3)相同特殊性值的聲明,根據樣式引入的順序,后聲明的規則優先級高(距離元素出現最近的)
 (4) 部分瀏覽器由于字節溢出問題出現的進位表現不做考慮

回答:

判斷優先級時,首先我們會判斷一條屬性聲明是否有權重,也就是是否在聲明后面加上了!important。一條聲明如果加上了權重,
那么它的優先級就是最高的,前提是它之后不再出現相同權重的聲明。如果權重相同,我們則需要去比較匹配規則的特殊性。
一條匹配規則一般由多個選擇器組成,一條規則的特殊性由組成它的選擇器的特殊性累加而成。選擇器的特殊性可以分為四個等級,
第一個等級是行內樣式,為1000,第二個等級是id選擇器,為0100,第三個等級是類選擇器、偽類選擇器和屬性選擇器,為0010,
第四個等級是元素選擇器和偽元素選擇器,為0001。規則中每出現一個選擇器,就將它的特殊性進行疊加,這個疊加只限于對應的等
級的疊加,不會產生進位。選擇器特殊性值的比較是從左向右排序的,也就是說以1開頭的特殊性值比所有以0開頭的特殊性值要大。
比如說特殊性值為1000的的規則優先級就要比特殊性值為0999的規則高。如果兩個規則的特殊性值相等的時候,那么就會根據它們引
入的順序,后出現的規則的優先級最高。

對于組合聲明的特殊性值計算可以參考:?《CSS 優先級計算及應用》?《CSS 優先級計算規則》?《有趣:256 個 class 選擇器可以干掉 1 個 id 選擇器》

7、關于偽類 LVHA 的解釋?

a標簽有四種狀態:鏈接訪問前、鏈接訪問后、鼠標滑過、激活,分別對應四種偽類:link、:visited、:hover、:active;
當鏈接未訪問過時:
(1)當鼠標滑過a鏈接時,滿足:link和:hover兩種狀態,要改變a標簽的顏色,就必須將:hover偽類在:link偽
類后面聲明;
(2)當鼠標點擊激活a鏈接時,同時滿足:link、:hover、:active三種狀態,要顯示a標簽激活時的樣式(:active),
必須將:active聲明放到:link和:hover之后。因此得出LVHA這個順序。
當鏈接訪問過時,情況基本同上,只不過需要將:link換成:visited。
這個順序能不能變?可以,但也只有:link和:visited可以交換位置,因為一個鏈接要么訪問過要么沒訪問過,不可能同時滿足,
也就不存在覆蓋的問題。

8、CSS3 新增偽類有那些?

(1)elem:nth-child(n)選中父元素下的第n個子元素,并且這個子元素的標簽名為elem,n可以接受具體的數
值,也可以接受函數。
(2)elem:nth-last-child(n)作用同上,不過是從后開始查找。
(3)elem:last-child選中最后一個子元素。
(4)elem:only-child如果elem是父元素下唯一的子元素,則選中之。
(5)elem:nth-of-type(n)選中父元素下第n個elem類型元素,n可以接受具體的數值,也可以接受函數。
(6)elem:first-of-type選中父元素下第一個elem類型元素。
(7)elem:last-of-type選中父元素下最后一個elem類型元素。
(8)elem:only-of-type如果父元素下的子元素只有一個elem類型元素,則選中該元素。
(9)elem:empty選中不包含子元素和內容的elem類型元素。
(10)elem:target選擇當前活動的elem元素。
(11):not(elem)選擇非elem元素的每個元素。
(12):enabled 控制表單控件的禁用狀態。
(13):disabled  控制表單控件的禁用狀態。
(14):checked單選框或復選框被選中。

詳細的資料可以參考:?《CSS3 新特性總結(偽類)》?《淺談 CSS 偽類和偽元素及 CSS3 新增偽類》

9、如何居中 div?

-水平居中:給 div 設置一個寬度,然后添加 margin:0 auto 屬性

div {
 width: 200px;
 margin: 0 auto;
}

-水平居中,利用 text-align:center 實現

.container {
 background: rgba(0, 0, 0, 0.5);
 text-align: center;
 font-size: 0;
}
.box {
 display: inline-block;
 width: 500px;
 height: 400px;
 background-color: pink;
}

-讓絕對定位的 div 居中

div {
 position: absolute;
 width: 300px;
 height: 300px;
 margin: auto;
 top: 0;
 left: 0;
 bottom: 0;
 right: 0;
 background-color: pink; /*方便看效果*/
}

-水平垂直居中一

/*確定容器的寬高寬500高300的層設置層的外邊距div{*/
position: absolute;/*絕對定位*/
width: 500px;
height: 300px;
top: 50%;
left: 50%;
margin: -150px00-250px;/*外邊距為自身寬高的一半*/
background-color: pink;/*方便看效果*/
}

-水平垂直居中二

/*未知容器的寬高,利用`transform`屬性*/
div {
 position: absolute; /*相對定位或絕對定位均可*/
 width: 500px;
 height: 300px;
 top: 50%;
 left: 50%;
 transform: translate(-50%, -50%);
 background-color: pink; /*方便看效果*/
}

-水平垂直居中三

/*利用flex布局實際使用時應考慮兼容性*/
.container {
 display: flex;
 align-items: center; /*垂直居中*/
 justify-content: center; /*水平居中*/
}
.containerdiv {
 width: 100px;
 height: 100px;
 background-color: pink; /*方便看效果*/
}

-水平垂直居中四

/*利用text-align:center和vertical-align:middle屬性*/
.container {
 position: fixed;
 top: 0;
 right: 0;
 bottom: 0;
 left: 0;
 background: rgba(0, 0, 0, 0.5);
 text-align: center;
 font-size: 0;
 white-space: nowrap;
 overflow: auto;
}
.container::after {
 content: '';
 display: inline-block;
 height: 100%;
 vertical-align: middle;
}
.box {
 display: inline-block;
 width: 500px;
 height: 400px;
 background-color: pink;
 white-space: normal;
 vertical-align: middle;
}

回答:

一般常見的幾種居中的方法有:
對于寬高固定的元素
(1)我們可以利用margin:0 auto來實現元素的水平居中。
(2)利用絕對定位,設置四個方向的值都為0,并將margin設置為auto,由于寬高固定,因此對應方向實現平分,可以實現水
平和垂直方向上的居中。
(3)利用絕對定位,先將元素的左上角通過top:50%和left:50%定位到頁面的中心,然后再通過margin負值來調整元素
的中心點到頁面的中心。
(4)利用絕對定位,先將元素的左上角通過top:50%和left:50%定位到頁面的中心,然后再通過translate來調整元素
的中心點到頁面的中心。
(5)使用flex布局,通過align-items:center和justify-content:center設置容器的垂直和水平方向上為居中對
齊,然后它的子元素也可以實現垂直和水平的居中。
對于寬高不定的元素,上面的后面兩種方法,可以實現元素的垂直和水平的居中。

10、display 有哪些值?說明他們的作用。

block  塊類型。默認寬度為父元素寬度,可設置寬高,換行顯示。
none  元素不顯示,并從文檔流中移除。
inline  行內元素類型。默認寬度為內容寬度,不可設置寬高,同行顯示。
inline-block 默認寬度為內容寬度,可以設置寬高,同行顯示。
list-item  像塊類型元素一樣顯示,并添加樣式列表標記。
table  此元素會作為塊級表格來顯示。
inherit  規定應該從父元素繼承display屬性的值。

詳細資料可以參考:?《CSS display 屬性》
11、position 的值 relative 和 absolute 定位原點是?

相關知識點:

absolute
生成絕對定位的元素,相對于值不為static的第一個父元素的padding box進行定位,也可以理解為離自己這一級元素最近的
一級position設置為absolute或者relative的父元素的padding box的左上角為原點的。
fixed(老IE不支持)
生成絕對定位的元素,相對于瀏覽器窗口進行定位。
relative
生成相對定位的元素,相對于其元素本身所在正常位置進行定位。
static
默認值。沒有定位,元素出現在正常的流中(忽略top,bottom,left,right,z-index聲明)。
inherit
規定從父元素繼承position屬性的值。

回答:

relative定位的元素,是相對于元素本身的正常位置來進行定位的。
absolute定位的元素,是相對于它的第一個position值不為static的祖先元素的padding box來進行定位的。這句話
我們可以這樣來理解,我們首先需要找到絕對定位元素的一個position的值不為static的祖先元素,然后相對于這個祖先元
素的padding box來定位,也就是說在計算定位距離的時候,padding的值也要算進去。

12、CSS3 有哪些新特性?(根據項目回答)

新增各種CSS選擇器  (:not(.input):所有class不是“input”的節點)
圓角    (border-radius:8px)
多列布局  (multi-column layout)
陰影和反射  (ShadowReflect)
文字特效    (text-shadow)
文字渲染    (Text-decoration)
線性漸變    (gradient)
旋轉      (transform)
縮放,定位,傾斜,動畫,多背景
例如:transform:scale(0.85,0.90)translate(0px,-30px)skew(-9deg,0deg)Animation:

13、請解釋一下 CSS3 的 Flex box(彈性盒布局模型),以及適用場景?

相關知識點:

Flex是FlexibleBox的縮寫,意為"彈性布局",用來為盒狀模型提供最大的靈活性。
任何一個容器都可以指定為Flex布局。行內元素也可以使用Flex布局。注意,設為Flex布局以后,子元素的float、cl
ear和vertical-align屬性將失效。
采用Flex布局的元素,稱為Flex容器(flex container),簡稱"容器"。它的所有子元素自動成為容器成員,稱為Flex
項目(flex item),簡稱"項目"。
容器默認存在兩根軸:水平的主軸(main axis)和垂直的交叉軸(cross axis),項目默認沿主軸排列。
以下6個屬性設置在容器上。
flex-direction屬性決定主軸的方向(即項目的排列方向)。
flex-wrap屬性定義,如果一條軸線排不下,如何換行。
flex-flow屬性是flex-direction屬性和flex-wrap屬性的簡寫形式,默認值為row nowrap。
justify-content屬性定義了項目在主軸上的對齊方式。
align-items屬性定義項目在交叉軸上如何對齊。
align-content屬性定義了多根軸線的對齊方式。如果項目只有一根軸線,該屬性不起作用。
以下6個屬性設置在項目上。
order屬性定義項目的排列順序。數值越小,排列越靠前,默認為0。
flex-grow屬性定義項目的放大比例,默認為0,即如果存在剩余空間,也不放大。
flex-shrink屬性定義了項目的縮小比例,默認為1,即如果空間不足,該項目將縮小。
flex-basis屬性定義了在分配多余空間之前,項目占據的主軸空間。瀏覽器根據這個屬性,計算主軸是否有多余空間。它的默認
值為auto,即項目的本來大小。
flex屬性是flex-grow,flex-shrink和flex-basis的簡寫,默認值為0 1 auto。
align-self屬性允許單個項目有與其他項目不一樣的對齊方式,可覆蓋align-items屬性。默認值為auto,表示繼承父
元素的align-items屬性,如果沒有父元素,則等同于stretch。

回答:

flex布局是CSS3新增的一種布局方式,我們可以通過將一個元素的display屬性值設置為flex從而使它成為一個flex
容器,它的所有子元素都會成為它的項目。
一個容器默認有兩條軸,一個是水平的主軸,一個是與主軸垂直的交叉軸。我們可以使用flex-direction來指定主軸的方向。
我們可以使用justify-content來指定元素在主軸上的排列方式,使用align-items來指定元素在交叉軸上的排列方式。還
可以使用flex-wrap來規定當一行排列不下時的換行方式。
對于容器中的項目,我們可以使用order屬性來指定項目的排列順序,還可以使用flex-grow來指定當排列空間有剩余的時候,
項目的放大比例。還可以使用flex-shrink來指定當排列空間不足時,項目的縮小比例。

詳細資料可以參考:?《Flex 布局教程:語法篇》?《Flex 布局教程:實例篇》

14、用純 CSS 創建一個三角形的原理是什么?

采用的是相鄰邊框連接處的均分原理。
 將元素的寬高設為0,只設置
 border
 ,把任意三條邊隱藏掉(顏色設為
 transparent),剩下的就是一個三角形。
 #demo {
 width: 0;
 height: 0;
 border-width: 20px;
 border-style: solid;
 border-color: transparent transparent red transparent;
}

15.一個滿屏品字布局如何設計?

簡單的方式:
 上面的div寬100%,
 下面的兩個div分別寬50%,
 然后用float或者inline使其不換行即可

16、CSS?多列等高如何實現?

(1)利用padding-bottom|margin-bottom正負值相抵,不會影響頁面布局的特點。設置父容器設置超出隱藏(overflow:
hidden),這樣父容器的高度就還是它里面的列沒有設定padding-bottom時的高度,當它里面的任一列高度增加了,則
父容器的高度被撐到里面最高那列的高度,其他比這列矮的列會用它們的padding-bottom補償這部分高度差。
(2)利用table-cell所有單元格高度都相等的特性,來實現多列等高。
(3)利用flex布局中項目align-items屬性默認為stretch,如果項目未設置高度或設為auto,將占滿整個容器的高度
的特性,來實現多列等高。

詳細資料可以參考:?《前端應該掌握的 CSS 實現多列等高布局》?《CSS:多列等高布局》

17、經常遇到的瀏覽器的兼容性有哪些?原因,解決方法是什么,常用 hack 的技巧?

(1)png24位的圖片在iE6瀏覽器上出現背景
解決方案:做成PNG8,也可以引用一段腳本處理。
(2)瀏覽器默認的margin和padding不同
解決方案:加一個全局的*{margin:0;padding:0;}來統一。
(3)IE6雙邊距bug:在IE6下,如果對元素設置了浮動,同時又設置了margin-left或
margin-right,margin值會加倍。
#box{float:left;width:10px;margin:0 0 0 10px;}
這種情況之下IE會產生20px的距離
解決方案:在float的標簽樣式控制中加入_display:inline;將其轉化為行內屬性。(_這個符號只有ie6會識別)
(4)漸進識別的方式,從總體中逐漸排除局部。
首先,巧妙的使用"9"這一標記,將IE游覽器從所有情況中分離出來。
接著,再次使用"+"將IE8和IE7、IE6分離開來,這樣IE8已經獨立識別。
.bb{
background-color:#f1ee18;/*所有識別*/
.background-color:#00deff9;/*IE6、7、8識別*/
+background-color:#a200ff;/*IE6、7識別*/
_background-color:#1e0bd1;/*IE6識別*/
}
(5)IE下,可以使用獲取常規屬性的方法來獲取自定義屬性,也可以使用getAttribute()獲取自定義
屬性;Firefox下,只能使用getAttribute()獲取自定義屬性
解決方法:統一通過getAttribute()獲取自定義屬性。
(6)IE下,event對象有x、y屬性,但是沒有pageX、pageY屬性;Firefox下,event對象有
pageX、pageY屬性,但是沒有x、y屬性。
解決方法:(條件注釋)缺點是在IE瀏覽器下可能會增加額外的HTTP請求數。
(7)Chrome中文界面下默認會將小于12px的文本強制按照12px顯示
解決方法:
1.可通過加入CSS屬性-webkit-text-size-adjust:none;解決。但是,在chrome
更新到27版本之后就不可以用了。
2.還可以使用-webkit-transform:scale(0.5);注意-webkit-transform:scale(0.75);
收縮的是整個span的大小,這時候,必須要將span轉換成塊元素,可以使用display:block/inline-block/...;
(8)超鏈接訪問過后hover樣式就不出現了,被點擊訪問過的超鏈接樣式不再具有hover和active了
解決方法:改變CSS屬性的排列順序L-V-H-A
(9)怪異模式問題:漏寫DTD聲明,Firefox仍然會按照標準模式來解析網頁,但在IE中會觸發怪異模
式。為避免怪異模式給我們帶來不必要的麻煩,最好養成書寫DTD聲明的好習慣。

18、li 與 li 之間有看不見的空白間隔是什么原因引起的?有什么解決辦法?

瀏覽器會把inline元素間的空白字符(空格、換行、Tab等)渲染成一個空格。而為了美觀。我們通常是一個<li>放在一行,
這導致<li>換行后產生換行字符,它變成一個空格,占用了一個字符的寬度。
解決辦法:
(1)為<li>設置float:left。不足:有些容器是不能設置浮動,如左右切換的焦點圖等。
(2)將所有<li>寫在同一行。不足:代碼不美觀。
(3)將<ul>內的字符尺寸直接設為0,即font-size:0。不足:<ul>中的其他字符尺寸也被設為0,需要額外重新設定其他
字符尺寸,且在Safari瀏覽器依然會出現空白間隔。
(4)消除<ul>的字符間隔letter-spacing:-8px,不足:這也設置了<li>內的字符間隔,因此需要將<li>內的字符
間隔設為默認letter-spacing:normal。

詳細資料可以參考:?《li 與 li 之間有看不見的空白間隔是什么原因引起的?》

19、為什么要初始化 CSS 樣式?

-因為瀏覽器的兼容問題,不同瀏覽器對有些標簽的默認值是不同的,如果沒對CSS初始化往往會出現瀏覽器之間的頁面顯示差異。
-當然,初始化樣式會對SEO有一定的影響,但魚和熊掌不可兼得,但力求影響最小的情況下初始化。
最簡單的初始化方法:*{padding:0;margin:0;}(強烈不建議)
淘寶的樣式初始化代碼:
body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend
,button,input,textarea,th,td{margin:0;padding:0;}
body,button,input,select,textarea{font:12px/1.5tahoma,arial,5b8b4f53;}
h1,h2,h3,h4,h5,h6{font-size:100%;}
address,cite,dfn,em,var{font-style:normal;}
code,kbd,pre,samp{font-family:couriernew,courier,monospace;}
small{font-size:12px;}
ul,ol{list-style:none;}
a{text-decoration:none;}
a:hover{text-decoration:underline;}
sup{vertical-align:text-top;}
sub{vertical-align:text-bottom;}
legend{color:#000;}
fieldset,img{border:0;}
button,input,select,textarea{font-size:100%;}
table{border-collapse:collapse;border-spacing:0;}

20、什么是包含塊,對于包含塊的理解?

包含塊(containing block)就是元素用來計算和定位的一個框。
(1)根元素(很多場景下可以看成是<html>)被稱為“初始包含塊”,其尺寸等同于瀏覽器可視窗口的大小。
(2)對于其他元素,如果該元素的position是relative或者static,則“包含塊”由其最近的塊容器祖先盒的content box
邊界形成。
(3)如果元素position:fixed,則“包含塊”是“初始包含塊”。
(4)如果元素position:absolute,則“包含塊”由最近的position不為static的祖先元素建立,具體方式如下:
如果該祖先元素是純inline元素,則規則略復雜:
?假設給內聯元素的前后各生成一個寬度為0的內聯盒子(inline box),則這兩個內聯盒子的padding box外面的包
圍盒就是內聯元素的“包含塊”;
?如果該內聯元素被跨行分割了,那么“包含塊”是未定義的,也就是CSS2.1規范并沒有明確定義,瀏覽器自行發揮
否則,“包含塊”由該祖先的padding box邊界形成。
如果沒有符合條件的祖先元素,則“包含塊”是“初始包含塊”。

21.CSS 里的 visibility 屬性有個 collapse 屬性值是干嘛用的?

在不同瀏覽器下以后什么區別?

(1)對于一般的元素,它的表現跟visibility:hidden;是一樣的。元素是不可見的,但此時仍占用頁面空間。
(2)但例外的是,如果這個元素是table相關的元素,例如table行,table group,table列,table column group,它的
表現卻跟display:none一樣,也就是說,它們占用的空間也會釋放。
在不同瀏覽器下的區別:
在谷歌瀏覽器里,使用collapse值和使用hidden值沒有什么區別。
在火狐瀏覽器、Opera和IE11里,使用collapse值的效果就如它的字面意思:table的行會消失,它的下面一行會補充它的位
置。

詳細資料可以參考:?《CSS 里的 visibility 屬性有個鮮為人知的屬性值:collapse》22、width:auto 和 width:100%的區別

一般而言
width:100%會使元素box的寬度等于父元素的content box的寬度。
width:auto會使元素撐滿整個父元素,margin、border、padding、content區域會自動分配水平空間。

23、絕對定位元素與非絕對定位元素的百分比計算的區別

絕對定位元素的寬高百分比是相對于臨近的position不為static的祖先元素的padding box來計算的。
非絕對定位元素的寬高百分比則是相對于父元素的content box來計算的。

24、簡單介紹使用圖片?base64?編碼的優點和缺點。

base64編碼是一種圖片處理格式,通過特定的算法將圖片編碼成一長串字符串,在頁面上顯示的時候,可以用該字符串來代替圖片的
url屬性。
使用base64的優點是:
(1)減少一個圖片的HTTP請求
使用base64的缺點是:
(1)根據base64的編碼原理,編碼后的大小會比原文件大小大1/3,如果把大圖片編碼到html/css中,不僅會造成文件體
積的增加,影響文件的加載速度,還會增加瀏覽器對html或css文件解析渲染的時間。
(2)使用base64無法直接緩存,要緩存只能緩存包含base64的文件,比如HTML或者CSS,這相比域直接緩存圖片的效果要
差很多。
(3)兼容性的問題,ie8以前的瀏覽器不支持。
一般一些網站的小圖標可以使用base64圖片來引入。

詳細資料可以參考:?《玩轉圖片 base64 編碼》?《前端開發中,使用 base64 圖片的弊端是什么?》?《小 tip:base64:URL 背景圖片與 web 頁面性能優化》

25、'display'、'position'和'float'的相互關系?

(1)首先我們判斷display屬性是否為none,如果為none,則position和float屬性的值不影響元素最后的表現。
(2)然后判斷position的值是否為absolute或者fixed,如果是,則float屬性失效,并且display的值應該被
設置為table或者block,具體轉換需要看初始轉換值。
(3)如果position的值不為absolute或者fixed,則判斷float屬性的值是否為none,如果不是,則display
的值則按上面的規則轉換。注意,如果position的值為relative并且float屬性的值存在,則relative相對
于浮動后的最終位置定位。
(4)如果float的值為none,則判斷元素是否為根元素,如果是根元素則display屬性按照上面的規則轉換,如果不是,
則保持指定的display屬性值不變。
總的來說,可以把它看作是一個類似優先級的機制,"position:absolute"和"position:fixed"優先級最高,有它存在
的時候,浮動不起作用,'display'的值也需要調整;其次,元素的'float'特性的值不是"none"的時候或者它是根元素
的時候,調整'display'的值;最后,非根元素,并且非浮動元素,并且非絕對定位的元素,'display'特性值同設置值。

詳細資料可以參考:?《position 跟 display、margincollapse、overflow、float 這些特性相互疊加后會怎么樣?》

26、margin 重疊問題的理解。

相關知識點:

塊級元素的上外邊距(margin-top)與下外邊距(margin-bottom)有時會合并為單個外邊距,這樣的現象稱為“margin合
并”。
產生折疊的必備條件:margin必須是鄰接的!
而根據w3c規范,兩個margin是鄰接的必須滿足以下條件:
?必須是處于常規文檔流(非float和絕對定位)的塊級盒子,并且處于同一個BFC當中。
?沒有線盒,沒有空隙,沒有padding和border將他們分隔開
?都屬于垂直方向上相鄰的外邊距,可以是下面任意一種情況
?元素的margin-top與其第一個常規文檔流的子元素的margin-top
?元素的margin-bottom與其下一個常規文檔流的兄弟元素的margin-top
?height為auto的元素的margin-bottom與其最后一個常規文檔流的子元素的margin-bottom
?高度為0并且最小高度也為0,不包含常規文檔流的子元素,并且自身沒有建立新的BFC的元素的margin-top
和margin-bottom
margin合并的3種場景:
(1)相鄰兄弟元素margin合并。
解決辦法:
?設置塊狀格式化上下文元素(BFC)
(2)父級和第一個/最后一個子元素的margin合并。
解決辦法:
對于margin-top合并,可以進行如下操作(滿足一個條件即可):
?父元素設置為塊狀格式化上下文元素;
?父元素設置border-top值;
?父元素設置padding-top值;
?父元素和第一個子元素之間添加內聯元素進行分隔。
對于margin-bottom合并,可以進行如下操作(滿足一個條件即可):
?父元素設置為塊狀格式化上下文元素;
?父元素設置border-bottom值;
?父元素設置padding-bottom值;
?父元素和最后一個子元素之間添加內聯元素進行分隔;
?父元素設置height、min-height或max-height。
(3)空塊級元素的margin合并。
解決辦法:
?設置垂直方向的border;
?設置垂直方向的padding;
?里面添加內聯元素(直接Space鍵空格是沒用的);
?設置height或者min-height。

回答:

margin重疊指的是在垂直方向上,兩個相鄰元素的margin發生重疊的情況。
一般來說可以分為四種情形:
第一種是相鄰兄弟元素的marin-bottom和margin-top的值發生重疊。這種情況下我們可以通過設置其中一個元素為BFC
來解決。
第二種是父元素的margin-top和子元素的margin-top發生重疊。它們發生重疊是因為它們是相鄰的,所以我們可以通過這
一點來解決這個問題。我們可以為父元素設置border-top、padding-top值來分隔它們,當然我們也可以將父元素設置為BFC
來解決。
第三種是高度為auto的父元素的margin-bottom和子元素的margin-bottom發生重疊。它們發生重疊一個是因為它們相
鄰,一個是因為父元素的高度不固定。因此我們可以為父元素設置border-bottom、padding-bottom來分隔它們,也可以為
父元素設置一個高度,max-height和min-height也能解決這個問題。當然將父元素設置為BFC是最簡單的方法。
第四種情況,是沒有內容的元素,自身的margin-top和margin-bottom發生的重疊。我們可以通過為其設置border、pa
dding或者高度來解決這個問題。

27、對?BFC?規范(塊級格式化上下文:block?formatting?context)的理解?

相關知識點:

塊格式化上下文(Block Formatting Context,BFC)是Web頁面的可視化CSS渲染的一部分,是布局過程中生成塊級盒
子的區域,也是浮動元素與其他元素的交互限定區域。
通俗來講
?BFC是一個獨立的布局環境,可以理解為一個容器,在這個容器中按照一定規則進行物品擺放,并且不會影響其它環境中的物品。
?如果一個元素符合觸發BFC的條件,則BFC中的元素布局不受外部影響。
創建BFC
(1)根元素或包含根元素的元素
(2)浮動元素float=left|right或inherit(≠none)
(3)絕對定位元素position=absolute或fixed
(4)display=inline-block|flex|inline-flex|table-cell或table-caption
(5)overflow=hidden|auto或scroll(≠visible)

回答:

BFC指的是塊級格式化上下文,一個元素形成了BFC之后,那么它內部元素產生的布局不會影響到外部元素,外部元素的布局也
不會影響到BFC中的內部元素。一個BFC就像是一個隔離區域,和其他區域互不影響。
一般來說根元素是一個BFC區域,浮動和絕對定位的元素也會形成BFC,display屬性的值為inline-block、flex這些
屬性時也會創建BFC。還有就是元素的overflow的值不為visible時都會創建BFC。

詳細資料可以參考:?《深入理解 BFC 和 MarginCollapse》?《前端面試題-BFC(塊格式化上下文)》

28、IFC 是什么?

IFC指的是行級格式化上下文,它有這樣的一些布局規則:
(1)行級上下文內部的盒子會在水平方向,一個接一個地放置。
(2)當一行不夠的時候會自動切換到下一行。
(3)行級上下文的高度由內部最高的內聯盒子的高度決定。

詳細資料可以參考:?《[譯]:BFC 與 IFC》?《BFC 和 IFC 的理解(布局)》

29、請解釋一下為什么需要清除浮動?清除浮動的方式

浮動元素可以左右移動,直到遇到另一個浮動元素或者遇到它外邊緣的包含框。浮動框不屬于文檔流中的普通流,當元素浮動之后,
不會影響塊級元素的布局,只會影響內聯元素布局。此時文檔流中的普通流就會表現得該浮動框不存在一樣的布局模式。當包含框
的高度小于浮動框的時候,此時就會出現“高度塌陷”。
清除浮動是為了清除使用浮動元素產生的影響。浮動的元素,高度會塌陷,而高度的塌陷使我們頁面后面的布局不能正常顯示。
清除浮動的方式
(1)使用clear屬性清除浮動。參考28。
(2)使用BFC塊級格式化上下文來清除浮動。參考26。
因為BFC元素不會影響外部元素的特點,所以BFC元素也可以用來清除浮動的影響,因為如果不清除,子元素浮動則父元素高度塌陷,必然會影響后面元素布局和定位,這顯然有違BFC元素的子元素不會影響外部元素的設定。

30、使用?clear?屬性清除浮動的原理?

使用clear屬性清除浮動,其語法如下:
clear:none|left|right|both
如果單看字面意思,clear:left應該是“清除左浮動”,clear:right應該是“清除右浮動”的意思,實際上,這種解釋是有問
題的,因為浮動一直還在,并沒有清除。
官方對clear屬性的解釋是:“元素盒子的邊不能和前面的浮動元素相鄰?!?,我們對元素設置clear屬性是為了避免浮動元素
對該元素的影響,而不是清除掉浮動。
還需要注意的一點是clear屬性指的是元素盒子的邊不能和前面的浮動元素相鄰,注意這里“前面的”3個字,也就是clear屬
性對“后面的”浮動元素是不聞不問的??紤]到float屬性要么是left,要么是right,不可能同時存在,同時由于clear
屬性對“后面的”浮動元素不聞不問,因此,當clear:left有效的時候,clear:right必定無效,也就是此時clear:left
等同于設置clear:both;同樣地,clear:right如果有效也是等同于設置clear:both。由此可見,clear:left和cle
ar:right這兩個聲明就沒有任何使用的價值,至少在CSS世界中是如此,直接使用clear:both吧。
一般使用偽元素的方式清除浮動
.clear::after{
content:'';
display:table;//也可以是'block',或者是'list-item'
clear:both;
}
clear屬性只有塊級元素才有效的,而::after等偽元素默認都是內聯水平,這就是借助偽元素清除浮動影響時需要設置disp
lay屬性值的原因。

31、zoom:1?的清除浮動原理?

清除浮動,觸發hasLayout;
zoom屬性是IE瀏覽器的專有屬性,它可以設置或檢索對象的縮放比例。解決ie下比較奇葩的bug。譬如外邊距(margin)
的重疊,浮動清除,觸發ie的haslayout屬性等。
來龍去脈大概如下:
當設置了zoom的值之后,所設置的元素就會就會擴大或者縮小,高度寬度就會重新計算了,這里一旦改變zoom值時其實也會發
生重新渲染,運用這個原理,也就解決了ie下子元素浮動時候父元素不隨著自動擴大的問題。
zoom屬性是IE瀏覽器的專有屬性,火狐和老版本的webkit核心的瀏覽器都不支持這個屬性。然而,zoom現在已經被逐步標
準化,出現在CSS3.0規范草案中。
目前非ie由于不支持這個屬性,它們又是通過什么屬性來實現元素的縮放呢?可以通過css3里面的動畫屬性scale進行縮放。

32、移動端的布局用過媒體查詢嗎?

假設你現在正用一臺顯示設備來閱讀這篇文章,同時你也想把它投影到屏幕上,或者打印出來,而顯示設備、屏幕投影和打印等這些
媒介都有自己的特點,CSS就是為文檔提供在不同媒介上展示的適配方法
當媒體查詢為真時,相關的樣式表或樣式規則會按照正常的級聯規被應用。當媒體查詢返回假,標簽上帶有媒體查詢的樣式表仍將被
下載(只不過不會被應用)。
包含了一個媒體類型和至少一個使用寬度、高度和顏色等媒體屬性來限制樣式表范圍的表達式。CSS3加入的媒體查詢使得無需修改
內容便可以使樣式應用于某些特定的設備范圍。

詳細資料可以參考:?《CSS3@media 查詢》?《響應式布局和自適應布局詳解》

33、使用 CSS 預處理器嗎?喜歡哪個?

SASS(SASS、LESS沒有本質區別,只因為團隊前端都是用的SASS)

34、CSS?優化、提高性能的方法有哪些?

加載性能:
(1)css壓縮:將寫好的css進行打包壓縮,可以減少很多的體積。
(2)css單一樣式:當需要下邊距和左邊距的時候,很多時候選擇:margin:top 0 bottom 0;但margin-bottom:bot
tom;margin-left:left;執行的效率更高。
(3)減少使用@import,而建議使用link,因為后者在頁面加載時一起加載,前者是等待頁面加載完成之后再進行加載。
選擇器性能:
(1)關鍵選擇器(key selector)。選擇器的最后面的部分為關鍵選擇器(即用來匹配目標元素的部分)。CSS選擇符是從右到
左進行匹配的。當使用后代選擇器的時候,瀏覽器會遍歷所有子元素來確定是否是指定的元素等等;
(2)如果規則擁有ID選擇器作為其關鍵選擇器,則不要為規則增加標簽。過濾掉無關的規則(這樣樣式系統就不會浪費時間去匹
配它們了)。
(3)避免使用通配規則,如*{}計算次數驚人!只對需要用到的元素進行選擇。
(4)盡量少的去對標簽進行選擇,而是用class。
(5)盡量少的去使用后代選擇器,降低選擇器的權重值。后代選擇器的開銷是最高的,盡量將選擇器的深度降到最低,最高不要超過
三層,更多的使用類來關聯每一個標簽元素。
(6)了解哪些屬性是可以通過繼承而來的,然后避免對這些屬性重復指定規則。
渲染性能:
(1)慎重使用高性能屬性:浮動、定位。
(2)盡量減少頁面重排、重繪。
(3)去除空規則:{}??找巹t的產生原因一般來說是為了預留樣式。去除這些空規則無疑能減少css文檔體積。
(4)屬性值為0時,不加單位。
(5)屬性值為浮動小數0.**,可以省略小數點之前的0。
(6)標準化各種瀏覽器前綴:帶瀏覽器前綴的在前。標準屬性在后。
(7)不使用@import前綴,它會影響css的加載速度。
(8)選擇器優化嵌套,盡量避免層級過深。
(9)css雪碧圖,同一頁面相近部分的小圖標,方便使用,減少頁面的請求次數,但是同時圖片本身會變大,使用時,優劣考慮清
楚,再使用。
(10)正確使用display的屬性,由于display的作用,某些樣式組合會無效,徒增樣式體積的同時也影響解析性能。
(11)不濫用web字體。對于中文網站來說WebFonts可能很陌生,國外卻很流行。web fonts通常體積龐大,而且一些瀏
覽器在下載web fonts時會阻塞頁面渲染損傷性能。
可維護性、健壯性:
(1)將具有相同屬性的樣式抽離出來,整合并通過class在頁面中進行使用,提高css的可維護性。
(2)樣式與內容分離:將css代碼定義到外部css中。

詳細資料可以參考:?《CSS 優化、提高性能的方法有哪些?》?《CSS 優化,提高性能的方法》

35、瀏覽器是怎樣解析 CSS 選擇器的?

樣式系統從關鍵選擇器開始匹配,然后左移查找規則選擇器的祖先元素。只要選擇器的子樹一直在工作,樣式系統就會持續左移,直
到和規則匹配,或者是因為不匹配而放棄該規則。
試想一下,如果采用從左至右的方式讀取CSS規則,那么大多數規則讀到最后(最右)才會發現是不匹配的,這樣做會費時耗能,
最后有很多都是無用的;而如果采取從右向左的方式,那么只要發現最右邊選擇器不匹配,就可以直接舍棄了,避免了許多無效匹配。

詳細資料可以參考:?《探究 CSS 解析原理》

36、在網頁中應該使用奇數還是偶數的字體?為什么呢?

(1)偶數字號相對更容易和web設計的其他部分構成比例關系。比如:當我用了14px的正文字號,我可能會在一些地方用14
×0.5=7px的margin,在另一些地方用14×1.5=21px的標題字號。
(2)瀏覽器緣故,低版本的瀏覽器ie6會把奇數字體強制轉化為偶數,即13px渲染為14px。
(3)系統差別,早期的Windows里,中易宋體點陣只有12和14、15、16px,唯獨缺少13px。

詳細資料可以參考:?《談談網頁中使用奇數字體和偶數字體》?《現在網頁設計中的為什么少有人用 11px、13px、15px 等奇數的字體?》

37、margin 和 padding 分別適合什么場景使用?

margin是用來隔開元素與元素的間距;padding是用來隔開元素與內容的間隔。
margin用于布局分開元素使元素與元素互不相干。
padding用于元素與內容之間的間隔,讓內容(文字)與(包裹)元素之間有一段距離。
何時應當使用margin:
?需要在border外側添加空白時。
?空白處不需要背景(色)時。
?上下相連的兩個盒子之間的空白,需要相互抵消時。如15px+20px的margin,將得到20px的空白。
何時應當時用padding:
?需要在border內測添加空白時。
?空白處需要背景(色)時。
?上下相連的兩個盒子之間的空白,希望等于兩者之和時。如15px+20px的padding,將得到35px的空白。

38、抽離樣式模塊怎么寫,說出思路,有無實踐經驗?[阿里航旅的面試題]

我的理解是把常用的css樣式單獨做成css文件……通用的和業務相關的分離出來,通用的做成樣式模塊兒共享,業務相關的,放
進業務相關的庫里面做成對應功能的模塊兒。

詳細資料可以參考:?《CSS 規范-分類方法》

39、簡單說一下 css3 的 all 屬性。

all屬性實際上是所有CSS屬性的縮寫,表示,所有的CSS屬性都怎樣怎樣,但是,不包括unicode-bidi和direction
這兩個CSS屬性。支持三個CSS通用屬性值,initial,inherit,unset。
initial是初始值的意思,也就是該元素元素都除了unicode-bidi和direction以外的CSS屬性都使用屬性的默認初始
值。
inherit是繼承的意思,也就是該元素除了unicode-bidi和direction以外的CSS屬性都繼承父元素的屬性值。
unset是取消設置的意思,也就是當前元素瀏覽器或用戶設置的CSS忽略,然后如果是具有繼承特性的CSS,如color,則
使用繼承值;如果是沒有繼承特性的CSS屬性,如background-color,則使用初始值。

詳細資料可以參考:?《簡單了解 CSS3 的 all 屬性》

40、為什么不建議使用統配符初始化 css 樣式。

采用*{padding:0;margin:0;}這樣的寫法好處是寫起來很簡單,但是是通配符,需要把所有的標簽都遍歷一遍,當網站較大時,
樣式比較多,這樣寫就大大的加強了網站運行的負載,會使網站加載的時候需要很長一段時間,因此一般大型的網站都有分層次的一
套初始化樣式。
出于性能的考慮,并不是所有標簽都會有padding和margin,因此對常見的具有默認padding和margin的元素初始化即
可,并不需使用通配符*來初始化。

41、absolute?的?containingblock(包含塊)計算方式跟正常流有什么不同?

(1)內聯元素也可以作為“包含塊”所在的元素;
(2)“包含塊”所在的元素不是父塊級元素,而是最近的position不為static的祖先元素或根元素;
(3)邊界是padding box而不是content box。

42、對于?hasLayout?的理解?

hasLayout是IE特有的一個屬性。很多的IE下的css bug都與其息息相關。在IE中,一個元素要么自己對自身的內容進
行計算大小和組織,要么依賴于父元素來計算尺寸和組織內容。當一個元素的hasLayout屬性值為true時,它負責對自己和可
能的子孫元素進行尺寸計算和定位。雖然這意味著這個元素需要花更多的代價來維護自身和里面的內容,而不是依賴于祖先元素來完
成這些工作。

詳細資料可以參考:?《CSS 基礎篇--CSS 中 IE 瀏覽器的 hasLayout,IE 低版本的 bug 根源》?《CSS 魔法堂:hasLayout 原來是這樣的!》

43、元素豎向的百分比設定是相對于容器的高度嗎?

如果是height的話,是相對于包含塊的高度。
如果是padding或者margin豎直方向的屬性則是相對于包含塊的寬度。

44、全屏滾動的原理是什么?用到了?CSS?的哪些屬性?(待深入實踐)

原理:有點類似于輪播,整體的元素一直排列下去,假設有5個需要展示的全屏頁面,那么高度是500%,只是展示100%,容器及容
器內的頁面取當前可視區高度,同時容器的父級元素overflow屬性值設為hidden,通過更改容器可視區的位置來實現全
屏滾動效果。主要是響應鼠標事件,頁面通過CSS的動畫效果,進行移動。
overflow:hidden;transition:all 1000 ms ease;

詳細資料可以參考:?《js 實現網頁全屏切換(平滑過渡),鼠標滾動切換》?《用 ES6 寫全屏滾動插件》

45、什么是響應式設計?響應式設計的基本原理是什么?如何兼容低版本的 IE?(待深入了解)

響應式網站設計是一個網站能夠兼容多個終端,而不是為每一個終端做一個特定的版本?;驹硎峭ㄟ^媒體查詢檢測不同的設備屏
幕尺寸做處理。頁面頭部必須有meta聲明的viewport。

詳細資料可以參考:?《響應式布局原理》?《響應式布局的實現方法和原理》

46、視差滾動效果,如何給每頁做不同的動畫?(回到頂部,向下滑動要再次出現,和只出現一次分別怎么做?)

視差滾動是指多層背景以不同的速度移動,形成立體的運動效果,帶來非常出色的視覺體驗。

詳細資料可以參考:?《如何實現視差滾動效果的網頁?》

47、如何修改 chrome 記住密碼后自動填充表單的黃色背景?

chrome表單自動填充后,input文本框的背景會變成黃色的,通過審查元素可以看到這是由于chrome會默認給自動填充的in
put表單加上input:-webkit-autofill私有屬性,然后對其賦予以下樣式:
{
background-color:rgb(250,255,189)!important;
background-image:none!important;
color:rgb(0,0,0)!important;
}
對chrome默認定義的background-color,background-image,color使用important是不能提高其優先級的,但是
其他屬性可使用。
使用足夠大的純色內陰影來覆蓋input輸入框的黃色背景,處理如下
input:-webkit-autofill,textarea:-webkit-autofill,select:-webkit-autofill{
-webkit-box-shadow:000px 1000px white inset;
border:1px solid #CCC !important;
}

詳細資料可以參考:?《去掉 chrome 記住密碼后的默認填充樣式》?《修改谷歌瀏覽器 chrome 記住密碼后自動填充表單的黃色背景》

48、怎么讓 Chrome 支持小于 12px 的文字?

在谷歌下css設置字體大小為12px及以下時,顯示都是一樣大小,都是默認12px。
解決辦法:
(1)可以使用Webkit的內核的-webkit-text-size-adjust的私有CSS屬性來解決,只要加了-webkit-text-size
-adjust:none;字體大小就不受限制了。但是chrome更新到27版本之后就不可以用了。所以高版本chrome谷歌瀏覽器
已經不再支持-webkit-text-size-adjust樣式,所以要使用時候慎用。
(2)還可以使用css3的transform縮放屬性-webkit-transform:scale(0.5);注意-webkit-transform:scale(0.
75);收縮的是整個元素的大小,這時候,如果是內聯元素,必須要將內聯元素轉換成塊元素,可以使用display:block/
inline-block/...;
(3)使用圖片:如果是內容固定不變情況下,使用將小于12px文字內容切出做圖片,這樣不影響兼容也不影響美觀。

詳細資料可以參考:?《谷歌瀏覽器不支持 CSS 設置小于 12px 的文字怎么辦?》

49、讓頁面里的字體變清晰,變細用 CSS 怎么做?

webkit內核的私有屬性:-webkit-font-smoothing,用于字體抗鋸齒,使用后字體看起來會更清晰舒服。
在MacOS測試環境下面設置-webkit-font-smoothing:antialiased;但是這個屬性僅僅是面向MacOS,其他操作系統設
置后無效。

詳細資料可以參考:?《讓字體變的更清晰 CSS 中-webkit-font-smoothing》

50、font-style 屬性中 italic 和 oblique 的區別?

italic和oblique這兩個關鍵字都表示“斜體”的意思。
它們的區別在于,italic是使用當前字體的斜體字體,而oblique只是單純地讓文字傾斜。如果當前字體沒有對應的斜體字體,
則退而求其次,解析為oblique,也就是單純形狀傾斜。
查看原文

贊 1 收藏 1 評論 0

小蘑菇 發布了文章 · 1月29日

vue el-select 全選 多選

兩種方式:
方式一:el-select可多選可單選,選擇全部后不能選擇其他,具體參照如下代碼:

<el-select size="middle" clearable v-model="form.ground"  @change="handlePlat" placeholder="請選擇小組" filterable multiple  style="width: 400px;">
  <el-option label="全部" value="全部"></el-option>
  <el-option v-for="(item, index) in groundList" :key="index" :label="item.name" :value="String(item.id)" :disabled="item.disabled"></el-option>
</el-select>

handlePlat(){
  if (this.form.ground.indexOf("全部") == "-1") {
    this.groundList.map((res) => {
      res.disabled = false;
    });
  } else {
    this.groundList.map((res) => {
      res.disabled = true;
    });
    this.form.ground = ["全部"];
  }
}

方式二:如果想要選擇所有選項時,得一個個去點擊,這樣不是很方便,我們可以在下拉框里新增一個選擇所有的選項,通過watch用幾行代碼就可以實現與其它選項的互斥來實現一鍵多選,如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script data-original="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
    <link rel="stylesheet" >
    <script data-original="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
    <div id="app">
        <el-form>
            <el-form-item>
                <el-select placeholder="請選擇活動區域" multiple v-model="citys">
                    <el-option label="選擇所有" value="all"></el-option>
                    <el-option v-for="item in cities" :label="item.label" :value="item.value" :key="item.value"></el-option>
                </el-select>
              </el-form-item>
          </el-form>
    </div>
    <script>
        new Vue({
            el:"#app",
            data:{
                cities: [
                    {value: 'Beijing',label: '北京'}, 
                    {value: 'Shanghai',label: '上海'}, 
                    {value: 'Nanjing',label: '南京'}, 
                    {value: 'Chengdu',label: '成都'}, 
                    {value: 'Shenzhen',label: '深圳'}, 
                    {value: 'Guangzhou',label: '廣州'}
                ],
                citys:[]
            },
            watch:{
                citys:function(val,oldval){
                    //獲取val和oldval里all的索引,如果沒有則返回-1
                    let newindex = val.indexOf('all'),oldindex = oldval.indexOf('all'); 
                    if(newindex!=-1 && oldindex==-1 && val.length>1) //如果新的選擇里有勾選了選擇所有選擇所有 則 只直線勾選所有整個選項
                        this.citys=['all']; else if(newindex!=-1 && oldindex!=-1 && val.length>1) //如果操作前有勾選了選擇所有且當前也選中了勾選所有且勾選數量大于1  則移除掉勾選所有
                        this.citys.splice(val.indexOf('all'),1)                    
                }
            }
        }) 
     </script>
</body>
</html>
查看原文

贊 0 收藏 0 評論 1

小蘑菇 發布了文章 · 1月27日

vue項目實現剪切板功能(vue-clipboard2)

方法/步驟:

1. 安裝vue-clipboard2插件

npm install --save vue-clipboard2 

image.png

2. 查看配置文件package.json,檢查vue-clipboard2是否安裝成功
image.png

3. 啟動服務 npm run dev
image.png

4. main.js添加

import Vue
import VueClipboard from 'vue-clipboard2'
Vue.use(VueClipboard)

image.png

5. copy組件

v-clipboard:copy="message"
v-clipboard:success="onCopy"
v-clipboard:error="onError"

image.png

6. 查看效果
點擊按鈕,彈框顯示了copy的內容,后兩張圖是在微信的輸入框中測驗剛剛的copy是否真的復制到了剪切板中。
image.png
image.png
image.png

注:以上方式:已測過,可用

查看原文

贊 0 收藏 0 評論 0

小蘑菇 發布了文章 · 1月25日

CSS3網頁小實例

第一種效果:

image
html代碼:

<input class="search" type="text" placeholder="搜索...">

CSS代碼:

.search{
    width:80px;
    height:40px;
    border-radius:40px;
    border:2px solid lightblue;
    position: absolute;
    right:200px;
    outline:none;
    text-indent:12px;
    color:#666;
    font-size:16px;
    padding:0;
    -webkit-transition:width 0.5s;
}
.search:focus{
    width:200px;
}
第二種效果:

image
html代碼:

<div class="banner">
    <a href="javascript:;">博</a>
    <span>這是我的個人博客</span>
</div>

CSS代碼:

.banner{
    width:234px;
    height:34px;
    border-radius:34px;
    position:absolute;
    top:400px;
    left:200px;
}
.banner a{
    display:inline-block;
    width:30px;
    height:30px;
    line-height:30px;
    border-radius:50%;
    border:2px solid lightblue;
    position:absolute;
    left:0px;top:0px;
    background:lightgreen;
    color:#fff;
    text-align:center;
    text-decoration:none;
    cursor:pointer;
    z-index:2;
}
.banner a:hover + span{
    -webkit-transform:rotate(360deg);
    opacity:1;
}
.banner span{
    display:inline-block;
    width:auto;
    padding:0 20px;
    height:34px;
    line-height:34px;
    background:lightblue;
    border-radius:34px;
    text-align: center;
    position:absolute;
    color:#fff;
    text-indent:25px;
    opacity:0;
    -webkit-transform-origin:8% center;
    -webkit-transition:all 1s;
}
第三種效果:

image
html代碼:

<div class="banner1">
    <a href="javascript:;">博</a>
    <span>這是我的個人博客</span>
</div>

CSS代碼:

.banner1{
    width:234px;
    height:34px;
    border-radius:40px;
    position:absolute;
    top:400px;
    left:600px;
}
.banner1 a{
    display:inline-block;
    width:30px;
    height:30px;
    line-height:30px;
    border-radius:50%;
    border:2px solid lightblue;
    position:absolute;
    left:0px;top:0px;
    background:lightgreen;
    color:#fff;
    text-align:center;
    text-decoration:none;
    cursor:pointer;
    z-index:2;
}
.banner1 a:hover + span{
    -webkit-transform:translateX(40px);
    opacity:1;
}
.banner1 span{
    display:inline-block;
    width:auto;
    padding:0 20px;
    height:30px;line-height:30px;
    background:lightblue;
    border-radius:30px;
    text-align: center;
    color:#fff;
    position:absolute;
    top:2px;
    opacity:0;
    -webkit-transition:all 1s;
    -webkit-transform:translateX(80px);
}
第四種效果:

image
html結構:

<div class="wrapper">
    <div class="round">
        <span>東邪</span>
        <span>西毒</span>
        <span>南乞</span>
        <span>北丐</span>
    </div>
</div>

CSS代碼:

.wrapper{
    width:100px;
    height:100px;
    background:lightblue;
    border-radius:50%;
    border:2px solid lightgreen;
    position: absolute;
    top:200px;
    left:400px;
    cursor:pointer;
}
.wrapper:after{
    content:'你猜';
    display:inline-block;
    width:100px;
    height:100px;
    line-height:100px;
    border-radius:50%;
    text-align:center;
    color:#fff;
    font-size:24px;
}
.wrapper:hover .round{
    -webkit-transform:scale(1);
    opacity:1;
    -webkit-animation:rotating 6s 1.2s linear infinite alternate;
}
@-webkit-keyframes rotating{
    0%{
        -webkit-transform:rotate(0deg);
    }
    100%{
        -webkit-transform:rotate(180deg);
    }
}
.round{
    width:240px;
    height:240px;
    border:2px solid lightgreen;
    border-radius:50%;
    position: absolute;
    top:-70px;
    left:-70px;
    -webkit-transition:all 1s;
    -webkit-transform:scale(0.35);
    opacity:0;
}
.round span{
    width:40px;
    height:40px;
    line-height:40px;
    display:inline-block;
    border-radius:50%;
    background:lightblue;
    border:2px solid lightgreen;
    color:#fff;
    text-align:center;
    position:absolute;
}
.round span:nth-child(1){
    right:-22px;
    top:50%;
    margin-top:-22px;
}
.round span:nth-child(2){
    left:-22px;
    top:50%;
    margin-top:-22px;
}
.round span:nth-child(3){
    left:50%;
    bottom:-22px;
    margin-left:-22px;
}
.round span:nth-child(4){
    left:50%;
    top:-22px;
    margin-left:-22px;
}
查看原文

贊 0 收藏 0 評論 0

小蘑菇 發布了文章 · 1月25日

Git 常用命令

以免后期忘記,故筆記整理。

1、復制遠程代碼到本地

git clone url

2、查看本地分支列表

git branch

3、查看所有分支列表(包括本地和遠程)

git branch -a

4、拉取當前分支的遠程變更,以及遠程中其他分支的更新信息

git pull

5、新建分支并切換到新分支

git checkout -b xxx

6、切換分支

git checkout xxx

7、合并分支,將 xxx 分支合并到當前分支

git merge xxx

8、將當前分支所有變更添加到暫存區

git add .

9、將暫存區的所有文件提交到本地倉庫

git commit -m ""

10、將本地倉庫的變更提交到遠程倉庫

git push

11、查看當前分支變更狀態

git status

12、臨時保存當前變更

git stash

13、取出最近一次保存的當前變更

git stash pop

14、獲取遠程已刪除分支(更新遠程分支緩存)

git fetch -p origin

速查表:
image.png

查看原文

贊 1 收藏 1 評論 0

小蘑菇 發布了文章 · 1月15日

Loading 制作方案

一、通過border-radius繪制圓環

<div class="loading-css"></div>

.loading-css {
    width: 50px;
    /*先將loading區域變成正方形*/
    height: 50px;
    display: inline-block;
    /*將loading區域變成行內元素,防止旋轉的時候,100%寬度都在旋轉*/
    border: 3px solid #f3f3f3;
    /*設置四周邊框大小,并將顏色設置為淺白色*/
    border-top: 3px solid red;
    /*將上邊框顏色設置為紅色高亮,以便旋轉的時候能夠看到旋轉的效果*/
    border-radius: 50%;
    /*將邊框和內容區域都變成圓形*/
}

@keyframes loading-360 {
    0% {
        transform: rotate(0deg); /*動畫起始的時候旋轉了0度*/
    }
    100% {
        transform: rotate(360deg); /*動畫結束的時候旋轉了360度*/
    }
}

.loading-css { /*在之前的CSS中加上動畫效果即可*/
    animation: loading-360 0.8s infinite linear; /*給圓環添加旋轉360度的動畫,并且是無限次*/
}

此時效果如下:
image.png

二、通過svg來繪制圓環

<svg viewBox="0 0 50 50" class="loading-svg">
    <circle cx="25" cy="25" r="20" fill="none" class="path"></circle>
</svg>

.loading-svg {
    width: 50px; /*設置svg顯示區域大小*/
    height: 50px;
    animation: loading-rotate 1.5s infinite ease-in-out; /*給svg也加上一個旋轉動畫*/
}
.path {
    stroke: #409eff; /*給畫筆設置一個顏色*/
    stroke-width: 2; /*設置線條的寬度*/
    stroke-dasharray: 95, 126; /*設置實現長95,虛線長126*/
    stroke-dashoffset: 0; /*設置虛線的偏移位置*/
    animation: loading-dash 1.5s ease-in-out infinite;
}
@keyframes loading-dash {
    0% {
        stroke-dasharray: 1, 126; /*實線部分1,虛線部分126*/
        stroke-dashoffset: 0; /*前面1/126顯示實線,后面125顯示空白*/
    }

    50% {
        stroke-dasharray: 95, 126; /*實線部分95,虛線部分126*/
        stroke-dashoffset: -31px /*順時針偏移31/126,即前31/126顯示空白,后面3/4顯示線條*/
    }

    to {
        stroke-dasharray: 6, 120; /*實線部分6,虛線部分120*/
        stroke-dashoffset: -120px; /*最后順時針偏移120/126,即前120/126顯示空白,后面6點顯示線條部分*/
    }
}
@keyframes loading-rotate {
    to {
        transform: rotate(1turn); // 旋轉1圈
    }
}

此時效果如下:
image.png

三、通過iconfont字體圖標
可以直接通過iconfont字體圖標代替圓環的繪制,直接以字體的形式顯示出圓環,然后給其加上旋轉動畫即可,如:
我們可以在iconfont網站上下載喜歡的Loading圖案。字體圖標下載后,將解壓后的內容拷貝到項目中,并引入其中的iconfont.css到頁面中,給要顯示字體圖標的元素加上iconfont類樣式
image.png
具體代碼引入方式,可參考demo_index.html文件,里面有三種引入方式,我這邊目前采用的是第二種。
image.png
代碼如下:

<link rel="stylesheet" href="./font/iconfont.css">

<span class="icon-Loading iconfont"></span>

.icon-Loading {
    display: inline-block;
    color: #0086B3;
    font-size: 40px;
    animation: rotating 2s infinite linear;
}

@keyframes rotating {
    0% {
        transform: rotate(0deg) /*動畫起始位置為旋轉0度*/
    }

    to {
        transform: rotate(1turn) /*動畫結束位置為旋轉1圈*/
    }
}

此時效果如下:
image.png

查看原文

贊 0 收藏 0 評論 0

認證與成就

  • 獲得 145 次點贊
  • 獲得 2 枚徽章 獲得 0 枚金徽章, 獲得 0 枚銀徽章, 獲得 2 枚銅徽章

擅長技能
編輯

(??? )
暫時沒有

開源項目 & 著作
編輯

(??? )
暫時沒有

注冊于 2020-07-29
個人主頁被 2.9k 人瀏覽

一本到在线是免费观看_亚洲2020天天堂在线观看_国产欧美亚洲精品第一页_最好看的2018中文字幕 <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <文本链> <文本链> <文本链> <文本链> <文本链> <文本链>