@LiTAOo
2018-07-28T02:52:34.000000Z
字数 42650
阅读 2601
html
mdn
学习笔记
目录
HTML元素结构
块级元素(block)和内联元素(inline)的区别
块级元素:与之前的内容通过另起一行的方式进行分隔,且元素后的内容也会在新的一行显示,从视觉上看来,块级元素独占一个区域,常见的元素包括<h>
、<a>
、<p>
、<ol>
、<ul>
、<div>
等。
内联元素:通常嵌套在块级元素内部,用来修饰文章的部分内容,内联元素的使用不会改变文章的排版结构(不会另起一行显示),常见的元素包括<span>
、<strong>
、<em>
等。
元素属性
元素属性满足要求:
space
。=
。"value"
。布尔型属性
<input type="text" disabled="disabled">
为了简便也可以写成:
<input type="text" disabled>
HTML文档基本结构
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My test page</title>
</head>
<body>
<p>This is my page</p>
</body>
</html>
HTML中的空白
在HTML文档中,无论使用多少空格(缩进),HTML解析器都会降为一个空格,如下面两种情况对于HTML解析器来说是等价的:
<p>Dogs are silly.</p>
<p>Dogs are
silly.</p>
频繁在代码中使用空格和缩进的目的主要是为了代码的可读性,如果真想出于显示效果的目的使用空格和换行,可以使用
和<br>
;在代码的排版上,通常子元素最好相对于父元素缩进2个空格。
HTML符号实体
在HTML中,<
、>
、'
、"
、&
都是特殊符号,它们是HTML语法的一部分,但如果我们真的需要其作为符号自身而不是语法的一部分时,我们需要使用其在HTML中的实体表示方法:
字符 | 字符表示 |
---|---|
< |
< |
> |
> |
' |
' |
" |
" |
& |
& |
空格 |
|
更多HTML符号实体可参考:appropriate entity references.
HTML注释
<!-- 这是一条注释 -->
head是指在HTML文档中处于<head>
到</head>
之间的部分,此处将包含常见的位于head中的元素:
<title>
元素
如果在head中添加一个<title>
元素,如:
<title><title> element</title>
则其作用主要有如下三个方面:
1.当加载HTML文件时,其内容显示在浏览器的标签栏。
2.当收藏网页时,其内容将会作为默认的书签内容。
3.当使用搜索引擎搜索时,会作为网页的标题名。
(注:此处<title>
的内容是"MDN Web Docs")
<meta>
元素
<meta>
元素的作用主要有:
指定HTML文档的字符编码。
<meta charset="utf-8">
为网页添加描述信息,主要用于浏览器搜索。
<meta name="author" content="Chris Mills">
<meta name="description" content="The Mozilla Developer Network (MDN) provides
information about Open Web technologies including HTML, CSS, and APIs for both
Web sites and HTML5 Apps. It also documents Mozilla products, like Firefox OS.">
其效果为:
其他类型的<meta>
。
如下所示:
<meta property="og:image" content="https://developer.cdn.mozilla.net/static/img/opengraph-logo.dc4e08e2f6af.png">
<meta property="og:description" content="The Mozilla Developer Network (MDN) provides
information about Open Web technologies including HTML, CSS, and APIs for both Web sites
and HTML5 Apps. It also documents Mozilla products, like Firefox OS.">
<meta property="og:title" content="Mozilla Developer Network">
这样的<meta>
被称为专有metadata协议,主要是一些社交网站创造的用来为用户提供更加详细的信息;如Open Graph Data则用于facebook,其作用是当在fackbook上链接MDN的网站时,会出现这样的效果:
为网站添加自定义图标
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
产生的效果为:
链接CSS文件和JavaScript文件
<link rel="stylesheet" href="my-css-file.css">
<script src="my-js-file.js"></script>
<script>
元素可以放在head下,但更好的选择是放在</body>
标签之前,这样可以确保在应用JacaScript文件之前,所有的HTML内容都被读取了(如果JacaScript试图获取一个目前为止不存在的元素则浏览器会产生错误),
如果不想引用外部的JavaScript文件,那么也可以把内容直接写在<script>
和</script>
之间。
设置网页内容采用的语言
如:
<html lang="en-US">
这里的作用主要有:
你也可以在HTML文档的子部分单独设置语言类型,如:
<p>Japanese example: <span lang="jp">ご飯が熱い。</span>.</p>
<h>
元素使用注意事项
<h1>
。<h1>
~<h6>
。<h>
的使用不要超过<h3>
。搜索引擎将会把文章的headings内容(<h>
)作为搜索的关键词,因此为内容取一个恰当的标题可以提高网页在搜索结果上的排名。
在使用元素时,应该充分考虑元素本身的语义是否符合逻辑,而不是出于显示效果的目的去使用该元素;如<h>
元素的语义是标题,而不应该出于使文本字体变大加粗的目的去使用该元素。另<span>
元素是无语义的。
<i>
、<b>
的使用
<i>
和<b>
元素本来是无语义的,其作用是仅仅是为了使得文本内容倾斜或加粗而不为其添加强调的语义。当CSS还不存在或被浏览器良好支持以前,通常使用这两个元素来为文本内容添加倾斜和加粗的效果,但如今,这两个元素已经失去了存在的意义。
为此,HTML5重新定义了这两个元素的意义,为其增添了语义。现在,通常使用<i>
来表示科学名词或外国文字:
<!-- scientific names -->
<p>
The Ruby-throated Hummingbird (<i>Archilochus colubris</i>)
is the most common hummingbird in Eastern North America.
</p>
<!-- foreign words -->
<p>
The menu was a sea of exotic words like <i lang="uk-latn">vatrushka</i>,
<i lang="id">nasi goreng</i> and <i lang="fr">soupe à l'oignon</i>.
</p>
使用<b>
来表示关键字:
<ol>
<li>
<b>Slice</b> two pieces of bread off the loaf.
</li>
<li>
<b>Insert</b> a tomato slice and a leaf of lettuce between the slices of bread.
</li>
</ol>
link的一般结构
<p>I'm creating a link to
<a href="https://www.mozilla.org/en-US/"
title="The best place to find more information about Mozilla's
mission and how to contribute" target="_blank">the Mozilla homepage</a>.
</p>
说明:
<a>
元素可以将包含在<a>
和</a>
之间的本文内容转变为一个链接,当鼠标点击该链接时,就会跳转到其他的网页或相同网页的不同位置。href
属性用于表示链接的地址,既可以是绝对地址也可以是相对地址。title
属性作用是当鼠标停留在连接上时,会显示链接的描述信息。target
属性用来表示新的链接的打开方式,"_blank"指用浏览器新的标签页打开,默认值为"_self"指在当前标签页打开链接。因此,上述代码产生的结果为:
I'm creating a link to the Mozilla homepage
使用图片作为链接
<a href="https://www.mozilla.org/en-US/">
<img src="mozilla-image.png" alt="mozilla logo that links to the mozilla homepage">
</a>
绝对地址与相对地址
在介绍<a>
元素的属性href
时指出其属性值既可以是绝对地址也可以是相对地址,那么这两者使用的区别是怎么样的?
绝对地址:包含协议和域名的URL地址,如http://www.example.com/projects/index.html
,这表明链接的index.html
文件位于域名为www.example.com
的web服务器的projects目录下。绝对地址的特点是,与当前正在书写的HTML文件位置无关,只要给出了绝对地址,就可以产生正确的链接(链接文件在服务器上的位置不发生改变的情况下)。
相对地址:与绝对地址相对应,其使用的特点是待链接的文件与当前正在书写的HTML文件的位置息息相关,具体讲解如下:
假设我们正在电脑本地开发一个网站,我们把所有相关的文件都放在一个名为creating-hyperlinks
的文件目录下,其目录结构如下图所示:
- contacts.html
- index.html
- pdfs
peoject-brief.pdf- projects
index.html
其中,在根目录下,有contacts.html
和index.html
两个文件,另外还有pdfs
和projects
两个目录。在这两个目录下又分别包含project-brief.pdf
和index.html
两个文件(在不同的目录下允许具有相同名字的文件)。假设现在我们正在编写根目录下的index.html
文件,并且想通过链接的方式引用其他文件,这时有如下几种不同的情况:
链接文件与当前文件位于同一目录下:
当我们想链接到contacts.html
文件时,使用如下代码:
<p>Want to contact a specific staff member?
Find details on our <a href="contacts.html">contacts page</a>.</p>
链接文件位于与当前文件同级的目录下:
当我们想链接到projects
目录下的index.html
文件时,使用如下代码:
<p>Visit my <a href="projects/index.html">project homepage</a>.</p>
链接文件位于与当前文件的上一级目录同级的目录下:
此时比如想在projects/index.html
中链接pdfs/project-brief.pdf
文件,使用如下代码:
<p>A link to my <a href="../pdfs/project-brief.pdf">project brief</a>.</p>
链接到当前文件的不同部分
<a>
不仅可以链接到外部文件,也可以链接到当前文件的不同部分(元素),比如当点下链接,可以直接跳转到当前网页的相关内容处(如标题):
首先为需要链接的元素分配一个ID
属性,如:
<h2 id="Mailing_address">Mailing address</h2>
通过在地址后添加#
+ID
的方式进行链接:
<p>Want to write us a letter? Use our <a href="contacts.html#Mailing_address">mailing address</a>.</p>
如果链接的元素位于本文件内,那么可以省略前面的地址信息:
<p>The <a href="#Mailing_address">company mailing address</a> can be found at the bottom of this page.</p>
链接的最佳做法
给出明确且清晰的链接信息。
Good link text:Download Firefox
<p><a href="https://firefox.com/">
Download Firefox
</a></p>
Bad link text:Click here to download FireFox
<p><a href="https://firefox.com/">
Click here</a>to download Firefox</p>
其他的建议:
如果可能的话,尽量使用相对地址。
这种情况通常针对的是同一网站的不同网页之间的引用,由于各个文件之间的相对位置关系能够确定,这样做可以带来的好处主要是:
当链接的内容是非HTML(网页)资源时,最好给出明确的提示。
比如当链接的对象是需要下载的文件或音频或视频的时候,最好在链接内容信息中给出提示,否则可能会造成较差的用户体验,比如:
<p><a href="http://www.example.com/large-report.pdf">
Download the sales report (PDF, 10MB)
</a></p>
<p><a href="http://www.example.com/video-stream/" target="_blank">
Watch the video (stream opens in separate tab, HD quality)
</a></p>
<p><a href="http://www.example.com/car-game">
Play the car game (requires Flash)
</a></p>
当链接到需要下载的文件时,使用download
属性指定默认的文件下载名。
<a href="https://download.mozilla.org/?product=firefox-latest-ssl&os=win64&lang=en-US"
download="firefox-latest-64bit-installer.exe">
Download Latest Firefox for Windows (64-bit) (English, US)
</a>
E-mail Links
E-mail链接是指,当点下链接时,会自动弹出系统自带的邮箱服务进行邮件的编写和发送,示例如下:
<a href="mailto:nowhere@mozilla.org">Send email to nowhere</a>
其中,href
属性以mailto:
开头则表示该链接是一个邮箱链接,本例中nowhere@mozilla.org
指邮件的发送地址,注明该信息的意义是当点击链接弹出系统自带的邮箱服务时,邮件接收人一栏的信息会被自动填充。
因此,如果为了简便,可对href
直接设置为"mailto:"
为了添加更多信息,如下:
<a href="mailto:nowhere@mozilla.org?cc=name2@rapidtables.com&bcc=name3@rapidtables.com&subject=The%20subject%20of%20the%20email&body=The%20body%20of%20the%20email">
Send mail with cc, bcc, subject and body
</a>
其中cc
表示抄送人,bcc
表示暗抄送人,subject
表示邮件标题,body
表示邮件内容。其书写规范是:
,
分隔。?
分隔。&
分隔。描述列表
除了之前介绍的有序列表<ol>
和无需列表<ul>
,事实上还存在一种描述列表dl
(description lists),这种列表主要用来描述一系列事项以及它们对应的描述。如名词+定义,或者是问题+问答,如:
<dl>
<dt>soliloquy</dt>
<dd>In drama, where a character speaks to themselves, representing their inner thoughts or feelings and in the process relaying them to the audience (but not to other characters.)</dd>
<dt>monologue</dt>
<dd>In drama, where a character speaks their thoughts out loud to share them with the audience and any other characters present.</dd>
<dt>aside</dt>
<dd>In drama, where a character shares a comment only with the audience for humorous or dramatic effect. This is usually a feeling, thought, or piece of additional background information.</dd>
</dl>
其中,<dt>
(description term),<dd>
(description definition)。默认情况下浏览器的处理方式会将definition部分进行缩进:
soliloquy
In drama, where a character speaks to themselves, representing their inner thoughts or feelings and in the process relaying them to the audience (but not to other characters.)
monologue
In drama, where a character speaks their thoughts out loud to share them with the audience and any other characters present.
aside
In drama, where a character shares a comment only with the audience for humorous or dramatic effect. This is usually a feeling, thought or piece of additional background information.
同时,一个<dt>
可以具有多个<dd>
与之对应。
文本引用
文本引用包含区块引用和内联引用:
区块引用:当需要引用别人的一段文章或者大段诗歌时,可以使用区块引用元素<blockquote>
:
比如引用的段落是:
<p>The <strong>HTML <code><blockquote></code> Element</strong> (or <em>HTML Block
Quotation Element</em>) indicates that the enclosed text is an extended quotation.</p>
则在HTML中使用<blockquote>
元素引用的代码为:
<blockquote cite="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote">
<p>The <strong>HTML <code><blockquote></code> Element</strong> (or <em>HTML Block
Quotation Element</em>) indicates that the enclosed text is an extended quotation.</p>
</blockquote>
注意到<blockquote>
元素包含了一个属性cite
,用于表示引用出处的URL。
另浏览器默认针对块状引用的呈现方式表现为如同一个具有缩进的段落,通过缩进来向用户表示这是一个块状引用。
内联引用:当只需要在段落中引用一句话时,采用内联引用元素<q>
:
<p>The quote element — <code><q></code> — is <q cite="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q">intended
for short quotations that don't require paragraph breaks.</q></p>
内联引用的用法与区块引用类似,只是浏览器默认将内联引用的信息采用双引号""
包围。
使用<cite>
提供引文出处
在使用<blockquote>
和<q>
进行引用时,都给出了cite
属性来提供原文的URL,然而目前无论是浏览器还是屏幕阅读器都对该信息没有什么处理和利用,这样也就无法向用户提供相关的参考信息。为了解决这个问题,可以使用<cite>
元素来指明引用的内容出于什么文章标题、书名或作者,例如:
<p>Hello and welcome to my motivation page. As <cite>Confucius</cite> once said:</p>
<blockquote cite="http://www.brainyquote.com/quotes/authors/c/confucius.html">
<p>It does not matter how slowly you go as long as you do not stop.</p>
</blockquote>
<p>I also love the concept of positive thinking, and <q cite="http://www.affirmationsforpositivethinking.com/index.htm">The Need To Eliminate Negative Self Talk</q> (as mentioned in <cite>Affirmations for Positive Thinking</cite>.)</p>
浏览器默认采用斜体的方式来处理<cite>
元素内容,因此效果如下:
Hello and welcome to my motivation page. As Confucius once said:
xxxxxx
I also love the concept of positive thinking, and The Need To Eliminate Negative Self Talk (as mentioned in Affirmations for Positive Thinking.)
如果为了用户能有更好的使用体验,更好的方法是,将<cite>
元素及其内容作为链接的文本信息封装成一个链接,这样能方便用户直接获取来源而无需根据标题自行查找:
<p>Hello and welcome to my motivation page. As <a href="http://www.brainyquote.com/quotes/authors/c/confucius.html"><cite>Confucius</cite></a> once said:</p>
<p>I also love the concept of positive thinking, and <q cite="http://www.affirmationsforpositivethinking.com/index.htm">The Need To Eliminate Negative Self Talk</q> (as mentioned in <a href="http://www.affirmationsforpositivethinking.com/index.htm"><cite>Affirmations for Positive Thinking</cite></a>.)</p>
效果为:
Hello and welcome to my motivation page. As Confucius once said:
I also love the concept of positive thinking, and The Need To Eliminate Negative Self Talk (as mentioned in Affirmations for Positive Thinking.)
名词缩写
当文本内容中出现英文名词的缩写时,可以使用<abbr>
搭配title
属性来表示名词缩写,其中title
用于解释缩写的具体内容:
<p>We use <abbr title="Hypertext Markup Language">HTML</abbr> to structure our web documents.</p>
<p>I think <abbr title="Reverend">Rev.</abbr> Green did it in the kitchen with the chainsaw.</p>
名词或术语定义
当在文章中第一次出现某个术语或名词时,通常需要对其进行定义;在字典中,名词定义的格式一般为:
该方式属于较为正式的定义;在HTML中,通常使用一种非正式的定义,如:
HTML使用<dfn>
对关键字进行定义,需要注意的是,<dfn></dfn>
包围的对象是需要被定义的关键字,如下:
<p><dfn>Firefox</dfn> is the web browser created by the Mozilla Foundation.</p>
另外,在使用<dfn>
时,相当于隐式地定义了<dfn>
和包含<dfn>
的元素(如上面的<p>
)之间的关系,表示包含元素中的所有内容都是<dfn>
的定义描述部分。如果想要显式地定义<dfn>
的范围,则需要使用aria-describedby
属性,如下例:
<p>
<span id="ff">
<dfn aria-describedby="ff">Firefox</dfn>
is the web browser created by the Mozilla Foundation.
</span>
You can download it at <a href="http://www.mozilla.org">mozilla.org</a>
</p>
在上例中,"Firefox"的定义范围被显式地限定在了<span></span>
之间,而不是整个<p></p>
。
网站开发人员联系方式
使用<address>
元素来给出网站开发者的联系方式,如:
<address>
<p>Page written by <a href="../authors/chris-mills/">Chris Mills</a>.</p>
</address>
注:此处的<adress>
只能用于描述网站开发人员的联系信息,不能用于一般的地址标注。
上下标
上标使用<sup>
,下标使用<sub>
:
<p>My birthday is on the 25<sup>th</sup> of May 2001.</p>
<p>Caffeine's chemical formula is C<sub>8</sub>H<sub>10</sub>N<sub>4</sub>O<sub>2</sub>.</p>
<p>If x<sup>2</sup> is 9, x must equal 3 or -3.</p>
代码引用
<code>
元素进行代码的标注。<pre>
包围住<code>
。<var>
在文本中指代代码中的变量名。<kbd>
在文本中指代键盘上的按键或输入。<samp>
在文本中指代计算机系统的输出信息。使用示例如下:
<pre><code>var para = document.querySelector('p');
para.onclick = function() {
alert('Owww, stop poking me!');
}</code></pre>
<p>You shouldn't use presentational elements like <code><font></code> and <code><center></code>.</p>
<p>In the above JavaScript example, <var>para</var> represents a paragraph element.</p>
<p>Select all the text with <kbd>Ctrl</kbd>/<kbd>Cmd</kbd> + <kbd>A</kbd>.</p>
<pre>$ <kbd>ping mozilla.org</kbd>
<samp>PING mozilla.org (63.245.215.20): 56 data bytes
64 bytes from 63.245.215.20: icmp_seq=0 ttl=40 time=158.233 ms</samp></pre>
日期和时间
使用<time>
元素对时间和日期进行标注,根据不同情况的时间表示如下:
<!-- Standard simple date -->
<time datetime="2016-01-20">20 January 2016</time>
<!-- Just year and month -->
<time datetime="2016-01">January 2016</time>
<!-- Just month and day -->
<time datetime="01-20">20 January</time>
<!-- Just time, hours and minutes -->
<time datetime="19:30">19:30</time>
<!-- You can do seconds and milliseconds too! -->
<time datetime="19:30:01.856">19:30:01.856</time>
<!-- Date and time -->
<time datetime="2016-01-20T19:30">7.30pm, 20 January 2016</time>
<!-- Date and time with timezone offset-->
<time datetime="2016-01-20T19:30+01:00">7.30pm, 20 January 2016 is 8.30pm in France</time>
<!-- Calling out a specific week number-->
<time datetime="2016-W04">The fourth week of 2016</time>
在使用HTML标记语言构建网页时,不仅有一些单独的元素(如<p>
、<img>
等)可以表示不同的内容信息,也存在一些板块元素(如标题、导航栏、主要内容区域、侧边栏、页脚等)帮助你从宏观地角度出发划分整个网页的大致结构,从而使得开发更加便捷和具有逻辑性。
网页的一般结构
<h1>
),该标题可能与网页具体内容并无太多关联,更多地只是起到对网页内容做大致描述的作用。具体到实际应用,如果网页是某大学的官方网页,则头部可能是“xxx大学”并伴随该大学的校徽logo;如果网页是某新闻网页,则头部可能是"xxx新闻网"及其logo。综上,一个简单的网页结构可能是这样的:
使用HTML板块元素描述网页结构
既然已经了解网页的大致结构,那么如何使用HTML元素来描述各个网页的板块呢?
<header>
。<nav>
。<main>
,其内部的子部分通常使用<article>
、<section>
、<div>
等元素表示。<aside>
,通常放在<main>
中。<footer>
。因此,如上网页的HTML代码可以表示为:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My page title</title>
<link href="https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300|Sonsie+One" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="style.css">
<!-- the below three lines are a fix to get HTML5 semantic elements working in old versions of Internet Explorer-->
<!--[if lt IE 9]>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<!-- Here is our main header that is used across all the pages of our website -->
<header>
<h1>Header</h1>
</header>
<nav>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">Our team</a></li>
<li><a href="#">Projects</a></li>
<li><a href="#">Contact</a></li>
</ul>
<!-- A Search form is another commmon non-linear way to navigate through a website. -->
<form>
<input type="search" name="q" placeholder="Search query">
<input type="submit" value="Go!">
</form>
</nav>
<!-- Here is our page's main content -->
<main>
<!-- It contains an article -->
<article>
<h2>Article heading</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Donec a diam lectus. Set sit amet ipsum mauris. Maecenas congue ligula as quam viverra nec consectetur ant hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur.</p>
<h3>subsection</h3>
<p>Donec ut librero sed accu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor.</p>
<p>Pelientesque auctor nisi id magna consequat sagittis. Curabitur dapibus, enim sit amet elit pharetra tincidunt feugiat nist imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros.</p>
<h3>Another subsection</h3>
<p>Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum soclis natoque penatibus et manis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.</p>
<p>Vivamus fermentum semper porta. Nunc diam velit, adipscing ut tristique vitae sagittis vel odio. Maecenas convallis ullamcorper ultricied. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, is fringille sem nunc vet mi.</p>
</article>
<!-- the aside content can also be nested within the main content -->
<aside>
<h2>Related</h2>
<ul>
<li><a href="#">Oh I do like to be beside the seaside</a></li>
<li><a href="#">Oh I do like to be beside the sea</a></li>
<li><a href="#">Although in the North of England</a></li>
<li><a href="#">It never stops raining</a></li>
<li><a href="#">Oh well...</a></li>
</ul>
</aside>
</main>
<!-- And here is our main footer that is used across all the pages of our website -->
<footer>
<p>©Copyright 2050 by nobody. All rights reversed.</p>
</footer>
</body>
</html>
元素使用备注:
<main>
用来显示此页面独有的内容(如导航栏和页脚不是独有内容,每个页面都可以使用相同的导航栏和页脚),在一个页面中只使用一次<main>
,直接放在<body>
中,且最好不要把它嵌套在其它元素内。<article>
顾名思义,用来描述<main>
中的文本信息。<section>
与<article>
类型,<section>
偏向用于把一部分内容组合起来,形成一个功能独立的部分(如一个迷你地图,一篇文章的一个章节),一般比较好的<section>
使用是在其内部以标题作为开始部分。<header>
代表一组介绍性的内容(可能不只单独一个标题),如果它是<body>
的子元素,则它定义了整个网页的头部,如果它是<article>
或<section>
的子元素,则它只是定义了对应区域的头部(注意与标题区分开)。无语义元素
当你想要用CSS或JavaScript单独渲染网页部分内容,而又不想引入额外语义时,这时可以采用无语义元素完成该功能。其中<span>
是内联无语义元素,<div>
是块级无语义元素。
换行和水平线
换行:<br>
。
水平线:<hr>
。
使用W3C Markup Validation Service进行HTML语法检查,支持三种格式的输入:
使用<img>
元素即可在网页中嵌入图片,但有几点需要注意:
<img>
元素时,添加上alt属性,它的内容和图片所传递的信息等价,当图片无法正常显示时发挥作用。<figure>
搭配<figcaption>
为图片添加说明信息(图题等),而不是使用title属性;类似的应用还可以是视频、音频、表格等。在网页中载入视频
使用<video>
元素载入的示例如下:
<video src="rabbit320.webm" controls>
<p>Your browser doesn't support HTML5 video. Here is a <a href="rabbit320.webm">link to the video</a> instead.</p>
</video>
使用说明:
为载入的视频准备多种不同的格式
由于不同的浏览器具有不同的视频/音频解码器,所以不同的浏览器可能只支持特定格式的视频/音频。
类似于MP4、WebM格式被称为容器格式,它们由不同格式的音频轨道和视频轨道以及一系列元数据构成,例如:
为了将不同格式的视频提供给<video>
元素,可以使用如下代码:
<video controls>
<source src="rabbit320.mp4" type="video/mp4">
<source src="rabbit320.webm" type="video/webm">
<p>Your browser doesn't support HTML5 video. Here is a <a href="rabbit320.mp4">link to the video</a> instead.</p>
</video>
<source>
元素取代<video>
中的src
属性,并将其移入到<source>
中。在这种情况下,浏览器会按顺序逐一从上到下选择出其支持的视频格式文件进行视频加载。<source>
元素都包含一个type
属性,这个属性的值以MIME形式对文件的类型进行指示,目的是告诉浏览器文件的类型信息从而使其快速挑选出符合格式要求的视频文件,并跳过不支持的文件格式。如果没有这个属性,那么浏览器只能逐一加载视频文件并尝试,这将耗费更多的时间和资源。video
元素的其它属性:
<video controls width="400" height="400"
autoplay loop muted
poster="poster.png">
<source src="rabbit320.mp4" type="video/mp4">
<source src="rabbit320.webm" type="video/webm">
<p>Your browser doesn't support HTML5 video. Here is a <a href="rabbit320.mp4">link to the video</a> instead.</p>
</video>
auto:当页面加载后,自动载入整个视频/音频。这个选项告诉服务端,用户需要马上加载视频/音频并进行流式播放,这在比如一些游戏场景等需要实时视频/音频的场景中会用到。
none:当页面加载后,不进行预加载。 这个值指的是用户不需要对这个视频/音频进行预先加载,这样可以减少网络流量,一个典型的情景是如果是一个具备播客功能的语音播客中,每一篇文章其实都有音频,但只有当用户确认打开这些音频收听时,才通过网络进行加载。否则,试想一下,这么多数量的音频同时进行预加载,速度是相当慢的。
在网页中载入音频
使用<audio>
元素嵌入视频,用法与<video>
类似:
<audio controls>
<source src="viper.mp3" type="audio/mp3">
<source src="viper.ogg" type="audio/ogg">
<p>Your browser doesn't support HTML5 audio. Here is a <a href="viper.mp3">link to the audio</a> instead.</p>
</audio>
音频格式一般提供mp3、ogg即可。
相比<video>
的使用,<audio>
存在一些小的差异:
为视频添加字幕(subtitle)或说明(caption)
通过WebVTT文本搭配<track>
元素嵌入到<video>
元素中可以实现为视频添加字幕或说明信息:
<video controls>
<source src="example.mp4" type="video/mp4">
<source src="example.webm" type="video/webm">
<track kind="subtitles" src="subtitles_en.vtt" srclang="en">
</video>
其中,典型的WebVTT文件内容如下:
WEBVTT
1
00:00:22.230 --> 00:00:24.606
This is the first subtitle.
2
00:00:30.739 --> 00:00:34.074
This is the second.
...
需要注意的是:
.vtt
结尾<track>
元素来链接vtt文件,且<track>
应放置在所有<source>
元素之后;并使用kind
属性指代文本内容的类型是subtitles、captions或是descriptions;使用srclang
指示文本内容的语言。其效果为:
视频和音频格式转换
使用格式工厂和狸窝视频转换器可以轻松地将视频格式转换为MP4、WebM,将音频格式转换成MP3、ogg等。
使用<iframe>
在网页内容中嵌入其它网页或第三方内容(视频、地图等),如:
嵌入youtube视频
点击嵌入按钮,得到相关<iframe>
代码
<iframe>
代码到自己的HTML文档中即可达到嵌入youtube视频的目的。<iframe>
常见属性及作用
如下<iframe>
代码:
<iframe src="https://developer.mozilla.org/en-US/docs/Glossary"
width="100%" height="500" frameborder="0"
allowfullscreen sandbox>
<p> <a href="https://developer.mozilla.org/en-US/docs/Glossary">
Fallback link for browsers that don't support iframes
</a> </p>
</iframe>
<frame>
使用的安全问题
什么是矢量图
常见的图片可以分为两类:光栅图和矢量图,其中,光栅图是我们最常使用的图片类型,其代表格式有Bitmap(.bmp)、PNG(.png),JEPG(.jpg)、GIF(.gif),而矢量图的代表格式为SVG(.svg)
光栅图和矢量图的区别是,当放大图片时,光栅图会产生一定程度的失真,而矢量图不会,可参考该示例vector-versus-raster.html:
什么是SVG
SVG即是一种图片格式也是一种语言。作为图片格式,它用来描述图片的类型(矢量图);作为语言,它可以用来设计和构造矢量图的具体信息,一个简单的示例如下:
<svg version="1.1"
baseProfile="full"
width="300" height="200"
xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" fill="black" />
<circle cx="150" cy="100" r="90" fill="blue" />
</svg>
其描述的矢量图形为:
想要构造一个简单的矢量图其代码非常简单,因为有诸如<rect>
、<circle>
等元素可以创造出不同的几何图形,但是如果图片的内容较为复杂或精致,则使用SVG语言来构造将变得十分困难,为此可以使用矢量图像编辑器Inkscape或Illustrator。
使用SVG的优势和劣势
基于以上内容,一般来说,光栅图像更适合用来显示那些复杂且精细的图片,如照片等。
SVG的跨浏览器支持问题
并非所有的浏览器都支持SVG(比较老的浏览器如IE8及以下、Android2.3及以下),为了兼顾这种情况,可以使用<img>
中的src属性指向PNG或JPG格式图片,而使用srcset属性指向SVG图片,如下所示:
<img src="equilateral.png" alt="triangle with equal sides" srcset="equilateral.svg">
在这种情况下,支持SVG的浏览器会加载SVG图片,而不支持SVG的老浏览器只会加载PNG或JPG版本的图片。
而针对CSS引用图片的例子如下:
background: url("fallback.png") no-repeat center;
background-image: url("image.svg");
background-size: contain;
如何在网页中嵌入SVG(矢量图)
通过<img>
嵌入
<img
src="equilateral.svg"
alt="triangle with all three sides equal"
height="87px"
width="100px" />
通过指定<img>
中的src属性值即可达到目的(因为SVG也是一种图片)。
通过<svg>
元素
<svg width="300" height="200">
<rect width="100%" height="100%" fill="green" />
</svg>
通过使用HTML提供的<svg>
元素可以将SVG文件中的代码包含进来。
通过<iframe>
元素
<iframe src="triangle.svg" width="500" height="500" sandbox>
<img src="triangle.png" alt="Triangle with three unequal sides" />
</iframe>
使用这种方法也可以嵌入SVG,不过这并不是一个好的办法。
为不同屏幕尺寸的设备提供不同分辨率大小的图片
在使用设备浏览网页时,由于设备的屏幕尺寸不一,应该为不同屏幕尺寸的设备提供不同分辨率大小的图片(显示的内容相同);为此可以通过使用srcset
和sizes
属性达到该目的:
<img srcset="elva-fairy-320w.jpg 320w,
elva-fairy-480w.jpg 480w,
elva-fairy-800w.jpg 800w"
sizes="(max-width: 320px) 280px,
(max-width: 480px) 440px,
800px"
src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy">
其示例网页可参考:responsive.html
其中,srcset
属性定义了一系列可供浏览器选择的图片,并且给出了图片的真实尺寸(320w代表宽度为320px,可以通过查看图片的属性来得到)。
sizes
则定义了一系列媒体条件,该条件的作用可以使得浏览器判断当前屏幕的尺寸处于什么状态下,并进行相应设置;如(max-width: 320px) 280px
的作用是:若当前屏幕或视口的宽度<=320px,则设置图片的插槽宽度为280px。另外可以注意到800px
没有媒体条件,其作用是,若之前的媒体条件都不满足,默认选中该项并将图片插槽宽度设置为800px(默认条件)。
关于媒体条件的匹配顺序:浏览器只会依次判断每个媒体条件并检查是否满足,若检查到符合的条件,则会忽略剩余的所有条件,因此如何指定媒体条件的编写顺序十分重要。
因此,浏览器根据不同设备加载图片的流程如下:
sizes
属性的媒体条件列表找出第一个符合的条件。srcset
属性列表找到真实尺寸与插槽宽度最接近的图片并加载。根据该流程,假设浏览器视口宽度或屏幕尺寸宽度为480px,则(max-width: 480px)
条件为真,得到相应的插槽宽度(440px);在srcset
中,由于480w与440px最接近,所以浏览器最终选取elva-fairy-480w.jpg
进行加载。
如果较老的浏览器不支持srcset
和sizes
的特性,则会忽略它们而选择src
属性中所指向的图片进行加载。
使用开发者工具确定插槽宽度
在上面的介绍中,提到了图片的插槽宽度,那么该宽度是如何选取的呢?为此可以使用浏览器自带的开发者工具来确定(以Firefox为例):
使用开发者工具查看浏览器对文件的加载情况
前面介绍了srcset
和sizes
的使用,那么如何检验浏览器是否真的在不同的视口宽度情况下加载了不同的图片文件呢?
需要注意的是,在进行测试时,则需要勾选Disable cache
选项(禁用缓存),否则浏览器可能会更偏向于加载已缓存的图片而不是最适合当前情况的图片。
将自己制作的网站托管到GitHub
为了能够使用开发者工具的network测试自己制作的网站是否正确,需要将其放到服务器上,而GitHub提供了一个免费的服务器功能,称为GitHub Pages.
为固定屏幕尺寸提供不同分辨率大小的图片
不同设备即使具有相同的屏幕尺寸,由于屏幕分辨率的不同(高分辨率屏幕/低分辨率屏幕),所需的图片分辨率大小也存在差异,为此,可以采用如下方式(假设屏幕尺寸为320px):
<img srcset="elva-fairy-320w.jpg,
elva-fairy-480w.jpg 1.5x,
elva-fairy-640w.jpg 2x"
src="elva-fairy-640w.jpg" alt="Elva dressed as a fairy">
如果设备的屏幕分辨率为标准或低分辨率,即1设备像素仅能用来表示1CSS像素,则"elva-fairy-320w.jpg
将被加载(默认为1x);但如果>=2设备像素能用来表示1CSS像素,则elva-fairy-640w.jpg 2x
将被加载。
使用图像裁剪来应对不同设备屏幕尺寸的情况
之前介绍了可以使用不同分辨率大小的图片来应对不同设备屏幕尺寸的情况,但如果对于有主体内容的图片(如人物),如果采用缩小图片的比例(分辨率)的方式来应对小屏幕情况的话,那么主体内容很可能会因缩小变得模糊而难以识别,为此,可以对原图像进行裁剪来降低其尺寸,并突出图片的主体部分,如下:
<picture>
<source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg">
<source media="(min-width: 800px)" srcset="elva-800w.jpg">
<img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva">
</picture>
原图片为:
经过裁剪后的图片为:
可参考示例:responsive-art-direction.html .
对于这类问题的处理,往往采用<picture>
元素,其中<source>
元素内的media
属性作用类似于之前介绍的sizes
属性,目的是给出一个媒体条件供浏览器判断并选择合适的图片,其匹配的方式与sizes
类似——选择第一个匹配的条件而忽略后续条件。
在任何情况下,都应该在<picture>
的末尾给出<img>
元素,该元素的作用有两个:
<img>
中的图片。<picture>
元素,则加载<img>
中的图片(兼容特性)。在使用<picture>
元素时,需要注意的是,只有当使用图像裁剪来应对不同设备屏幕尺寸的情况下才使用media
属性;当使用media
属性时,不要在<source>
中的sizes
属性值重复添加媒体条件。
为什么不能只用CSS或JavaScript来进行响应式图片的处理?
因为为了提升网页的加载速度,浏览器采用一种图片预加载的技术,该技术会使得浏览器解析器在加载CSS或JavaScript文件之前,先加载所有需要用到的图片(该技术可以节省20%的加载时间)。正是因为该技术的存在,使得只用CSS或JavaScript来进行响应式图片处理的方式变得笨拙。比如这样一个例子,在加载JavaScript文件文件前,已经加载了一个800px宽度的图片,在加载JavaScript文件后,检测到视口宽度只有480px,则此时再重新下载一个480px宽度的图片。这样的处理方式,与响应式图片处理的理念背道而驰,这也是为什么需要使用srcset
和sizes
属性来从一开始就确保浏览器能够加载正确尺寸的图片。
大胆尝试使用新兴的图片格式
目前有一些新兴的图片格式(如WebP和JPEG-2000),它们可以在保证含有较高图片质量的同时又不占用大量的存储空间(文件较小),只不过目前的众多浏览器对它们的支持是参差不齐的。
为了考虑到兼容性,可以使用<picture>
元素:
<picture>
<source type="image/svg+xml" srcset="pyramid.svg">
<source type="image/webp" srcset="pyramid.webp">
<img src="pyramid.png" alt="regular pyramid built from four equilateral triangles">
</picture>
如何简单快速地使用画图工具更改图片的分辨率大小
使用图片优化工具缩小图片文件大小
使用tinypng优化JPG和PNG格式图片,可以使得保证图片质量的同时尽可能地缩小文件大小,其使用效果如下:
HTML表格的创建
使用<table></table>
,在其内部可以使用<tr></tr>
(table row)表示一行的数据,<td></td>
(table data)表示一个单元格数据。如下代码:
<table>
<tr>
<td>Hi, I'm your first cell.</td>
<td>Hi, I'm your second cell.</td>
<td>Hi, I'm your third cell.</td>
<td>Hi, I'm your fourth cell.</td>
</tr>
<tr>
<td>Second row, first cell.</td>
<td>Cell 2.</td>
<td>Cell 3.</td>
<td>Cell 4.</td>
</tr>
</table>
其效果为:
Hi, I'm your first cell. | Hi, I'm your second cell. | Hi, I'm your third cell. | Hi, I'm your fourth cell. |
Second row, first cell. | Cell 2. | Cell 3. | Cell 4. |
为表格添加头部
使用<th></th>
即可声明一个表格头部,其使用方法与<td></td>
类似。如下代码:
<table>
<tr>
<td> </td>
<th scope="col">Knocky</th>
<th scope="col">Flor</th>
<th scope="col">Ella</th>
<th scope="col">Juan</th>
</tr>
<tr>
<th scope="row">Breed</th>
<td>Jack Russell</td>
<td>Poodle</td>
<td>Streetdog</td>
<td>Cocker Spaniel</td>
</tr>
<tr>
<th scope="row">Age</th>
<td>16</td>
<td>9</td>
<td>10</td>
<td>5</td>
</tr>
<tr>
<th scope="row">Owner</th>
<td>Mother-in-law</td>
<td>Me</td>
<td>Me</td>
<td>Sister-in-law</td>
</tr>
<tr>
<th scope="row">Eating Habits</th>
<td>Eats everyone's leftovers</td>
<td>Nibbles at food</td>
<td>Hearty eater</td>
<td>Will eat till he explodes</td>
</tr>
</table>
其显示效果为:
Knocky | Flor | Ella | Juan | |
---|---|---|---|---|
Breed | Jack Russell | Poodle | Streetdog | Cocker Spaniel |
Age | 16 | 9 | 10 | 5 |
Owner | Mother-in-law | Me | Me | Sister-in-law |
Eating Habits | Eats everyone's leftovers | Nibbles at food | Hearty eater | Will eat till he explodes |
如何扩展单元格的宽度和高度
在<th>
和<td>
元素中,支持colspan和rowspan属性,通过对其赋值如colspan="2"
可以使得当前单元格的宽度占据两个单元格的宽度;通过赋值rowspan="2"
可以使得当前单元格的高度占据两个单元格的高度。
如下代码:
<table>
<tr>
<th colspan="2">Animals</th>
</tr>
<tr>
<th colspan="2">Hippopotamus</th>
</tr>
<tr>
<th rowspan="2">Horse</th>
<td>Mare</td>
</tr>
<tr>
<td>Stallion</td>
</tr>
<tr>
<th colspan="2">Crocodile</th>
</tr>
<tr>
<th rowspan="2">Chicken</th>
<td>Cock</td>
</tr>
<tr>
<td>Rooster</td>
</tr>
</table>
其效果为:
Animals | |
---|---|
Hippopotamus | |
Horse | Mare |
Stallion | |
Crocodile | |
Chicken | Cock |
Rooster |
表格的常用样式设置
HTML表格提供了一种可以统一处理整列单元格的方法,与之相关的元素为<colgroup></colgroup>
和<col></col>
,使用方法为:在<table>
下添加<colgroup></colgroup>
,其中包含<col>
,每一个<col>
表示按照从左到右的顺序对一列单元格进行设置;如果有连续列使用同样的设置,可以添加span
属性。
假设有如下表格:
Mon | Tues | Wed | Thurs | Fri | Sat | Sun | |
---|---|---|---|---|---|---|---|
1st period | English | German | Dutch | ||||
2nd period | English | English | German | Dutch | |||
3rd period | German | German | Dutch | ||||
4th period | English | English | Dutch |
如果对其添加样式设置:
<colgroup>
<col span="2">
<col style="background-color:#97DB9A;">
<col style="width:42px;">
<col style="background-color:#97DB9A;">
<col style="background-color:#DCC48E; border:4px solid #C1437A;">
<col span="2" style="width:42px;">
</colgroup>
则最终呈现的效果为:
<caption></caption>
添加标题且直接放置到<table>
下即可。对表格进行结构化
表格的内容大致可以划分为头部、内容主体、脚部。为了分别对这些不同的内容进行标记,分别使用<thead>
、<tbody>
、<tfoot>
。一般来说,表格的头部为表格的第一行;表格的脚部一般是对各行数据的总结;其余的内容一般为内容主体。
例如如下表格:
关于头部、内容主体、脚部的划分代码如下:
<table>
<thead>
<tr>
<th>Purchase</th>
<th>Location</th>
<th>Date</th>
<th>Evaluation</th>
<th>Cost (€)</th>
</tr>
</thead>
<tfoot>
<tr>
<td colspan="4">SUM</td>
<td>118</td>
</tr>
</tfoot>
<tbody>
<tr>
<td>Haircut</td>
<td>Hairdresser</td>
<td>12/09</td>
<td>Great idea</td>
<td>30</td>
</tr>
<tr>
<td>Lasagna</td>
<td>Restaurant</td>
<td>12/09</td>
<td>Regrets</td>
<td>18</td>
</tr>
<tr>
<td>Shoes</td>
<td>Shoeshop</td>
<td>13/09</td>
<td>Big regrets</td>
<td>65</td>
</tr>
<tr>
<td>Toothpaste</td>
<td>Supermarket</td>
<td>13/09</td>
<td>Good</td>
<td>5</td>
</tr>
</tbody>
</table>
增强表格的可访问性(accessibility)
表格对普通用户很方便的原因是他们可以一眼就看出表内数据(单元格)与最上侧及最左侧头部之间的联系。但是对于具有视觉障碍的用户,他们只能依靠屏幕阅读器来阅读表格,为此需要增强表格的可访问来让这类的特殊的用户也能够容易地判断数据与头部之间的对应关系。
<th>
来指定表格中的头部 <th>
来声明表格的相应头部,这是后续处理的基础。使用scope
属性来指定头部的类型
如果与该头部相关的数据在表格中以列的方式排列,则该头部属于列头部;与之对应的是行头部;通过在<th>
中添加属性scope="row"
或scope="col"
来分别标记行头部和列头部;根据上图表格,则有:
<thead>
<tr>
<th scope="col">Purchase</th>
<th scope="col">Location</th>
<th scope="col">Date</th>
<th scope="col">Evaluation</th>
<th scope="col">Cost (€)</th>
</tr>
</thead>
对于行头部,有:
<tr>
<th scope="row">Haircut</th>
<td>Hairdresser</td>
<td>12/09</td>
<td>Great idea</td>
<td>30</td>
</tr>
另外,scope
可取的属性值还包括rowgroup
、colgroup
,这主要针对的是内层含有子头部的头部,如下图表格:
其中对于Clothed和Accessories头部的标记则需要使用scope="colgroup"
,对于Belguium和The Netherlands头部的标记使用scope="rowgroup"
。
使用id和headers属性
这种方法同样可以增强表格的可访问性,与使用scope
属性的方法并列,不过该方法给出了更加精确的头部与单元格之间的关系,但却需要更加繁琐地进行标记:
<th>
元素中添加id属性。<td>
元素中使用headers属性用于指明与之关联的头部id,如果id有多个,则id间用空格分隔。若采用这样的方法,上图表格的标记方式为:
<table>
<caption>Items Sold August 2016</caption>
<thead>
<tr>
<td> </td>
<td> </td>
<th colspan="3" id="clothes">Clothes</th>
<th colspan="2" id="accessories">Accessories</th>
</tr>
<tr>
<td> </td>
<td> </td>
<th id="trousers">Trousers</th>
<th id="skirts">Skirts</th>
<th id="dresses">Dresses</th>
<th id="bracelets">Bracelets</th>
<th id="rings">Rings</th>
</tr>
</thead>
<tbody>
<tr>
<th rowspan="3" id="belgium">Belgium</th>
<th id="antwerp">Antwerp</th>
<td headers="clothes trousers belgium antwerp">56</td>
<td headers="clothes skirts belgium antwerp">22</td>
<td headers="clothes dresses belgium antwerp">43</td>
<td headers="accessories bracelets belgium antwerp">72</td>
<td headers="accessories rings belgium antwerp">23</td>
</tr>
<tr>
<th id="gent">Gent</th>
<td headers="clothes trousers belgium gent">46</td>
<td headers="clothes skirts belgium gent">18</td>
<td headers="clothes dresses belgium gent">50</td>
<td headers="accessories bracelets belgium gent">61</td>
<td headers="accessories rings belgium gent">15</td>
</tr>
<tr>
<th id="brussels">Brussels</th>
<td headers="clothes trousers belgium brussels">51</td>
<td headers="clothes skirts belgium brussels">27</td>
<td headers="clothes dresses belgium brussels">38</td>
<td headers="accessories bracelets belgium brussels">69</td>
<td headers="accessories rings belgium brussels">28</td>
</tr>
<tr>
<th rowspan="2" id="netherlands">The Netherlands</th>
<th id="amsterdam">Amsterdam</th>
<td headers="clothes trousers netherlands amsterdam">89</td>
<td headers="clothes skirts netherlands amsterdam">34</td>
<td headers="clothes dresses netherlands amsterdam">69</td>
<td headers="accessories bracelets netherlands amsterdam">85</td>
<td headers="accessories rings netherlands amsterdam">38</td>
</tr>
<tr>
<th id="utrecht">Utrecht</th>
<td headers="clothes trousers netherlands utrecht">80</td>
<td headers="clothes skirts netherlands utrecht">12</td>
<td headers="clothes dresses netherlands utrecht">43</td>
<td headers="accessories bracelets netherlands utrecht">36</td>
<td headers="accessories rings netherlands utrecht">19</td>
</tr>
</tbody>
</table>
使用<form>
元素创建HTML表单
每一个HTML表单在创建时几乎都有这样的格式:
<form action="/my-handling-form-page" method="post">
</form>
<form>
元素中所有属性都是可选的,但在实际使用时,一般都需要添加action
和method
属性:
为了创建如下图所示的表单,可以使用如下HTML代码:
<form action="/my-handling-form-page" method="post">
<div>
<label for="name">Name:</label>
<input type="text" id="name" name="user_name">
</div>
<div>
<label for="mail">E-mail:</label>
<input type="email" id="mail" name="user_mail">
</div>
<div>
<label for="msg">Message:</label>
<textarea id="msg" name="user_message"></textarea>
</div>
</form>
其中,<div>
元素的使用是为了方便对表单各个组件构造样式(如果有必要的话);<lable>
元素的使用可以使得标签与表单组件一一对应起来,其方法为在<lable>
中使用for属性,该属性的值与需要绑定的表单组件的id相同。使用<lable>
最明显的效果是:鼠标只需点击标签名,便会定位到相应的表单组件上。
<input>
元素是表单的输入组件,通过type属性来使用不同的输入组件,若type="text"
则<input>
成为一个单行输入框;若为type="email"
那么<input>
会成为一个单行email输入框,并且具有检测输入是否有效的功能。
<textarea></textarea>
则用来产生一个多行的输入框。
若要使得输入框具有默认的输入信息,对于<input>
,需要使用value元素,其内容为输入框的默认输入信息:
<input type="text" value="by default this element is filled with this text" />
对于<textarea>
,在<textarea></textarea>
之间添加内容即可:
<textarea>by default this element is filled with this text</textarea>
<button>
元素
可以使用该元素来创建一个按钮:
<button type="submit">Send your message</button>
其中,type属性定义了当点击按钮后执行的操作,它有三个可取值:submit
、reset
、button
action
属性指定的服务器端。name
属性
在定义每个表单组件时,最好都加上name
属性,这是为了给当前组件命名,用于后端处理(后端根据此处定义的名字来处理对应的表单组件)。
<fieldset>
和<legend>
属性
<fieldset>
元素用于将需要设置为相同用途的各组件聚集起来,以方便设置样式或语义统一;而<legeng>
(嵌套在<fieldset>
中且刚好位于<fieldset>
标签下)则描述了<fieldset>
的用途。
许多辅助技术(如屏幕阅读器)在使用<lengend>
元素时,会将其看待成<fieldset>
内部定义的组件的标签的一部分。比如一些屏幕阅读器会在读出相应组件标签内容前,先读<lengend>
中的内容。
比如如下示例:
<form>
<fieldset>
<legend>Fruit juice size</legend>
<p>
<input type="radio" name="size" id="size_1" value="small">
<label for="size_1">Small</label>
</p>
<p>
<input type="radio" name="size" id="size_2" value="medium">
<label for="size_2">Medium</label>
</p>
<p>
<input type="radio" name="size" id="size_3" value="large">
<label for="size_3">Large</label>
</p>
</fieldset>
</form>
当使用屏幕阅读器阅读这个表单时,会依次读出"Fruit juice size small"、"Fruit juice size medium"、""Fruit juice size large"。
因此,<fieldset>
一般配合单选表单(radio)使用;每当定义单选表单时,确保使用<fieldset>
增强其可访问性。
此外,<fieldset>
还具有可以区分表单的用途,如上述表单,其效果为:
可以看到在表单周围添加了边框,并且<lengend>
中的内容作为了当前表单的标题,这是使用了<fieldset>
的结果。
<label>
元素的作用
增强表单组件的可访问性
当使用如下代码定义一个文本输入框:
<label for="name">Name:</label> <input type="text" id="name" name="user_name">
屏幕阅读器在阅读该表单组件时,会说出"Name,edit text",这对于视觉具有障碍的用户具有非常好的提示作用。但如果不使用<label>
元素,屏幕阅读器只能读出"Edit text blank",这对于用户来说没有任何帮助。
增强用户体验
前文提到过,当使用<lable>
元素与表单组件进行绑定后,用鼠标点击标签的内容即可选中表单组件:
这无疑是十分具有人性化的功能,因为对于单选框和复选框来说,可供点击的区域太小,通过这种方式可以扩大选中范围,从而增强用户体验。
使用常用的HTML结构元素来设计表单结构
使用<div>
或<p>
来包围表单组件及其标签;不过对于具有多个选项的复选框和单选按钮,经常使用<li>
来包围表单组件及其标签:
<div>
<label for="name">Name:</label>
<input type="text" id="name" name="user_name">
</div
<p>
<label for="pwd">
<span>Password: </span>
<strong><abbr title="required">*</abbr></strong>
</label>
<input type="password" id="pwd" name="password">
</p>
<ul>
<li>
<label for="title_1">
<input type="radio" name="title" id="title_1" value="M.">
<span>Mister</span>
</label>
</li>
<li>
<label for="title_2">
<input type="radio" name="title" id="title_2" value="Ms.">
<span>Miss</span>
</label>
</li>
</ul>
不仅仅可以在<form>
中使用 <fieldset>
来为表单组件设置标题或为表单组件进行分区,也可以使用<h1>
、<h2>
、<section>
元素达到相同的目的。
<fieldset>
元素来包围单选按钮(radio),当表单内具有功能不同的组件时,使用<section>
进行功能划分。关于表单结构的设计示例,可参考示例:running live,其代码为source.
参考The native form widgets.
不过值得注意的地方有:
当在表单元素中使用disable属性时,需要考虑到其继承的特性——若当前表单元素没有设置disable
属性,则它会继承包含它的容器元素(如<fieldset>
)的设置,若包含它的容器元素也没有设置diable
属性,当前表单元素才是使能的。
若不想要用户修改表单的输入值,可以使用readonly属性,若使用diable属性,该表单的数据不会被发送到服务器端。
若想要表单组件的数据被提交到服务器端,则元素应该包含name属性,否则不被发送。
<fieldset>
和<legend>
以及list一起使用。表单数据是如何被发送到服务器端的
目前的网站一般是基于客户端/服务器的架构构建的。其中,客户端一般为网络浏览器。在客户端和服务器之间,采用HTTP协议进行通信:当客户端需要访问服务器时,会向服务器发送一个HTTP请求;同样地,若服务器要回复该请求,也通过HTTP协议完成,其示意图如下:
对于HTML表单来说,其本质无非就是允许用户以一种简单的方式来配置HTTP的请求。用户所提交的表单信息,最终会被转变为HTTP请求的内容发送到服务器端。
如何定义数据发送的方式
在客户端方面,通过使用表单元素<form>
来定义发送数据的方式,其包含诸多属性可以用来配置HTTP请求。其中最重要的属性是action
和method
。
action属性定义了表单数据发送的目的地,其值必须是一个具有有效格式的URL地址,如假设表单数据在提交时需要发送到http://foo.com
,则有:
<form action="http://foo.com">
如果不提供action
属性,那么表单的数据将会提交到包含该表单元素的网页(即定义该表单的网页):
<form>
需要注意的是,在设置URL时,既可以使用HTTP,也可以使用HTTPS协议,它们的区别是:如果使用HTTPS,那么表单数据在传输前会得到加密,这提高了数据的安全性。相反,如果使用HTTP,则意味着不具备加密服务,众多浏览器会向用户发出安全警告。
method属性则定义了HTTP请求的发送方式,其中最常用的有GET
和POST
方法。
每当你想访问一个网页,浏览器都会向特定的URL(服务器地址)发送一个HTTP请求。HTTP请求包含两个部分:头部(header)和主体(body)。其中头部主要包含描述浏览器本身功能的一系列全局元数据,而主体则包含一系列供服务器用来处理特定请求的必要信息。
GET方法
GET
方法一般被浏览器用来向服务器索取特定的资源。使用GET
方法时,相当于浏览器告诉服务器“服务器你好,我需要这个资源”。正是由于这个原因,浏览器一般不需要向服务器提供特定的数据或内容。因此在使用该方法时,HTTP请求的body部分为空。但如果仍然想用这种方法提交表单数据,由于不使用body,所以数据的内容只能附加到URL的后面。
假设有如下表单示例:
<form action="http://foo.com" method="get">
<div>
<label for="say">What greeting do you want to say?</label>
<input name="say" id="say" value="Hi">
</div>
<div>
<label for="to">Who do you want to say it to?</label>
<input name="to" id="to" value="Mom">
</div>
<div>
<button>Send my greetings</button>
</div>
</form>
由于使用GET
方法,当表单提交后,将看到www.foo.com/?say=Hi&to=Mom
出现在浏览器的地址栏
表单提交的数据以一系列name/value对的形式附加到URL后,使用?
分隔URL和表单数据,并且使用&
分隔不同的name/value对。
在上例中,表单向目的地址提供了两组数据:
say
,其值为Hi
to
,其值为Mom
相应的HTTP请求信息如下:
GET /?say=Hi&to=Mom HTTP/1.1
Host: foo.com
POST
方法时,相当于浏览器告诉服务器“服务器你好,请你查看这个数据并向我返回一个合适的结果”;在这种情况下,服务器会用到浏览器提供的数据。如果表单数据以这种方式提交,那么数据信息将会被附加到HTTP请求的body中。
<form action="http://foo.com" method="post">
<div>
<label for="say">What greeting do you want to say?</label>
<input name="say" id="say" value="Hi">
</div>
<div>
<label for="to">Who do you want to say it to?</label>
<input name="to" id="to" value="Mom">
</div>
<div>
<button>Send my greetings</button>
</div>
</form>
当表单被提交后,不会有表单数据被附加到URL后,取而代之的是,数据将会出现在HTTP请求的body中,相应的HTTP请求如下所示:
POST / HTTP/1.1
Host: foo.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 13
say=Hi&to=Mom
如何使用开发者工具查看HTTP请求
以Chrome dev-tools为例,假设有网页POST method example,其步骤大致如下:
随后你将得到如图所示信息:
POST和GET方法使用注意事项
服务器如何检索浏览器发送的表单数据
无论使用哪种HTTP方法,传递到服务器的表单数据将会被解析成一系列的键/值对,并形成一个列表以供服务器进行处理。如何获取并处理这些数据,与服务器使用的平台和框架有关,常用的服务器框架有:
通过表单向服务器发送文件
通过表单向服务器发送文件是一个特殊情况,文件是二进制数据,而其余数据一般为文本数据。由于HTTP是一个文本传输协议,所以要发送文件需要做一些额外的处理;在这种情况下,需要用到<form>
的enctype属性。该属性用来指定表单生成的HTPP请求中的Content-type
的值,该值的作用用来告诉服务器发送数据的类型。默认情况下Content-type
的值为application/x-www-form-urlencoded
。
如果想要发送文件,则需要:
multipart/form-data
例如:
<form method="post" enctype="multipart/form-data">
<div>
<label for="file">Choose a file</label>
<input type="file" id="file" name="myFile">
</div>
<div>
<button>Send the file</button>
</div>
</form>
需要注意的是,许多服务器都会通过配置限制通过HTTP请求接收的文件大小。因此在设计提交文件的表单组件时,最好能对服务器能接收多大的文件做到心中有数。
表单数据有效性验证方式
对表单数据的有效性进行验证可以确保用户输入服务器所需的数据。一般来说,表单数据有效性验证方式可以分为:
一般情况下,网站开发者都会采取前后端验证相结合的方式对表单数据进行验证。
使用HTML内置表单验证
内置表单验证是HTML5的特性,通过使用一些表单元素的属性便可达到对数据进行简单验证的目的,如果一个表单组件被验证为有效,则:
:valid
CSS伪类匹配,此时可以利用CSS进行样式设置。当一个表单组件被验证为无效时,则:
:invalid
CSS伪类匹配,此时也同样可以利用CSS进行相应的样式处理。与表单验证相关的属性
required
当在一个表单元素中使用required
属性时,表示该数据不能省略,如下示例:
<form>
<label for="choose">Would you prefer a banana or cherry?</label>
<input id="choose" name="i_like" required>
<button>Submit</button>
</form>
同时根据之前体到的知识点,可以添加如下CSS代码使得表单元素在数据有效性不同时呈现不同的样式:
input:invalid {
border: 2px dashed red;
}
input:valid {
border: 2px solid black;
}
当数据无效时,其效果为:
当数据有效时,其效果为:
pattern
使用该属性则说明,表单数据的在输入上应该遵循某种特定的格式,否则将无法通过验证。通常pattern
与正则表达式结合在一起使用。
一些正则表达式的语法为:
a
——匹配一个字符a(不是b,不是aa等)。abc
——匹配三个字符,且顺序为a,b,c。a*
——匹配0个或多个a。a+
——匹配至少一个a。[^a]
——匹配一个不是a的字符。a|b
——匹配a或b。[abc]
——匹配a,b,c中的任意一个字符。[^abc]
——匹配除a,b,c的其它任意一个字符。[a-z]
——匹配字符a-z中的任意一个字符。[A-Z]
——匹配字符A-Z中的任意一个字符。[A-Za-z]
——匹配字符A-Z或a-z中的任意一个字符。a.c
——匹配a,任意字符,c。a{5}
——匹配5个a。a{5,7}
——匹配5-7个a。[ -]
——匹配空格或-。[0-9]
——匹配0-9之间的任意一个数字。[Ll].*k
——匹配一个L或l,0个或多个任意字符,1个k。关于pattern
的使用示例如下:
<form>
<label for="choose">Would you prefer a banana or a cherry?</label>
<input id="choose" name="i_like" required pattern="banana|cherry">
<button>Submit</button>
</form>
需要注意的是,一些<input>
元素类型不需要pattern
属性也可以完成数据验证的功能,如email
和url
。此外,<textarea>
元素不支持pattern
属性的使用。
min,max,minlength,maxlength
当需要限制表单数据的长度时,如输入类型为text
,则使用minlength
和maxlength
限制最小最大的长度;当输入类型为number
时,使用min
和max
来限制其取值区间,一般还可以配合step
一起使用,step
定义了数值增加或减少的步长。
关于针对特定HTML问题的处理方法,参考Use HTML to solve common problems.