笔试题记录

1. 空元素 Empty Element (滴滴笔试)

空元素是HTML/SVG里的不可能存在子节点的元素。
个人理解就是:自闭和标签

HTML中的空元素:

  • <br/> <hr> <img> <input/> <link> <meta>
  • <area> <source> <track> <wbr> <base> <param> <keygen> <col> <colgroup> <command> <embed>

2. <video src="movie.ogg" controls="controls"> (滴滴笔试)

<video>video是闭合标签</video>,不用必须指定宽高
类似,<audio></audio>也是闭合标签

videoaudio都有的属性:

  • autoplay loop src controls

3. 否定伪类 :not()

伪类pseudo Class为一个元素的特定状态应用样式
伪元素pseudo Element为一个元素的特定部分应用样式

伪类:

  • :active :hover :focus :visited :enabled disabled :invalid :lang() :not() :optional :out-of-range
  • :readonly :read-write :required :root :scope :target :valid
  • :checked :default :defined :empty :first :focus-within :host :indeterminate :in-range :left :link
  • 长子first-child 嫡长子first-of-type 幼子:last-child 嫡幼子:last-of-type
  • 自定义规则:nth-child() :nth-of-type() 从后往前:nth-last-child() :nth-last-of-type()
  • 独子:only-child :only-of-type

伪元素:

  • ::after ::before ::first-letter ::first-line ::selection ::slotted

4. 状态码 (头条面试)

301 永久移动
302 临时移动
304 Not Modified
502 Bad Gateway
503 Service Unavailable

5. 获取元素?getElementByLabel()?

document.getXXX系列:

  • getElementById() // id
  • getElementsByClassName() // 类名
  • getElementsByName() // name属性
  • getElementsByTagName() // 标签名
  • getElementsByTagNameNS() // 使用命名空间的XML文档

获取元素还有Selector:

  • document.queySelector()
  • document.querySelectorAll()

6. GET和POST区别 (腾讯、头条面试)

GET - 从指定的资源请求数据
POST - 向指定资源提交要被处理的数据

GET:

  • 请求可被缓存
  • 请求保留在浏览器历史记录中
  • 可被收藏成书签
  • 不应用于敏感数据
  • 请求有长度限制
  • 只应当用于取数据
  • 请求参数只能是ASCII码,所以需要encode编码

POST:

  • 请求不会被缓存
  • 不保留在历史记录中
  • 不能被收藏成书签
  • 对数据长度无要求

7. 死锁

死锁产生的四个必要条件:

  • 互斥条件
  • .不可剥夺条件
  • 请求和保持条件
  • 循环等待条件

死锁预防:

  • 破坏“不可剥夺”:一个进程不能获得所需的全部资源便处于等待状态,等待期间他占有的资源被隐式地释放
  • 破坏“请求与保持”:一、静态分配:每个进程在开始执行时就申请他所需的全部资源。二、动态分配:每个进程在申请所需资源时它本身不占用系统资源。
  • 破坏“循环等待”:按编号顺序进行

8. CSS优先级问题(伪类+属性选择器)

    <div class="main">
        <div class="test"></div>
    </div>
    <style>
        .main div{
            width: 200px;
            height: 200px;
            border: 1px red solid;
        }
        .test {
            border: 1px green solid;
        }
    </style>

.main div要比.test优先级高
ICE(Id > Class > Element)

伪类

    <div class="text">
        <p>伪类与类的优先级相等</p>
        <p>所以后者起作用</p>
    </div>
    <style>
        .text p{
            color: red;
        }
        p:first-child{
            color: green;
        }
    </style>

类和伪类优先级一致;元素和伪元素优先级一致

    <div>
        <p class="text" id="zpj">属性选择器</p>
    </div>
    <style>
        p[class="text"]{
            color: green;
        }
        [id="zpj"]{
            color: blue;
        }
        .text{
            color: red;
        }
    </style>

属性选择器的优先级等于类选择器

9. innerHTMLinnerText

共同点是都可以读写。
text表文本;html表格式;inner是标签内部;outer包含标签本身;value只用于input和textarea

  • innerText : 只要文本
  • innerHTML : HTML格式
  • outerText:包含标签自己
  • outerHTML :包含标签自己
  • value : input和textarea

10. 箭头函数

  1. 箭头函数更适用于那些本来需要匿名函数的地方
  2. 箭头函数不能用作构造函数
  3. 没有自己的this、arguments、super和new.target
  • 箭头函数不会创建自己的this,只能从自己的作用域链上一层继承this
  • 使用剩余参数相较于使用arguments是更好的选择
  • 箭头函数不要用作对象方法,this指向问题
  • 箭头函数没有prototype属性
  • 箭头函数不能使用yield关键字,不能用作生成器

高级用法:

// 加括号的函数体返回对象字面量
() => ({name: 'zpj'});
// 支持剩余参数和默认参数
(a =1,b =true,...rest) => {};
// 支持参数列表解构
([a,b]=[1,2], {name: c} ={name: a+b}) => a+b+c;

说到this,提一下setTimeout

setTimeout调用的代码运行在与所在函数完全分离的执行环境上。这会导致代码中的this指向window

bind改变this指向,只改变一次

new.target :在普通函数调用中,指向undefined; 在类的构造方法中,指向被new执行的构造函数

// 1. 使用new.target来保证构造函数正确使用
function Foo(){
    if(!new.target) throw "Foo() must be called with new";
    // construction
}

// 2. 使用instanceof & new操作符干了什么(作业帮面试)
function User(name, pw){
    var self = this instanceof User ? this : Object.create(User.prototype);
    self.name = name;
    self.password = pw;
    return self;
}

11. 能冒泡的事件

先说onaddEventListener/attachEvent的区别

  • on+事件,只能绑定一个事件,后面的会覆盖前面的
  • addEventListener(eventName, function, useCapture)可以绑定多个事件
  • 移除事件有removeEventListener/detachEvent()

事件模型一般分为capture -> target -> bubble 的过程
注意到useCapturetrue是在捕获阶段处理事件,默认false是在冒泡阶段处理事件

有的事件没有冒泡过程。每个event都有一个event.bubles属性,可以知道他是否可以冒泡。

不冒泡的事件有:

  • abort blur error focus load mouseenter mouseleave resize unload

12. 组合选择器 (美团面试)

  • A,B 任意选择器, 所有A or B
  • A B 后代选择器, A后代中的B
  • A>B 子选择器,A的第一代B
  • A+B 毗邻选择器,弟弟选择器,next-sibling,A后的第一个B

13. <input/>标签的type类型 (头条面试)

  • button checkbox color date datetime datetime-local email file hidden
  • image month number password radio range reset search submit
  • tel text ime url week

注意: 没有textarea<textarea> </textarea>是独立的一个标签

14. Array.from() Object.keys() (京东面试)

一、 Array.from(arrayLike, mapFunc, thisArg)

  • 字符串、set、map、arguments
    Array.from('foo');
    // ['f', 'o', 'o']
    let s = new Set(['foo', window]);
    Array.from(s);
    // ["foo", Window]
    let m = new Map([[1,2],[3,4],[5,6]]);
    Array.from(m);
    // [[1, 2], [2, 4], [4, 8]]
    function f(){
      return Array.from(arguments);
    }
    f(1,2,3);
    // [1,2,3]

    如何将arguments转化成真正的数组:

    1. Array.from(arguments)
    2. Array.prototype.slice.call(arguments)

说到arguments,讲一下arguments和函数形参的联系

在非严格模式下,arguments指向的是形参的引用地址,一个改变,另一个跟着改变;
严格模式下,arguments是静态副本,二者互相独立。

function add(a,b){
    console.log(a,b); // 1 2
    console.log(arguments); // 1 2
    arguments[0] = 10;
    console.log(a,b); // 10 2
    console.log(arguments); // 10 2
    return a+b;
}
add(1,2); // 12

// 严格模式
'use strict'
function add(a,b){
    console.log(a,b); // 1 2
    console.log(arguments); // 1 2
    arguments[0] = 10;
    console.log(a,b); // 1 2
    console.log(arguments); // 10 2
    return a+b;
}
add(1,2); // 3

二、Object.keys(obj)

  • 遍历自身的可枚举属性,顺序和for-in一致,区别在于for-in会遍历原型链上的可枚举属性
    // simple Array
    Object.keys([1,2,3]); // ['0', '1', '2']
    // array like object
    Object.keys({0: 1, 1: 2, 2: 3}); // ["0", "1", "2"]
    // array like object with random key ordering
    Object.keys({100: 'a', 2: 'b', 7: 'c'}); // ["2", "7", "100"]
    【注意】:想要拿到不可枚举属性,使用getOenPropertyNames()

    也就是说,遍历对象属性的三种方法

    1. for-in:遍历自身和原型链上的可枚举属性,一般配合hasOwnProperty()使用
    2. Object.keys():遍历自身的可枚举属性
    3. Object.getOwnPropertyNames():遍历自身的所有属性,包括不可枚举属性

15. instanceof运算符 typeof操作符 (京东面试)

一、 instanceof 测试构造函数的prototype属性是否出现在对象的原型链中的任何位置

object instanceof constructor检测constructor.prototype是否存在于object的原型链上
实际上就是在问:constructor.prototype.isPrototypeOf(object);

function Car(){};
var c = new Car();
c instanceof Car;
c instanceof Object; // Object.prototype.isPrototypeOf(c);

二、 typeof 返回操作数的类型

类型 结果
Undefined "undefined"
Null "object"
Boolean "boolean"
Number "number"
BigInt "bigint"
String "string"
Symbol "symbol"
Function "function"
其余复杂对象(如:数组,Set, Map) "object"
typeof NaN === "number"
typeof Number(1) === "number"
typeof null === "object"
typeof /s/g === "object"

三、 Object.prototype.toString.call()

  • 判断类型最全面的方法:返回值为 "[object Type]"
    Object.prototype.toString.call(1); // "[object Number]"
    Object.prototype.toString.call(/s/); // "[object RegExp]"

四、Array.isArray()判断数组
五、isNaN()判断NaN

16. 严格模式

问题 严格模式 非严格模式
with 禁止with 不禁止
变量声明 变量必须声明 未声明的变量将隐式声明为全局变量
this指向 普通函数(非方法、非构造函数)中的this指向undefined this指向全局对象
this指向 callapply传入nullundefined,保持原样 会被转换成全局对象
不可扩展 给只读属性和不可扩展对象创建新成员,抛错 静默失败
eval eval中不能定义变量和函数 变量和函数定义在新的作用域中
arguments arguments拥有参数的静态副本 arguments和参数指向同一个值
delete delete不可配置属性会抛错 静默失败,返回false
对象字面量 定义多个同名属性会报错 保留最后一个
函数多个同名参数 报错 最后一个为准
八进制字面量 禁止 允许
关键字 eval arguments 不能作变量名· -

17. 语义化 (头条面试)

  • 语义化的优点:
  1. 易于阅读,样式丢失也能呈现清晰的结构
  2. SEO,搜索引起根据标签来确定上下文和各个关键字的权重
  3. 便于多设备解析
  4. 利于代码维护
  • 常见语义化标签
    • <header> <nav> <main> <article> <aside> <footer> <section>

18. 宏任务和微任务(setTimeoutPromise 的区别)(快手面试)

  • Event Loop 事件循环有很多tick,每个tick包括一队宏任务和一队微任务
  • 传统异步(setTimeout)是事件循环(宏任务)
  • promise是任务队列(微任务)

任务队列是挂在事件循环队列的每个tick之后的一个队列。在事件循环的每个tick中,可能出现的异步动作不会导致一个完整的新事件添加到事件循环队列中,而是会生成一个微任务,挂在当前事件循环的后面。
事件循环队列类似于一个游乐园游戏:玩过了滑滑梯之后,你需要跑到队尾才能再玩一次。而任务队列等于玩过之后直接插队继续玩。

console.log(1); // 当前tick宏任务
setTimeout(function(){
    console.log(2); // 下一个tick宏任务
}, 0);
var p = new Promise(function(resolve, reject){
    console.log(3); // 当前tick宏任务
    resolve();
});
p.then(res => {
    console.log(4); // 当前tick微任务
});
console.log(5); // 当前tick宏任务
// 1 3 5 4 2

19. 强缓存和协商缓存 cache-control (头条面试)

请求设置
字段名 | 说明

  • | -
    no-cache | 告知(代理)服务器,不要直接使用缓存,要求向原服务器发起请求
    no-store | 所有内容不会被保存
    max-age=delta-seconds | 客户端会缓存delta秒

响应设置
字段名称 | 说明

  • | -
    public | 公开,任何情况下都缓存该资源
    must-revalidate | 当前资源一定是向原服务器发去验证的,请求失败返回504

20. JSON.parse() 解析数字 (360笔试)

  • 键:JSON中字段名只允许双引号包裹"name"
  • 值:数字直接写,字符串双引号
    JSON.parse('{"age": 23}'); // -> {age: 23}
    JSON.parse('{"age": "23"}'); // -> {age: "23"}

21. 默认inherit的css属性 (360笔试)

  • 并非所有未定义的css属性会默认inherit
  • color text-indent text-align line-height list-style-type list-style-image list-style cursor
  • direction word-spacing text-transform white-space border-collapse

22. url()的写法 (360笔试)

资源地址可以使用单引号或双引号包起来,也可以不使用任何引号

  • url('image.gif)
  • url("image.gif")
  • url(image.gif)

使用@import

  • @import url("global.css)
  • @import url(global.css)
  • @import "global.css"

23. for-infor-of的比较 (流利说面试)

一、forEach遍历数组,无法使用returnbreak挑出循环
二、for-in 遍历普通对象

  • index是字符串,而不是数字
  • 作用于数组的for-in循环还会遍历自定义属性,以及原型链属性
  • 随机顺序遍历数组

三、for-ofIterator

  • Iterator一是为各种数据结构提供一个统一的访问接口;二是使数据结构成员能按某种次序排序
  • for-of只遍历拥有Symbol.iterator属性的对象
  • 原生具备Iterator接口的数据结构: Array Map Set String TypedArray arguments NodeList
  • 阮一峰ES6

24. animation 动画 (美团面试)

@keyframes mymovie{
    from {top: 0px;}
    to {top: 200px;}
}
div {
    animation: mymovie 2s infinite;
    position: relative;
}

两件事:1. 定义关键帧; 2. animation播放设置
animation: name duration timing-function delay iteration-count direction;

描述
animation-name keyframe
animation-duration 持续时间,带单位 2s
animation-timing-function 速度曲线 linear ease ease-in ease-out ease-in-out
animation-delay 延迟 2s
animation-iteration-count 播放次数
animation-direction normal alternate

流利说面试:这道题还牵扯出top和transform的性能问题,transform合成计算,改变偏移量会引发回流重绘。

回流重绘的浏览器优化,维护队列,操作到了一定数量或者到了一定的时间,批处理一个队列。
添加删除可见元素,元素位置改变,尺寸改变,margin、padding、border、content、width、height的改变都会回流。
回流一定重绘,重绘不一定回流。

25. 返回顶部按钮(寒武纪面试)

两种思路:1. scroll API; 2. 锚点标记<a href="#top"></a>

        window.onscroll = function () {
            var scrollTop = document.documentElement.scrollTop;
            if (scrollTop < 1200) {
                document.querySelector('#topbtn').style.display = 'none';
            } else {
                document.querySelector('#topbtn').style.display = 'block';
            }
        }
        // 定时器实现思路
        document.querySelector('#topbtn').onclick = function () {
            var itvId = setInterval(function () {
                var scrollTop = document.documentElement.scrollTop;
                if (scrollTop > 0) {
                    window.scrollTo(0, scrollTop - 20);
                } else {
                    clearInterval(itvId);
                }
            }, 16);
        }
        // requestAnimationFrame
        document.querySelector('#topbtn').onclick = function () {
            (function smoothscroll() {
                var currentScroll = document.documentElement.scrollTop || document.body.scrollTop;
                if (currentScroll > 0) {
                    window.requestAnimationFrame(smoothscroll);
                    window.scrollTo(0, currentScroll - 20);
                }
            })();
        }

26. margin可以百分比吗?(爱奇艺笔试)

可以,基于父元素宽度的百分比,包括margin-top margin-bottom

padding同理。为什么不是高度的百分比,会导致无限循环。

27. 堆排序,建堆过程 (寒武纪面试)

堆是一颗完全二叉树

  • 完全二叉树Complete Binary Tree:除了最后一层外每一层都被填满,最后一层保持左对齐
  • 满二叉树Perfect Binary Tree:每一层都被填满
  • 满二叉树一定是完全二叉树;完全二叉树不一定是满二叉树

堆排序按原始顺序建立完全二叉树,然后找到第一个非叶子节点,从下至上开始不断调整大小顺序。完全二叉树从零开始排列,可以用一个数组表示,结点元素完全和序列挂钩。

// 建堆注意迭代,换完父节点,注意下一层节点还需要换,知道叶子结点
function bigHeap(array, i, length){
    // 不用建树,因为完全二叉树的节点和排序一一对应,所以直接用序列号即可
    while(i <= Math.floor(length)/2 - 1){ // i代表父节点,父节点在非叶子节点范围内则迭代
        let left = 2*i+1;
        let right = 2*i+2;
        let bigChild = left; // 记录被交换的节点序号
        if(right < length){
            if(array[right] > array[bigChild]){
                bigChild = right;
            }
        } 
        if(array[bigChild] > array[i]){
            let temp = array[bigChild];
            array[bigChild] = array[i];
            array[i] = temp;
        }
        // update
        i = bigChild; // 被交换的子节点向下迭代
    }
}

var a = [1,2,3,4,5,6,7,8];
// 初始化堆
for(let i = Math.floor(a.length/2)-1; i >= 0; i--){
    bigHeap(a, i, a.length); // 从后往前依次建堆
}
console.log(a);

// 堆排序的话,每次更换堆顶点与堆尾
for(let i = a.length - 1; i > 0; i --){
    let temp = a[i];
    a[i] = a[0];
    a[0] = temp;
    bigHeap(a, 0, i); // 从后往前依次建堆
}

28. 前端性能优化(寒武纪面试)

  • 减少请求资源大小和次数
    • 打包工具,合并压缩css和js
    • 图片资源懒加载,雪碧图
    • 缓存,减少cookie
  • 代码优化
    • 动画效果用css,不用js
    • 减少DOM操作,都是为了减少回流重绘渲染的时间
    • <script>defer和async,不阻塞渲染,提升首屏加载速度
  • 存储优化
    • 利用本地存储storage

29. 实现一个sleep()函数 (头条面试)

(async function(){
    // something A
    await sleep();
    // something B
})();

function sleep(seconds){
    return new Promise((resolve)=>{
        setTimeout( function(){ resolve(); }, seconds);
    });
}

30. let和var的区别 (流利说面试)

var age = 100;
let year = 6;
if(age > 12){
    let age = 10;
     var year = age * 3;
    console.log(age, year);
}
console.log(age, year)

输出:year 已经被声明
因为let会生成一个暂时性死区,在let形成的块级作用域中不能再声明同名变量。

31. 前端性能优化(寒武纪面试)

核心思想:

  1. 减少请求资源大小和请求次数: 打包工具,合并和压缩css和js;图片懒加载;
  2. 利用缓存和本地存储:storage/cookie/304
  3. 代码书写上的优化:使用css做效果不是js(合成计算);回流重绘;defer/async

32. 对称加密(奇安信笔试)

对称加密:加密和解密使用相同的密钥

  • DES(Data Encryption Standard) 数据加密标准,强度不够,能够暴力破解
  • 3DES 使用3个密钥进行DES加密,维护3个密钥,增加维护成本
  • AES(Advanced Encription Standard) 高级加密标准

33. animationtoptransform的区别 (流利说面试)

.animation{
    animation: myMovie 1s infinite;
}
@keyframes myMovie{
    0%: {top: 0;}  /* 或者 0%: { transform: translate(0, 0);} */
    25%:{top: 100px;}
    50%:{top: 200px;}
    75%:{top: 300px}
    100%:{top: 400px;}
}

transform动画由GPU控制,支持硬件加速,不需要软件方面的渲染
浏览器接收到页面文档后,会将文档中的标记语言解析为DOM树。DOM树和CSS树结合后形成浏览器构建页面的渲染树。渲染树中包含大量的渲染元素,每个渲染元素会被分到一个图层中,每个图层又会被加载到GPU形成渲染纹理。使用transform的图层不会触发repaint,最终都由独立的合成器进程进行处理。

  • 独立的复合图层

    • 3Dtransform
    • <video><canvas>
    • CSS filters
    • z-index
  • 可以触发GPU加速的CSS属性

    • transform
    • opacity
    • filter

34. mouse事件 (奇安信)

事件 描述
mousedown 鼠标按下
mouseup 鼠标弹起,鼠标释放
mousewheel 鼠标滚轮滚动
mouseout 鼠标移出
mouseover 鼠标移动到元素上
mousemove 鼠标在元素内移动

35. 值类型和引用类型 (招商银行面试)

var n = 1;
// instanceof 和 isPrototypeOf 需要的参数是对象object
n instanceof Number; // false
Number.prototype.isPrototypeOf(n); // false
// 隐式类型转换,原型链属性
n.__proto__ === Number.prototype; // true
n.constructor === Number; // true

值类型存储在栈内存中;引用类型存储在堆内存中
深拷贝和浅拷贝

36. a:linka:hover (海康威视笔试)

a标签定义超链接,href指向url,target表明打开方式
伪类:

  • link 未访问前的样式表属性
  • visited 已访问
  • hover 鼠标悬浮
  • active 鼠标按下,激活连接

定义顺序符合Love/Hate原则:LVHA

37. 多用局部变量,少用全局变量(海康笔试)

函数执行模型和标识符解析

  • 函数声明时会创建[[Scope]]属性,存储作用于信息,是一个对象Variable Object,列表中有可访问的变量。
  • 作用域链最前端是Activation Object , 最末端是全局对象Global Object
  • 函数被执行时会创建执行对象Execution Object
  • ==全局变量处在作用域链末端,查找变量的速度要比局部变量慢==

在美团面试时,还被问到了,作用域链中未查找到的变量最后会输出什么?

属性查找:静默失败(undefined)
变量查找:分为LHS和RHS
LHS查询:静默创建全局属性(非全局变量)
RHS查询:查不到报错(未声明)

// 不声明anything变量
window.anything; // undefined
anything; // ReferenceError: anything is not defined

// 属性查找:undefined
function run(){
    console.log(this.anything)
}
run(); // undefined

// 变量查找:RHS报错
function run(){
    console.log(anything);
}
run(); // ReferenceError: anything is not defined

// 变量查找:LHS静默创建全局属性
function run(){
    anything = 'zpj';
    console.log(anything);
}
run(); // 'zpj'

全局属性和全局变量的区别:

  • var声明全局变量的同时会自动创建同名全局属性,通过window.XXX访问
  • ==全局属性可以被delete删除,但是全局变量不可以==
function run(){
    anything = 'zpj';
    console.log(anything);
}
run(); // 'zpj'
anything; // 'zpj'
delete anything; // true
anything; // ReferenceError
var hahaha = 'zpj';
delete hahaha; // false
hahaha; // 'zpj'

38. substr()substring()的区别(海康笔试)

  • substr(start, length)
  • substring(start, stop) 从stop到stop-1的所有字符,不接受负参数
  • slice(start, end) 含首不含尾,负数表示从后往前
  • splice(start, length)

39. CSS前景色和背景色(度小满笔试)

前景就是文本和边框;当时选项里出现了foreground-color做干扰

前景色 color border-color : 前景包括文本和边框
背景色 background-color
透明度 opacity filter: alpha(opacity=80)

40. UNIQUEDISTINCT区别(度小满)

unique是建表时约束某列值唯一
distinct是查询时过滤重复

41. 什么是shell ?(度小满)

shell是系统跟计算机硬件交互时使用的中间介质。用户直接面对的不是计算机硬件,而是shell,用户把指令告诉shell,然后shell再传给系统内核,接着内核再去支配计算机硬件执行各种操作。

bash: linux默认安装的shell叫作bash,即Bourne Again ShellBourne Shell的增强版本。Bourne Shell是最早流行的一个shell,创始人是Steven Bourne

42. 提升性能(海康威视)

  • 减少HTTP请求(资源大小和请求次数):雪碧图,压缩合并js和css
  • 使用CDN(内容分发网略):选择最近的服务器
  • 缓存(Expires / cache-control: max-age)
  • 压缩(Accept-Encoding:gzip, deflate)(Content-Encoding: gzip)
  • 样式表放在头部(减少重绘)
  • 脚本放在底部(阻塞DOM树的更新)
  • 使用外部脚本和样式文件(重复利用)
  • DNS缓存(DNS域名解析)
  • 避免重定向(301/302)

43. 行内元素和块级元素的嵌套问题(海康)

p div h1-h6 form ul ol dl dd dt li table tr td th hr blockquote address header section article footer
块级元素:

  • 独占一行,没有宽高时默认100%
  • 块级元素允许设置宽高,width、height、margin、padding、border都可控制
  • 块级元素可以包含行内元素、块级元素

span a img input em b i q select textarea button
行内元素:

  • 行内元素不换行
  • 不能设置width、height、上下margin和上下padding
  • 默认宽度是content宽度
  • 行内元素只能包含文字、行内元素、行内块元素
  • display: inline-block; 行内块元素在行内元素的基础上,可以设置宽高width、height