一张图阐述一下Web前端开发的概要
HTML/CSS部分
1、什么是盒子模型?
在网页中,一个元素占有空间的大小由几个部分构成,其中包括元素的内容(content),元素的内边距(padding),元素的边框 (border),元素的外边距(margin)四个部分。这四个部分占有的空间中,有的部分可以显示相应的内容,而有的部分只用来分隔相邻的区域或区 域。4个部分一起构成了css中元素的盒模型。
2、行内元素有哪些?块级元素有哪些? 空(void)元素有那些?
行内元素:a、b、span、img、input、strong、select、label、em、button、textarea
块级元素:div、ul、li、dl、dt、dd、p、h1-h6、blockquote
空元素:即系没有内容的HTML元素,例如:br、meta、hr、link、input、img
3、CSS实现垂直水平居中
一道经典的问题,实现方法有很多种,以下是其中一种实现:
HTML结构:
1
2
3
|
<div class="wrapper">
<div class="content"></div>
</div>
|
CSS:
1
2
3
4
5
6
7
8
9
10
11
|
.wrapper{position:relative;}
.content{
background-color:#6699FF;
width:200px;
height:200px;
position: absolute; //父元素需要相对定位
top: 50%;
left: 50%;
margin-top:-100px ; //二分之一的height,width
margin-left: -100px;
}
|
4、简述一下src与href的区别
href 是指向网络资源所在位置,建立和当前元素(锚点)或当前文档(链接)之间的链接,用于超链接。
src是指向外部资源的位置,指向的内容将会嵌入到文档中当前标签所在位置;在请求src资源时会将其指向的资源下载并应用到文档内,例如js脚 本,img图片和frame等元素。当浏览器解析到该元素时,会暂停其他资源的下载和处理,直到将该资源加载、编译、执行完毕,图片和框架等元素也如此, 类似于将所指向资源嵌入当前标签内。这也是为什么将js脚本放在底部而不是头部。
5、什么是CSS Hack?
一般来说是针对不同的浏览器写不同的CSS,就是 CSS Hack。
IE浏览器Hack一般又分为三种,条件Hack、属性级Hack、选择符Hack(详细参考CSS文档:css文档)。例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// 1、条件Hack
<!--[if IE]>
.test{color:red;}
<![endif]-->
// 2、属性Hack
.test{
color:#0909; /* For IE8+ */
*color:#f00; /* For IE7 and earlier */
_color:#ff0; /* For IE6 and earlier */
}
// 3、选择符Hack
* html .test{color:#090;} /* For IE6 and earlier */
* + html .test{color:#ff0;} /* For IE7 */
|
6、简述同步和异步的区别
同步是阻塞模式,异步是非阻塞模式。
同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去;
异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。
7、px和em的区别
px和em都是长度单位,区别是,px的值是固定的,指定是多少就是多少,计算比较容易。em得值不是固定的,并且em会继承父级元素的字体大小。
浏览器的默认字体高都是16px。所以未经调整的浏览器都符合: 1em=16px。那么12px=0.75em, 10px=0.625em
8、什么叫优雅降级和渐进增强?
渐进增强 progressive enhancement:
针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。
优雅降级 graceful degradation:
一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。
区别:
a. 优雅降级是从复杂的现状开始,并试图减少用户体验的供给
b. 渐进增强则是从一个非常基础的,能够起作用的版本开始,并不断扩充,以适应未来环境的需要
c. 降级(功能衰减)意味着往回看;而渐进增强则意味着朝前看,同时保证其根基处于安全地带
9、浏览器的内核分别是什么?
IE: trident内核
Firefox:gecko内核
Safari:webkit内核
Opera:以前是presto内核,Opera现已改用Google Chrome的Blink内核
Chrome:Blink(基于webkit,Google与Opera Software共同开发)
JavaScript部分
1、怎样添加、移除、移动、复制、创建和查找节点?
1)创建新节点
createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点
2)添加、移除、替换、插入
appendChild() //添加
removeChild() //移除
replaceChild() //替换
insertBefore() //插入
3)查找
getElementsByTagName() //通过标签名称
getElementsByName() //通过元素的Name属性的值
getElementById() //通过元素Id,唯一性
2、实现一个函数clone,可以对JavaScript中的5种主要的数据类型(包括Number、String、Object、Array、Boolean)进行值复制。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
/**
* 对象克隆
* 支持基本数据类型及对象
* 递归方法
*/
function clone(obj) {
var o;
switch (typeof obj) {
case "undefined":
break;
case "string":
o = obj + "";
break;
case "number":
o = obj - 0;
break;
case "boolean":
o = obj;
break;
case "object": // object 分为两种情况 对象(Object)或数组(Array)
if (obj === null) {
o = null;
} else {
if (Object.prototype.toString.call(obj).slice(8, -1) === "Array") {
o = [];
for (var i = 0; i obj.length; i++) {
o.push(clone(obj[i]));
}
} else {
o = {};
for (var k in obj) {
o[k] = clone(obj[k]);
}
}
}
break;
default:
o = obj;
break;
}
return o;
}
|
3、如何消除一个数组里面重复的元素?
1
2
3
4
5
6
7
8
9
|
// 方法一:
var arr1 =[1,2,2,2,3,3,3,4,5,6],
arr2 = [];
for(var i = 0,len = arr1.length; i< len; i++){
if(arr2.indexOf(arr1[i]) < 0){
arr2.push(arr1[i]);
}
}
document.write(arr2); // 1,2,3,4,5,6
|
4、想实现一个对页面某个节点的拖曳?如何做?(使用原生JS)。
5、在Javascript中什么是伪数组?如何将伪数组转化为标准数组?
伪数组(类数组):无法直接调用数组方法或期望length属性有什么特殊的行为,但仍可以对真正数组遍历方法来遍历它们。典型的是函数的 argument参数,还有像调用getElementsByTagName,document.childNodes之类的,它们都返回 NodeList对象都属于伪数组。可以使用Array.prototype.slice.call(fakeArray)将数组转化为真正的Array 对象。
1
2
3
4
5
6
7
|
function log(){
var args = Array.prototype.slice.call(arguments);
//为了使用unshift数组方法,将argument转化为真正的数组
args.unshift('(app)');
console.log.apply(console, args);
};
|
6、Javascript中callee和caller的作用?
caller是返回一个对函数的引用,该函数调用了当前函数;
callee是返回正在被执行的function函数,也就是所指定的function对象的正文。
7、请描述一下cookies,sessionStorage和localStorage的区别
sessionStorage用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也 随之销毁。因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储。而localStorage用于持久化的本地存储,除非主 动删除数据,否则数据是永远不会过期的。
web storage和cookie的区别
Web Storage的概念和cookie相似,区别是它是为了更大容量存储设计的。Cookie的大小是受限的,并且每次你请求一个新的页面的时候Cookie都会被发送过去,这样无形中浪费了带宽,另外cookie还需要指定作用域,不可以跨域调用。
除此之外,Web Storage拥有setItem,getItem,removeItem,clear等方法,不像cookie需要前端开发者自己封装 setCookie,getCookie。但是Cookie也是不可以或缺的:Cookie的作用是与服务器进行交互,作为HTTP规范的一部分而存在 ,而Web Storage仅仅是为了在本地“存储”数据而生。
8、手写数组快速排序
关于快排算法的详细说明,可以参考阮一峰老师的文章快速排序
“快速排序”的思想很简单,整个排序过程只需要三步:
(1)在数据集之中,选择一个元素作为”基准”(pivot)。
(2)所有小于”基准”的元素,都移到”基准”的左边;所有大于”基准”的元素,都移到”基准”的右边。
(3)对”基准”左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。
9、统计字符串”aaaabbbccccddfgh”中字母个数或统计最多字母数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
var str = "aaaabbbccccddfgh";
var obj = {};
for(var i=0;istr.length;i++){
var v = str.charAt(i);
if(obj[v] & obj[v].value == v){
obj[v].count = ++ obj[v].count;
}else{
obj[v] = {};
obj[v].count = 1;
obj[v].value = v;
}
}
for(key in obj){
document.write(obj[key].value +'='+obj[key].count+' '); // a=4 b=3 c=4 d=2 f=1 g=1 h=1
}
|
10、写一个function,清除字符串前后的空格。(兼容所有浏览器)
1
2
3
4
5
|
function trim(str) {
if (str & typeof str === "string") {
return str.replace(/(^s*)|(s*)$/g,""); //去除前后空白符
}
}
|
其他
1、一次完整的HTTP事务是怎样的一个过程?
基本流程:
a. 域名解析
b. 发起TCP的3次握手
c. 建立TCP连接后发起http请求
d. 服务器端响应http请求,浏览器得到html代码
e. 浏览器解析html代码,并请求html代码中的资源
f. 浏览器对页面进行渲染呈现给用户
2、对前端工程师这个职位你是怎么样理解的?
a. 前端是最贴近用户的程序员,前端的能力就是能让产品从 90分进化到 100 分,甚至更好
b. 参与项目,快速高质量完成实现效果图,精确到1px;
c. 与团队成员,UI设计,产品经理的沟通;
d. 做好的页面结构,页面重构和用户体验;
e. 处理hack,兼容、写出优美的代码格式;
f. 针对服务器的优化、拥抱最新前端技术。
JavaScript的类型转换
JavaScript是一种无类型语言,类型转换分为显式转换和隐式转换
隐式转换
通过运算符进行转换,在一些运算中,Javascript也会进行自动类型转换
显式转换
通过手动进行类型转换,Javascript提供了以下转型函数:
转换为数值类型:Number(mix)、parseInt(string,radix)、parseFloat(string)
转换为字符串类型:toString(radix)、String(mix)
转换为布尔类型:Boolean(mix)
JavaScript的原型与继承
Js所有的函数都有一个prototype属性,这个属性引用了一个对象,简称原型,javascript中的继承是通过原型链来体现的,访问一个对象的属性时,先在基本属性中查找,如果没有,再沿着__proto__这条链向上找,这就是原型链。
B.prototype = new A();,此时B.prototype.constructor就是构造对象A,随后使用B.prototype.constructor = B;将B原型的构造器重新指向B构造函数在进行原型继承后,要进行修正操作。
JavaScript的闭包
闭包函数类似于Java等OO语言中的getter和setter函数,即因为变量作用域的原因,在函数外部无法读取函数内的局部变量。闭包就是能够读取其他函数内部变量的函数。父对象的所有变量,对子对象都是可见的,反之则不成立。闭包就是将函数内部和函数外部连接起来的一座桥梁。
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。 闭包会在父函数外部,改变父函数内部变量的值。
HTTP中Get和Post
get是从服务器上获取数据,post是向服务器传送数据。
GET请求,请求的数据会附加在URL之后,以?分割URL和传输数据,多个参数用&连接。POST请求:POST请求会把请求的数据放置在HTTP请求包的包体中。
即GET请求的数据会暴露在地址栏中,而POST请求则不会。
对于GET,特定的浏览器和服务器对URL的长度有限制。因此,在使用GET请求时,传输数据会受到URL长度的限制。数据量不能大于2KB
对于POST,由于不是URL传值,理论上是不会受限制的,但是实际上各个服务器会规定对POST提交数据大小进行限制,理论上,IIS4中最大量为80KB,IIS5中为100KB。
POST的安全性比GET的高。在FORM提交的时候,如果不指定Method,则默认为GET。
JavaScript事件绑定
IE的attachEvent()
elemObject.attachEvent("eventName", functionReference);
eventName 参数的值是表示事件名称的字符串,比如onclick(含on)。functionReference 参数是一个不带括号的函数引用
W3C DOM 的addEventListener()
nodeReference.addEventListener("eventType", listenerReference, captureFlag);
用 W3C DOM 规范中的行话来说,addEventListener() 方法为指定的结点注册了一个事件,表示该结点希望处理相应的事件。
第一个参数是一个声明事件类型的字符串,比如click,mousedown。(不含on)
第二个参数可以和早些时候描述过的函数引用同样对待。
第三个参数则是一个Boolean值,指明该结点是否以DOM中的捕捉模式来侦听事件。
JavaSciprt事件冒泡以及目标元素。
事件冒泡: 当一个元素上的事件被触发的时候,比如说鼠标点击了一个按钮,同样的事件将会在那个元素的所有祖先元素中被触发。这一过程被称为事件冒泡;这个事件从原始元素开始一直冒泡到DOM树的最上层。
目标元素: 任何一个事件的目标元素都是最开始的那个元素,并且它在我们的元素对象中以属性的形式出现。使用事件代理的话我们可以把事件处理器添加到一个元素上,等待一个事件从它的子级元素里冒泡上来,并且可以很方便地得知这个事件是从哪个元素开始的。
JavaScript图片轮播
1.全局变量等
定义初始index,图片总数
2.自动切换定时器处理
设置自动切换时间,自动切换后修改index
3.为左右箭头添加事件处理
滑入清除定时器,滑出则重置定时器,根据curIndex进行上/下一个图片处理
4.为右下角的li 按钮绑定事件处理
用css来隐藏img,用siblings而不是先hide全部在fadein,使用siblings来处理这样的情况速度会比较快。简单来讲siblings就是除开当前显示的这个以外的所有统计图片全部fadeOut
JavaScript网页前进和后退的代码
前进: history.forward();=history.go(1);
后退: history.back();=history.go(-1);
cookie和session的区别
1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用COOKIE。
4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
CSS 优先级法则
1.、 选择器都有一个权值,权值越大越优先,当权值相等时,后出现的样式表设置要优于先出现的样式表设置;
2、 创作者的规则高于浏览者:即网页编写者设置的CSS 样式的优先权高于浏览器所设置的样式;
3、继承的CSS 样式不如后来指定的CSS 样式,在同一组属性设置中标有“!important”规则的优先级最大
CSS选择器
浏览器兼容性问题
javascript兼容性问题
1、在标准的事件绑定中绑定事件的方法函数为 addEventListener,而IE使用的是attachEvent
2、事件处理中非常有用的event属性获得亦不相同,标准浏览器是作为参数带人,而ie是window.event方式获得,获得目标元素ie为e.srcElement 标准浏览器为e.target
3、然后在ie中是不能操作tr的innerHtml
4、然后ie日期函数处理与其它浏览器不大一致,比如: var year= new Date().getYear(); 在IE中会获得当前年,但是在firefox中则会获得当前年与1900的差值。
5、获得DOM节点的方法有所差异,其获得子节点方法不一致。
css兼容性问题
1、不同浏览器的标签默认的外补丁和内补丁不同,解决方案:用通配符*来设置各个标签的内外补丁是0。
2、div的垂直居中问题 vertical-align:middle; 将行距增加到和整个DIV一样高 line-height:200px; 然后插入文字
3、margin加倍的问题 设置为float的div在ie下设置的margin会加倍。这是一个ie6都存在的bug。解决方案是在这个div里面加上 display:inline;
Ajax是什么
ajax是异步的 JavaScript 和 XML。通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
Ajax的交互模型
1--启动 获取XMlHttpRequest对象
2--open 打开url通道,并设置异步传输
3--send 发送数据到服务器
4--服务器接受数据并处理,处理完成后返回结果
5--客户端接收服务器端返回
同步和异步的区别
同步:脚本会停留并等待服务器发送回复然后再继续
异步:脚本允许页面继续其进程并处理可能的回复
Ajax跨域的解决方法
如果在A网站中,我们希望使用Ajax来获得B网站中的特定内容,如果A网站与B网站不在同一个域中,那么就出现了跨域访问问题。
IE对于跨域访问的处理是,弹出警告框,提醒用户。如果用户将该网站纳入可信任网站,或者调低安全级别,那么这个问题IE就不会在提醒你。
FireFox等其它非微软的浏览器遇到跨域访问,则解决方案统一是拒绝访问
几个可行的方案:
1、Web代理的方式。
2、on-Demand方式
3、iframe方式。
4、用户本地转储方式
什么是PHP
超级文本预处理语言 Hypertext PreProcessor,是一种用来开发动态网站的服务器端脚本语言。
PHP字符串翻转
echo strrev($a);
PHP支持多继承吗?
不支持。PHP中只允许单继承,父类可以被一个子类用关键字“extends”继承。
echo(),print(),print_r()的区别
echo是PHP语句, print和print_r是函数,语句没有返回值,函数可以有返回值
echo输出一个或者多个字符串
print()只能打印出简单类型变量的值(如int,string)
print_r() 可以打印出复杂类型变量的值(如数组,对象)
在PHP中如何定义常量
使用define () 来定义常量,比如define (“Newconstant”, 30);
语句include和require的区别,如何避免多次包含同一文件
require是无条件包含,也就是如果一个流程里加入require,无论条件成立与否都会先执行require
include有返回值,而require没有(可能因为如此require的速度比include快) 包含文件不存在或者语法错误的时候require是致命的,include不是
使用 require_once() 和 include_once()可以避免多次包含同一文件以避免函数重定义,变量重新赋值等问题。 返回值和include() 相同。如果文件已被包含,本函数返回 TRUE。
HTTP协议1.0及1.1的区别,并简单说下HTTP协议
HTTP,超文本传输协议。它定义了浏览器和服务器的通信规则。HTTP协议是基于TCP/IP的TCP协议上,现在万维网使用的是HTTP1.1版本,其特点包括,C/S模式,请求简单(GET/POST/HEAD),灵活(可以传输任何类型的数据HTML、XML、JSON、自定义等),无连接(每次连接只处理一个请求,从发出请求到收到200状态为止断开连接),无状态。
HTTP协议主要包括,响应消息格式、请求消息格式、状态码知识点。
什么是MVC?
MVC,即Model(数据层),View(视图层),Controller(控制层)。
PHP中的MVC模型是一种有效将代码分成三层的管理办法,
Model表示着应用中的数据信息
View负责将应用中的数据信息展现出来
Controller控制着如何将数据信息读出。
Spring MVC工作原理
1. 客户端请求提交到DispatcherServlet
2. 由DispatcherServlet控制器查询一个或多个HandlerMapping,找到处理请求的Controller
3. DispatcherServlet将请求提交到Controller
4. Controller调用业务逻辑处理后,返回ModelAndView
5. DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图
6. 视图负责将结果显示到客户端
为什么要用Spring
1、Spring能很好的与各大框架进行集成
2、创建对象时,如果我们不用spring需要用工厂模式来创建,这个spring相当于工厂模式已经帮我们做了创建对象的功能(IOC、依赖注入)。
3、在用Hibernate的时候,如果不用spring每次都要写事务的提交代码,有了spring可以通过AOP帮助我们管理事务
4、面向切面编程(AOP)在要记录日志的时候添加一条记录后需要在数据里同时添加一条添加成功了或失败的记录,那么就可以用Spring的Aop来处理,虽然不用Aop也能做但是不用Spring的Aop就会写很多重复的代码。
Spring中的IOC和AOP
IOC依赖注入,即用接口编程,在程序中不出现new关键字,用接口来命名引用,然后通过某种方式把接口的某个实现类的实例注入到引用里,从而实现接口与具体实现类的松耦合。
AOP面向方面的编程,即,是一种编程技术,它允许程序员对横切关注点或横切典型的职责分界线的行为(例如日志和事务管理)进行模块化。AOP 的核心构造是方面,它将那些影响多个类的行为封装到可重用的模块中。
Spring bean生命周期
实例化——填充属性——
调用BeanNameAware的setBeanName()方法
调用BeanFactoryAware的setBeanFactory()方法
调用ApplicationContextAwar的setApplicationContext()方法
调用BeanPostprocessore的预初始化方法
调用InitialzingBean的afterPropertiesSet()方法
调用定制的初始化方法——调用Beanprocessors的后初始化方法——
bean可以使用——容器关闭——
调用DisposableBean的destroy()方法——
调用定制的销毁方法——结束
1. BeanFactoyPostProcessor实例化
2. Bean实例化,然后通过某些BeanFactoyPostProcessor来进行依赖注入
3. BeanPostProcessor的调用.Spring内置的BeanPostProcessor负责调用Bean实现的接口: BeanNameAware, BeanFactoryAware, ApplicationContextAware等等,等这些内置的BeanPostProcessor调用完后才会调用自己配置的BeanPostProcessor
4. Bean销毁阶段
SSH整合
SSH:Struts(表示层)+Hibernate(持久层)+Spring(业务层)
Struts是一个表示层框架,主要作用是界面展示,接收请求,分发请求。
Hibernate是一个持久层框架,它只负责与关系数据库的操作。
Spring是一个业务层框架,是一个整合的框架,能够很好地黏合表示层与持久层。
Spring的事务管理
事务就是对一系列的数据库操作进行统一的提交或回滚操作,如果插入成功,那么一起成功,如果中间有一条出现异常,那么回滚之前的所有操作。这样可以防止出现脏数据,防止数据库数据出现问题。
开发中为了避免这种情况一般都会进行事务管理。Spring中也有自己的事务管理机制,一般是使用TransactionMananger进行管理,可以通过Spring的注入来完成此功能。
数据库连接池
开源数据库连接池主要有c3p0、dbcp、proxool三种
DBCP是Apache上的一个 java连接池项目,也是 tomcat使用的连接池组件。由于建立数据库连接是一个非常耗时耗资源的行为,所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完后再放回去。dbcp没有自动的去回收空闲连接的功能。
各种排序算法的比较
二叉树
1.在二叉树的第I层上至多有2i-1个结点。
2.深度为k的二叉树至多有2k-1个结点(k>=1)
3.在任意一个二叉树中,度为0的结点总是比度为2的结点多一个;
4.具有n 个结点的二叉树,其深度至少为[log2n]+1。
B树平衡多路查找树
1.所有非叶子结点至多拥有两个儿子(Left和Right);
2.所有结点存储一个关键字;
3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树;
4.所有的叶子结点都位于同一层。
搜索:从根结点开始,如果查询的关键字与结点的关键字相等,那么就命中;
否则,如果查询关键字比结点关键字小,就进入左儿子;如果比结点关键字大,就进入
右儿子
Dijkstra 算法
在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短值。
把顶点集合V分成两组:
1.S:已求出的顶点的集合(初始时只含有源点V0)
2.V-S=T:尚未确定的顶点集合
将T中顶点按递增的次序加入到S中,保证:
1.从源点V0到S中其他各顶点的长度都不大于从V0到T中任何顶点的最短路径长度
2.每个顶点对应一个距离值
html
- 标签的定义与用法
声明必须是 HTML 文档的第一行,位于 标签之前。
声明不是 HTML 标签;它是指示 web 浏览器关于页面使用哪个 HTML 版本进行编写的指令。
是HTML5的声明,所有的浏览器都支持它,对大小写不敏感,没有结束标签。
- 块级元素和行内元素有哪些?
块级元素:
转载于:https://www.cnblogs.com/29boke/p/5648258.html