介绍
前面的文章多次使用到了HTML(HyperText Markup Language,中文就是超文本标记语言)。这门语言可以使用任何的文本编辑器进行编写,写出的文档就是网页,只要将文件名以后缀 .html 结尾,浏览器就可以解释该文档,并以一定的格式呈现出来。
HTML是Web前端三剑客之一,主要是负责数据的结构、框架或骨架,表示哪些数据是标题啊、主体啊、导航啊、链接啊、表格啊、段落啊、图片啊、音频、代码啊等。简而言之,就是表示数据是什么。
核心思想
HTML的核心思想很简单,就是给你的信息打标记,举个例子:
<这是一篇文章>
<这是标题>XX爆炸性新闻</这是标题>
<这是段落>
某年某月某日,某某发生某事。。。
</这是段落>
<这是段落>
其他事情。。。
</这是段落>
</这是一篇文章>
尖括号 < > 及其里面的词就是标记或者标签,只不过HTML标准里面用的是英文单词,我这只是用中文的词来说明这个思想。
标记有开始标记和结束标记,结束标记里面多一个正斜杠,就是 </ > 。
真正的信息(就是要呈现给用户看的)就写在开始标记和结束标记之间,这就是标记的内容。有时候没有内容,开始标记和结束标记可以合二为一,变成 < /> ,就是把正斜杠写到右尖括号前面,或者省略正斜杠。
标记及其内容统一叫做元素,比如例子中的开始标记<文章>
和结束标记</文章>
及其之间的内容就是一个元素。可以看到元素可以嵌套,就是元素里面的内容可以再次包含元素,不过开始标记和结束标记要注意遥相呼应,事实上,编写的时候可以采用缩进来增加层次感且不易出错。
元素还有属性,属性可以有属性值,也可以没有,这些后面再讨论。这里要提到的是一个编写规范,不管是标记、属性还是值,习惯上都采用英文小写单词用连字符(就是短横线、减号)相连。表单中的需要发往Web服务器的数据可以使用后端的开发规范。
每一个元素都可以设置一个id
属性,其值必须在该网页中是唯一的。
目前HTML的版本是HTML5,大多数浏览器版本都支持大部分常用的特性。再次强调,HTML的主要思想就是给你的信息打标记,这些标记表示数据的结构、框架或骨架,就是语义,至于数据如何呈现(比如呈现在哪个位置,什么颜色、字体、背景等等)和动态行为是由CSS(层叠样式表,Cascading Style Sheets)和JavaScript来负责。它们都由浏览器来解释执行。
基本结构
HTML5的网页基本都有如下结构:
<!DOCTYPE html>
<html lang="zh-cmn-hans">
<head>
<meta charset="utf-8" />
<title>这里是网页的标题</title>
</head>
<body>
</body>
</html>
可以看到,基本结构就是由各种标记组成的,只不过标记使用的是英文单词,而且这些标记都是标准化了的,浏览器必须识别它们。这些标记也很语义化,基本上都是使用语义相对应的英文单词或缩写,这也是理所当然的,便于记忆和使用嘛。
基本结构里面包含以下几点:
- 第一行的DOCTYPE声明了本网页是HTML5网页,根据HTML网页的编写规范,基本上这个词是网页文档中唯一的大写单词;
<html>
元素:所有信息都包含在这个元素里面,没什么可说的,不过该元素有一个属性lang
,在这个网页中,我把它的值设置为zh-cmn-hans
,就是说本网页的语言是是简体中文,关于语言的编码,也是相当复杂,有专门的标准,这里暂且不说;<head>
元素:它必须是<html>
元素里面的第一个元素。它里面的信息除了下面的<title>
元素之外,在浏览器上都是不可见的,就是说用户在浏览器上不能直接看到里面的信息;<body>
元素:先说这个元素,这是<html>
元素里面的第二个元素。你可以在这个元素里面放置你的信息,包括文本、图像、音频、视频等,当然你又可以给这些信息打上合适的标记;<meta>
元素:它被包含在元素里面,而且它由于没有内容,所以开始标记和结束标记可以合二为一。它有一个属性charset
,非常重要,就是指示浏览器使用哪种字符编码(简单的理解就是编码规定了如何将二进制数据映射到我们人类可识别的文字和符号,简称字符,因为计算机只能识别0、1的二进制数据)来读取本文档。但是仅仅告诉浏览器使用何种字符编码还不行,网页文档本身在使用文本编辑器编写完保存的时候必须使用该字符编码来保存,通过网络传输的话那传输时也必须使用该字符编码来传输。就好像我给你写了一封信,信上指示你说要用英语来读这封信,但信的内容却是用中文写的,那么你还是不能读这封信。这里我使用了普遍采用的utf-8
这种字符编码,Web上基本都用这个,它能表示全球各个语言中的字符,而且占用字节数较少。字符编码也是比较复杂但很重要的内容,这里暂且不说;-
元素:就是浏览器里面展示该网页时在某个地方显示的该网页的标题,大多数是在浏览器的标签页上,见下图。这个元素其实也挺重要的,据说搜索引擎就会根据该元素的内容来分类、设置权重、建立索引等等,如果收藏某个网页的话而且还会显示在你的收藏夹里。所以得给每个网页取一个适当的标题。
OK,每个网页都有这个基本结构,剩下的就是往<body>
元素里面添加你的各种信息了。
文本信息
首先,我们可以向元素里面添加文本,毕竟文字在我们的生活中占据很重要的位置,特别是在古代。文字可以写成小说、剧本、新闻等等。添加文本很简单,直接在元素里面敲文字(各种语言都行)就可以了。
如果光是这样的话,那就谈不上说HTML负责数据的结构、框架或骨架了。不错,HTML还提供了很多标记来描述数据,这里先说一些常用的。
写文章的时候通常要为文章起标题,而且有文章的总标题,副标题,文章内容相关的放在同一个标题下,标题下又可能有若干个子标题,就类似文档的大纲似的,比如本网页总标题就是我的Java Web之路 - HTML(1)
,下面又有各级标题。所以,HTML提供了<h1>
、<h2>
、<h3>
、<h4>
、<h5>
、<h6>
这六个标记来说明标题的语义。我们试试给信息打上这些标记会是什么样子,先看代码:
<!DOCTYPE html>
<html lang="zh-cmn-hans">
<head>
<meta charset="utf-8" />
<title>这里是网页的标题</title>
</head>
<body>
<h1>这是一级标题</h1><h2>这是一级标题</h2>
<h3>这是一级标题</h3><h4>这是一级标题</h4>
<h5>这是一级标题</h5><h6>这是一级标题</h6>
</body>
</html>
我特地把这些信息两个一行来写,看看浏览器是怎么处理的:
可以看到,浏览器会把各级标题的字体大小显示的不太一样,一级标题最大,六级标题最小。大多数浏览器都会这么处理,那么问题来了,不是说HTML只负责信息的语义,不负责信息是如何展示的吗?话虽如此,给不同语义的信息来个默认的展示效果,不就省的我们还要再写信息如何展示的代码了嘛。这又再一次体现了契约优先(本质就是由默认值)的思想。这就是说我们还是可以修改这些各级标题是如何展示的,比如字体、颜色等等,这就要用到CSS了。
注意,浏览器可以关闭CSS和JavaScript,就是让这两个技术不起作用,从这个角度看,给标记设置默认的展示效果也有这方面的原因。
虽然标记有默认的展示效果,但我们一定不能为了获得这些类似的展示效果而强行给某些信息打上标记,而是应该使用CSS去获得这些展示效果。比如,不能为了加大字体就强行把不是标题的内容打上<h1>
标记,这应该交给CSS去做,是否打上<hn>
标记(n代表1、2、3、4、5、6)应该考虑该内容在语义上是否是标题!
第二点很重要的是,明明代码里面两个标题一行,为何浏览器展示的效果确是每个标题占一行?这是因为HTML规定了某些标记有个作用,浏览器遇到它就必须另起一行来展示,有这个作用的标记就叫块级标记,没有这个作用的就是行级标记(不知道是否可以这么划分,通常的划分方式是块级标记是里面可以嵌套其他标记的,行级标记是里面不可以嵌套其他标记的)。
事实上,HTML规定文本里面的格式(缩进、换行、多个连续的空格等等)都没用,浏览器会把这些格式压缩成一个空格。比如下面的代码实际展示的是一行:
<body>
这是第一段。。。
这是第二段。。。
这是第三段。。。
</body>
展示效果成了:
这是第一段。。。 这是第二段。。。 这是第三段。。。
除了表示标题的标记以外,还有其他很多作用于文本,甚至是整个语义上的布局的标记,下面仅仅使用一段代码来展示比较常用的标记,不做过多解释说明。
<!DOCTYPE html>
<html lang="zh-cmn-hans">
<head>
<meta charset="utf-8" />
<title>这里是网页的标题</title>
</head>
<body>
<header>
<h1>这里是网页的页眉,里面可以有导航</h1>
<nav>
这里是整个页面的导航按钮。。。
</nav>
</header>
<main><!-- 一个页面往往只有一个主体部分 -->
<article><!-- 这里也可以使用通用容器标记<div> -->
<header>
<h2>这里是主体的页眉,可以有主体的导航/目录、介绍等等</h2>
<nav>
这里是目录
</nav>
<p>这里是介绍</p>
</header>
<article>
<h2>这里是第一篇文章</h2>
<p>这里是段落一</p>
<p>这里是段落二</p>
<p>。。。</p>
</article>
<article>
<h2>这里是第二篇文章</h2>
<section>
<h3>这里是第二篇文章的第一部分</h3>
<p>与上面类似</p>
</section>
<section>
<h3>这里是第二篇文章的第二部分</h3>
<p>与上面类似</p>
</section>
</article>
</article>
</main>
<aside>
<h2>这里是附注,往往跟主体内容相关性没那么强,但比较独立,浏览器上通常会显示主体的两侧</h2>
</aside>
<footer>
<p>这里是整个页面的页脚,通常放一些版权声明、隐私政策之类的。</p>
</footer>
</body>
</html>
涉及到布局的标记有:
<header>
:页眉<main>
:主体<footer>
:页脚<aside>
:附注
涉及到文本内容的标记有:
<nav>
:导航<h1>
、…、<h6>
:标题<article>
:文章<section>
:区块,里面的内容通常有相似主题。<p>
:段落<div>
:通用语义,实在想不出什么语义,那就用它。
还有很多用来标记文本的,比如表示重要性的<strong>
、表示强调的<em>
、表示图的<figure>
和<figcaption>
、表示引用或参考的<cite>
、表示引述文本的<blockquote>
和<q>
、表示代码的<code>
等等。
以上这些标记在我们的Java Web开发中暂时用不到,所以都不讨论。
链接
链接可以说是网页的灵魂,正是它才能形成Web。表示信息是一个链接的标记是<a>
。下面举例:
<!DOCTYPE html>
<html lang="zh-cmn-hans">
<head>
<meta charset="utf-8" />
<title>这里是网页的标题</title>
</head>
<body>
<nav>
<ul>
<li><a href="https://www.youkuaiyun.com/">优快云</a></li>
<li><a href="https://www.baidu.com/">百度</a></li>
</ul>
</nav>
<p>
这里是某些文本。。。有些<a href="dir/file.html">东西</a>需要人们在另一个网页中查看
</p>
<nav>
<ul>
<li><a href="#question1">What is HTML?</a></li>
<li><a href="#question2">How does HTML work?</a></li>
</ul>
</nav>
<article>
<h1 id="question1">What is HTML?</h1>
<p>
HTML is ... <br /><br /><br /><br /><br /><br /><br /><br /><br />
<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
</p>
<h2 id="question2">How does HTML work?</h2>
<p>
HTML is explained by browser ...
</p>
</article>
<p></p>
</body>
</html>
在浏览器上呈现这样:
上面的例子中<ul>
标记表示是一个无序列表,<li>
表示是列表中的一项。我们将优快云
、百度
和东西
打上<a>
标记,表示它们都是一个链接,用鼠标点击它们可以看到指定的另一个网页。<br>
表示需要换行,这里用来模拟页面很长导致看不见question2
。
可以看到,浏览器为列表、链接都设置了默认的样式,鼠标移到链接上会变成手型。
链接必须要有一个href
属性,其值就是目标网页的URL,当然可以是本网站内部的其他网页,也可以是外部网站某个网页,甚至是本网页中的其他部分(需要使用元素的id
属性,如例子所示)。
表单
表单允许用户向Web服务器提交数据,而不是仅仅用浏览器向Web服务器索要网页。
最常用的表单应该要数登录表单了。用户通过输入用户名和密码,点击登录按钮向Web服务器发起登录请求。
表单使用标记<form>
,在<form>
添加供用户输入信息的其他内容,常用的有文本框、密码框、单选按钮、复选按钮、下拉列表选择框以及最后的提交按钮。我们先简单介绍文本框、密码框以及提交按钮,其他的以后再介绍。
先上代码:
<!DOCTYPE html>
<html lang="zh-cmn-hans">
<head>
<meta charset="utf-8" />
<title>这里是网页的标题</title>
</head>
<body>
<form method="post" action="login-success.html">
<label for="user-name">用户名:</label><input type="text" id="user-name" name="userName" />
<label for="password">密码:</label><input type="password" id="password" name="password" />
<input type="submit" value="登录"/>
</form>
</body>
</html>
再看看浏览器上的呈现:
第一点,从呈现上看,用户名和密码都是文本框,不过,密码的文本框会将输入信息屏蔽,<input>
标记使用type
属性来区分各类输入方式:text
是文本框、password
是密码框、radio
是单选按钮、checkbox
是复选按钮等。
其次,我为标记指定了id和name两个属性,id属性用于
而name
属性用于标识用户输入的该项数据,这样Web服务器才能根据该名字取出对应的数据,可以理解为Web服务器应用程序中的变量名,或者参数名。所以,name
属性的值通常遵循后端应用程序的开发规范,由于我们以后是使用Java Servlet技术作为后端应用的开发技术(还有PHP、Python、Go等技术),所以遵循Java的变量名命名规范(采用驼峰形式,比如userName
)。
通常,表单中的每一项输入都会有一个关联的<label>
元素,用于呈现,总不能光出现一个文本框在那吧,这样用户如何知道输入什么数据呢!它有一个for
属性,用来指定关联元素的id
。
提交按钮也是使用<input>
标记,type
属性值是submit
,还有一个value
属性,用来指定按钮上呈现的文字。
最后,回过头来看<form>
标记,它必须指定一个action
属性,它的值通常是后端应用中处理用户提交数据的一个程序的URL,比如可以是login.servlet
、login.jsp
、login.php
、login.asp
等等,后缀名通常表明了采用的后端应用开发技术。当然,我的例子里直接指定了一个HTML页面(login-success.html
,你需要创建这么一个页面,相信你已经知道怎么创建了!),相当于不处理用户提交的数据,一般不能这么做!
那么,用户提交的数据是如何提交到Web服务器的呢?答案当然就是HTTP啊,浏览器使用HTTP来向Web服务器请求网页,再用它来向Web服务器提交数据也就理所当然了啊。浏览器会将用户输入的信息封装成HTTP的报文格式,最后通过网卡发送出去。
在文章我的Java Web之路 - Web基础(2)提到过,HTTP报文里面含有HTTP方法,常用的有GET、POST等。<form>
标记的method
属性就是用于指定提交数据的HTTP方法。默认值是get
,但通常使用post
,一方面get
的语义就是获取而不是提交。另一方面get
会将参数直接暴露在浏览器的地址栏里面。最后get
提交的数据不能太大。
我们把上述代码中的元素的method属性值修改为get,保存,然后用浏览器打开,输入用户名和密码后点击提交,效果呈现如下:
可以看到,使用get
方法提交表单数据会在URL上附加上你的数据,同时也可以看到<input>
标记的name
属性值在这所起的作用,就是参数名的作用。
总结
到此为止,我们就先介绍这么多,我们来总结一下:
- 所谓大道至简,一项技术的核心思想往往很简单,HTML的核心思想就是给信息打标记;
- 一个网页就是一个HTML文档,它就只包含你的信息和标记两种内容;
- HTML负责的是数据的结构、框架或骨架,就是语义,至于数据如何呈现(比如呈现在哪个位置,什么颜色、字体、背景等等)和动态行为是由CSS(层叠样式表,Cascading Style Sheets)和JavaScript来负责;
- HTML、CSS和JavaScript都由浏览器来解释执行,所以叫前端三剑客;
- 既然有前端三剑客,那就有后端四剑客(Web服务器、数据库、缓存、消息队列),统称为七剑下天山;
- 给你的信息打标记时,一定只能考虑语义,寻找最符合语义的标记,而不要考虑标记的默认呈现效果,那只是契约优先思想的体现;
- 网页的语言和字符编码很重要,字符编码通常使用
utf-8
; - 浏览器会忽略你的信息的格式(缩进、换行等),应该使用标记或CSS来实现格式;
- 标记有块级标记和行级标记之分,浏览器遇到块级标记则另起一行展示;
- 链接是网页的灵魂,使用
<a>
标记创建链接,必须指定href
属性; - 表单用于向Web服务器提交数据,使用
<form>
标记创建表单,必须指定action
属性,通常指定method
属性值为post
比较安全且传输数据量较大; - 表单中的各项输入常用
<input>
标记实现,使用type
属性指定各类输入,如文本框、密码框、单选、复选等,通常要为它关联到一个<label>
元素,同时指定id
属性和name
属性,name
属性的值通常遵从后端技术的命名规范。